diff --git a/src/app/article/[slug]/page.tsx b/src/app/article/[slug]/page.tsx
new file mode 100644
index 0000000..e0db5b1
--- /dev/null
+++ b/src/app/article/[slug]/page.tsx
@@ -0,0 +1,34 @@
+"use client"
+import { ArrowLeftIcon } from "@heroicons/react/24/outline"
+import Link from "next/link"
+// page https://www.businessinsider.com/web3-music-platforms-blockchain-even-sound-iyk-streaming-services-artists-2023-9#:~:text=Web3%20music%20platforms%20are%20combining,and%20'create%20dope%20consumer%20experiences'&text=Web3%20music%20platforms%20are%20changing,and%20ways%20to%20reach%20fans.
+import React from "react"
+
+type Props = {
+ params: {
+ slug: string
+ }
+}
+
+const Page = ({ params }: Props) => {
+ // TODO: Explore based on the slug, we can also change the slug to be like the id or something the backend understands
+ // We can also pre-render the article from the backend
+ return (
+ <>
+
+
+
+ Go Back Home
+
+
+
+
+
+ >
+ )
+}
+
+export default Page
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 9ca6e12..b8916be 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -2,6 +2,8 @@ import type { Metadata } from "next"
import Image from "next/image"
import { Inter, Jaldi } from "next/font/google"
import "./globals.css"
+import Header from "@/components/LayoutHeader"
+import Footer from "@/components/LayoutFooter"
const inter = Inter({ subsets: ["latin"], variable: "--font-inter" })
const jaldi = Jaldi({
@@ -23,55 +25,12 @@ export default function RootLayout({
return (
-
+
{children}
+
)
}
-
-export const Header = () => {
- return (
-
-
-
-
-
-
-
- a Lume project
-
-
-
- )
-}
-
-const Web3NewsLogo = ({ className }: { className?: string }) => {
- return (
-
-
-
-
- )
-}
diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx
index 415f3ed..33b19c9 100644
--- a/src/app/search/page.tsx
+++ b/src/app/search/page.tsx
@@ -1,7 +1,7 @@
import React, { FormEvent } from "react"
import Link from "next/link"
import { ArrowLeftIcon } from "@heroicons/react/24/outline"
-import { formatDate } from "@/utils"
+import { formatDate, getResults } from "@/utils"
import SimplifiedSearchBar from "@/components/SimplifiedSearchBar"
type Props = {
@@ -16,17 +16,25 @@ const Page = async ({ searchParams }: Props) => {
return (
-
-
-
-
- Go Back Home
-
+
+
+
+
+
+ Go Back Home
+
+
{results.length > 0 && (
<>
{results.map((item) => (
-
@@ -34,7 +42,7 @@ const Page = async ({ searchParams }: Props) => {
{formatDate(item.timestamp)}
{item.title}
-
+
))}
@@ -47,27 +55,4 @@ const Page = async ({ searchParams }: Props) => {
)
}
-async function getResults({
- query
-}: {
- query?: string
-}): Promise {
- if (!query) return []
-
- return [
- {
- id: 1,
- timestamp: new Date(),
- title: "Mock Title 1",
- description: "Mock Description 1"
- },
- {
- id: 2,
- timestamp: new Date(),
- title: "Mock Title 2",
- description: "Mock Description 2"
- }
- ]
-}
-
export default Page
diff --git a/src/components/LayoutFooter.tsx b/src/components/LayoutFooter.tsx
new file mode 100644
index 0000000..17d55ee
--- /dev/null
+++ b/src/components/LayoutFooter.tsx
@@ -0,0 +1,13 @@
+import React from "react"
+
+type Props = {}
+
+const Footer = ({}: Props) => {
+return ()
+}
+
+export default Footer
\ No newline at end of file
diff --git a/src/components/LayoutHeader.tsx b/src/components/LayoutHeader.tsx
new file mode 100644
index 0000000..9e9ffc5
--- /dev/null
+++ b/src/components/LayoutHeader.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import Image from "next/image"
+
+type Props = {}
+
+export const Header = ({}: Props) => {
+ return (
+
+
+
+
+
+
+
+ a Lume project
+
+
+
+ )
+ }
+
+ const Web3NewsLogo = ({ className }: { className?: string }) => {
+ return (
+
+
+
+
+ )
+ }
+
+export default Header
\ No newline at end of file
diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx
index 6f657f6..2e11157 100644
--- a/src/components/SearchBar.tsx
+++ b/src/components/SearchBar.tsx
@@ -1,70 +1,70 @@
"use client"
-import React, { FormEvent, useCallback, useEffect, useRef, useState } from "react"
-import {
- ChevronDownIcon,
- ChevronRightIcon
-} from "@heroicons/react/24/outline" // Assuming usage of Heroicons for icons
+import React, {
+ FormEvent,
+ useCallback,
+ useEffect,
+ useRef,
+ useState
+} from "react"
+import { ChevronDownIcon, ChevronRightIcon } from "@heroicons/react/24/outline" // Assuming usage of Heroicons for icons
import { flushSync } from "react-dom"
import Link from "next/link"
import { usePathname, useSearchParams, useRouter } from "next/navigation"
-import { formatDate } from "@/utils"
+import { formatDate, getResults } from "@/utils"
type Props = {
variant: "default" | "simplified"
}
-const SearchBar = ({variant}: Props) => {
- const searchParams = useSearchParams();
- const router = useRouter();
- const pathname = usePathname();
- const [query, setQuery] = useState(searchParams.get("q") ?? "");
+const SearchBar = ({ variant }: Props) => {
+ const searchParams = useSearchParams()
+ const router = useRouter()
+ const pathname = usePathname()
+ const [query, setQuery] = useState(searchParams.get("q") ?? "")
const inputRef = useRef()
const [isLoading, setIsLoading] = useState(false)
const [activeInput, setActiveInput] = useState(true)
- const [results, setResults] = useState<
- SearchResult[]
- >([])
+ const [results, setResults] = useState([])
- const handleSearch = useCallback(async (event?: FormEvent) => {
- event?.preventDefault()
- setIsLoading(true)
- const newSearchParams = new URLSearchParams(searchParams)
+ const handleSearch = useCallback(
+ async (event?: FormEvent) => {
+ event?.preventDefault()
+ setIsLoading(true)
+ const newSearchParams = new URLSearchParams(searchParams)
- if(query) {
- newSearchParams.set('q', query)
- } else {
- newSearchParams.delete('q')
- }
-
- router.push(`${pathname}?${newSearchParams}`)
-
- // Perform search and update results state
- // Assume fetchResults is a function that fetches search results
- // const searchResults = await fetchResults(query);
- // Mock the search results
- const searchResults = [
- {
- id: 1,
- timestamp: new Date(),
- title: "Mock Title 1",
- description: "Mock Description 1"
- },
- {
- id: 2,
- timestamp: new Date(),
- title: "Mock Title 2",
- description: "Mock Description 2"
+ if (query) {
+ newSearchParams.set("q", query)
+ } else {
+ newSearchParams.delete("q")
}
+
+ router.push(`${pathname}?${newSearchParams}`)
+
+ // Perform search and update results state
+ // Assume fetchResults is a function that fetches search results
+ // const searchResults = await fetchResults(query);
+ // Mock the search results
+ const searchResults = await getResults({ query })
+
+ setResults(searchResults)
+ setIsLoading(false)
+ setActiveInput(false)
+ },
+ [
+ query,
+ setResults,
+ setIsLoading,
+ setActiveInput,
+ searchParams,
+ router,
+ pathname
]
- setResults(searchResults)
- setIsLoading(false)
- setActiveInput(false)
- }, [query, setResults, setIsLoading, setActiveInput, searchParams, router, pathname])
+ )
useEffect(() => {
- if(searchParams.get("q") && searchParams.get("q") !== "") {
- handleSearch();
+ if (searchParams.get("q") && searchParams.get("q") !== "") {
+ handleSearch()
}
}, [searchParams, handleSearch])
@@ -128,10 +128,10 @@ const SearchBar = ({variant}: Props) => {
{
- flushSync(() => {
- setActiveInput(true)
- })
- inputRef.current?.focus()
+ flushSync(() => {
+ setActiveInput(true)
+ })
+ inputRef.current?.focus()
}}
>
{'"'}
@@ -162,7 +162,8 @@ const SearchBar = ({variant}: Props) => {
<>
{results.map((item) => (
-
@@ -170,11 +171,12 @@ const SearchBar = ({variant}: Props) => {
{formatDate(item.timestamp)}
{item.title}
-
+
))}
- {results.length}+ search results for {query}
+ {results.length}+ search results for{" "}
+ {query}
diff --git a/src/types.d.ts b/src/types.d.ts
index b0fd0ff..4d63566 100644
--- a/src/types.d.ts
+++ b/src/types.d.ts
@@ -3,4 +3,5 @@ type SearchResult = {
timestamp: Date
title: string
description: string
+ slug: string
}
\ No newline at end of file
diff --git a/src/utils.ts b/src/utils.ts
index 18d455e..a6773ab 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -2,11 +2,36 @@ import { formatDistanceToNow } from "date-fns"
// Utility function to format dates
export const formatDate = (date: string | Date) => {
- const distance = formatDistanceToNow(new Date(date), { addSuffix: true })
- return distance
- .replace(/less than a minute?/, "<1m")
- .replace(/ minutes?/, "m")
- .replace(/ hours?/, "h")
- .replace(/ days?/, "d")
- .replace(/ weeks?/, "w")
- }
\ No newline at end of file
+ const distance = formatDistanceToNow(new Date(date), { addSuffix: true })
+ return distance
+ .replace(/less than a minute?/, "<1m")
+ .replace(/ minutes?/, "m")
+ .replace(/ hours?/, "h")
+ .replace(/ days?/, "d")
+ .replace(/ weeks?/, "w")
+}
+
+export async function getResults({
+ query
+}: {
+ query?: string
+}): Promise {
+ if (!query) return []
+
+ return [
+ {
+ id: 1,
+ timestamp: new Date(),
+ title: "Mock Title 1",
+ description: "Mock Description 1",
+ slug: "hello-world"
+ },
+ {
+ id: 2,
+ timestamp: new Date(),
+ title: "Mock Title 2",
+ description: "Mock Description 2",
+ slug: "hello-world-2"
+ }
+ ]
+}