diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index a2dc41ec..12563156 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -1,7 +1,7 @@
@import "tailwindcss";
:root {
- --background: #ffffff;
+ --background: white;
--foreground: #171717;
}
@@ -20,7 +20,7 @@
}
body {
- background: var(--background);
+ background: white;
color: var(--foreground);
font-family: Arial, Helvetica, sans-serif;
}
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index f7fa87eb..08027197 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
});
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: "Frontend Assessment",
+ description: "A simple product listing page with data fetching",
};
export default function RootLayout({
@@ -23,10 +23,8 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
-
-
+
+
{children}
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index e68abe6b..24057c13 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -1,103 +1,4 @@
-import Image from "next/image";
-
-export default function Home() {
- return (
-
-
-
-
- -
- Get started by editing{" "}
-
- src/app/page.tsx
-
- .
-
- -
- Save and see your changes instantly.
-
-
-
-
-
-
-
- );
+import Main from "../components/Main";
+export default async function Home() {
+ return ( );
}
diff --git a/frontend/src/components/card.tsx b/frontend/src/components/card.tsx
new file mode 100644
index 00000000..85381fab
--- /dev/null
+++ b/frontend/src/components/card.tsx
@@ -0,0 +1,13 @@
+
+export default function Card({productName, price, imageURL, onClick}) {
+ return (
+
+

+
{productName}
+
${price}
+
+ );
+}
diff --git a/frontend/src/components/main.tsx b/frontend/src/components/main.tsx
new file mode 100644
index 00000000..7514bbb7
--- /dev/null
+++ b/frontend/src/components/main.tsx
@@ -0,0 +1,81 @@
+"use client"
+
+import Card from "./Card";
+import Preview from "./Preview";
+import { useState, useEffect } from 'react';
+
+export default function Main() {
+
+ var [productData, setProductData ] = useState([]);
+ var [filteredData, setFilteredProductData] = useState([]);
+ var [previewProductData, setPreviewProductData] = useState(null);
+
+ var searchItems = function(value){
+ if(productData.length == 0) return;
+
+ if(value.trim() == ""){
+ setFilteredProductData(productData);
+ return;
+ }
+
+ const results = productData.filter(item =>
+ item.title.toLowerCase().includes(value.toLowerCase())
+ );
+
+ setFilteredProductData(results);
+ }
+
+ useEffect(() => {
+
+ (async () => {
+ const res = await fetch('https://fakestoreapi.com/products');
+ const data = await res.json();
+ if(data){
+ setProductData(data);
+ setFilteredProductData(data);
+ }
+ })()
+
+ }, []);
+
+ return (
+
+
searchItems(e.target.value) } type="text" placeholder="Search Product" className="z-[90] max-w-[90%] fixed top-[20px] left-[20px] rounded-[20px] p-[10px] w-[300px] bg-gray-800 text-base text-white placeholder:text-gray-500 focus:outline-none sm:text-sm/6" />
+
+
+
+ { previewProductData &&
+ (
+
{ setPreviewProductData(null) }}
+ />
+ )
+ }
+
+ { filteredData.length == 0 && No Product Avaible
}
+
+
+
+ {
+ filteredData.map( data =>
+ ( { setPreviewProductData(data) }}
+ />)
+ )
+ }
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/frontend/src/components/preview.tsx b/frontend/src/components/preview.tsx
new file mode 100644
index 00000000..ed2ff1d4
--- /dev/null
+++ b/frontend/src/components/preview.tsx
@@ -0,0 +1,34 @@
+export default function Preview({ productName, description, price, imageURL, ratings, onClick }) {
+
+ var starRatingStr = "";
+ for (var i = 0; i < 5; i++) {
+ if(i < Math.round(ratings.rate)) starRatingStr += "★";
+ else starRatingStr += "☆";
+ }
+
+ return (
+
+
+
+
+
+
+
+ { productName }
+ ${price}
+
+
+
+ { starRatingStr }
+ {ratings.count || 1} reviews
+
+
+
{description}
+
+
+
X
+
+
+
+ );
+}