Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Table, TableBody, TableHeader } from "@repo/ui/components/table";
import { ProdcutTableHead } from "./product-table-head/product-table-head";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Update import to use corrected component name

Once you've fixed the typo in the ProductTableHead component name, you'll need to update this import.

-import { ProdcutTableHead } from "./product-table-head/product-table-head";
+import { ProductTableHead } from "./product-table-head/product-table-head";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { ProdcutTableHead } from "./product-table-head/product-table-head";
import { ProductTableHead } from "./product-table-head/product-table-head";

import { ProductTableRow } from "./product-table-row/product-table-row";
import { ProductTablePages } from "./product-table-pages/product-table-pages";

const ProductTable = () => {
return (
<>
<Table className="mb-4">
<TableHeader>
<ProdcutTableHead />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Update component usage to match corrected name

After fixing the component name, you'll need to update its usage here.

-          <ProdcutTableHead />
+          <ProductTableHead />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<ProdcutTableHead />
<ProductTableHead />

</TableHeader>
<TableBody>
<ProductTableRow
productName="Crypite - Saas Crypto Currency website design"
comments={20}
likes={40}
earning="0.00$"
sales={0}
status="Published"
version="1.5.4"
totalPrice="0.00$"
rowIndex={1}
/>
</TableBody>
</Table>
<ProductTablePages page={1} limit={10} total={20} />
</>
);
};
export { ProductTable };
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { TableHead, TableRow } from "@repo/ui/components/table";
import Typography from "@repo/ui/components/typography";

const ProdcutTableHead = () => {
return (
<TableRow className="!bg-card">
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
#
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Product Name
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Status
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Sales
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Version
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Earining
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix typo in table header: "Earining" should be "Earning"

There's a typo in the table header text.

-          Earining
+          Earning
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Earining
Earning

</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Actions
</Typography>
</TableHead>
</TableRow>
);
};
Comment on lines +4 to +44
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix typo in component name: "Prodcut" should be "Product"

There's a typo in the component name ProdcutTableHead. This should be renamed to ProductTableHead for consistency and to avoid confusion.

-const ProdcutTableHead = () => {
+const ProductTableHead = () => {

Don't forget to update the export statement as well:

-export { ProdcutTableHead };
+export { ProductTableHead };

This will require updating imports in other files that use this component.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const ProdcutTableHead = () => {
return (
<TableRow className="!bg-card">
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
#
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Product Name
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Status
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Sales
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Version
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Earining
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Actions
</Typography>
</TableHead>
</TableRow>
);
};
const ProductTableHead = () => {
return (
<TableRow className="!bg-card">
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
#
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Product Name
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Status
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Sales
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Version
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Earining
</Typography>
</TableHead>
<TableHead className="border-b-2 border-background">
<Typography className="font-bold text-foreground" variant="label/sm">
Actions
</Typography>
</TableHead>
</TableRow>
);
};
export { ProductTableHead };


export { ProdcutTableHead };
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@repo/ui/components/select";
import Typography from "@repo/ui/components/typography";
import { useState } from "react";

interface ProductTablePageProps {
page?: number;
limit: number;
total: number;
onChange?: (pageNum: string) => void;
}

const ProductTablePages = (props: ProductTablePageProps) => {
const { page = 1, total, limit, onChange } = props;
const [selectPage, setSelectPage] = useState<string>(String(page));
const getPages = () => {
const pages: number[] = [];
for (let i = 1; i <= Math.floor(total / limit); i++) {
pages.push(i);
}
return pages;
};
Comment on lines +21 to +27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix pagination calculation to handle remainders

The current pagination calculation doesn't account for remainders, which means if you have a total that's not divisible by the limit, you'll be missing a page.

const getPages = () => {
  const pages: number[] = [];
-  for (let i = 1; i <= Math.floor(total / limit); i++) {
+  const totalPages = Math.ceil(total / limit);
+  for (let i = 1; i <= totalPages; i++) {
    pages.push(i);
  }
  return pages;
};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getPages = () => {
const pages: number[] = [];
for (let i = 1; i <= Math.floor(total / limit); i++) {
pages.push(i);
}
return pages;
};
const getPages = () => {
const pages: number[] = [];
const totalPages = Math.ceil(total / limit);
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
return pages;
};

return total === 0 ? null : (
<div className="flex items-center gap-[16px]">
<Typography variant="label/sm" component="span">
Page
</Typography>
<Select
value={selectPage}
onValueChange={(value) => {
setSelectPage(value);
onChange?.(value);
}}
>
<SelectTrigger className="max-w-[65px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
{getPages().map((number) => (
<SelectItem value={String(number)}>{number}</SelectItem>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add missing key prop to mapped elements

React requires a unique key prop for elements in an iterable to help with efficient rendering and updates.

{getPages().map((number) => (
-  <SelectItem value={String(number)}>{number}</SelectItem>
+  <SelectItem key={number} value={String(number)}>{number}</SelectItem>
))}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<SelectItem value={String(number)}>{number}</SelectItem>
{getPages().map((number) => (
<SelectItem key={number} value={String(number)}>{number}</SelectItem>
))}
🧰 Tools
🪛 Biome (1.9.4)

[error] 45-45: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

))}
</SelectContent>
</Select>
<Typography variant="label/sm">Of {total}</Typography>
</div>
);
};
export { ProductTablePages };
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import Image from "next/image";
import IconHeart from "@repo/icons/heart";
import MessegeIcon from "@repo/icons/message";
import { TableCell, TableRow } from "@repo/ui/components/table";
import Typography from "@repo/ui/components/typography";
import { Badge } from "@repo/ui/components/badge";
import DotsVerticalIcon from "@repo/icons/dotsVertical";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@repo/ui/components/dropdown-menu";

interface ProductTableRowProps {
rowIndex: number;
imgSrc?: string;
productName: string;
likes?: number;
comments?: number;
status: string;
sales: number;
version: string;
earning: string;
totalPrice: string;
}

const ProductTableRow = (props: ProductTableRowProps) => {
const {
rowIndex,
imgSrc = "/images/product-placeholder.jpg",
productName,
status,
sales,
version,
earning,
likes,
comments,
totalPrice,
} = props;
// Crypite - Saas Crypto Currency website design
return (
<TableRow className="!bg-card">
<TableCell className="border-b-2 border-background">
<Typography variant="label/sm">{rowIndex}</Typography>
</TableCell>
<TableCell className="border-b-2 border-background max-w-[400px]">
<div className="flex gap-[10px]">
<div>
<Image
src={imgSrc}
alt="Product Placeholder"
width={91}
height={61}
/>
</div>
<div className="flex flex-wrap -86">
<Typography variant="label/sm" className="max-w-[200px] truncate">
{productName}
</Typography>
<div className="flex gap-2 w-full">
<span className="inline-flex items-center gap-1">
<IconHeart size={20} />
<Typography variant="label/sm">{likes || 0}</Typography>
</span>
<span className="inline-flex items-center gap-1">
<MessegeIcon size={20} color="#A1A1AA" />
<Typography variant="label/sm">{comments || 0}</Typography>
</span>
</div>
</div>
</div>
</TableCell>
<TableCell className="border-b-2 border-background">
<Badge
className={`${status === "Published" ? "bg-success-400" : "bg-secondary"} p-[8px] rounded-lg`}
>
<Typography variant="label/sm">{status}</Typography>
</Badge>
</TableCell>
<TableCell className="border-b-2 border-background">
<Typography variant="label/sm">
<span>{sales}</span>
<span className="text-muted-foreground">({totalPrice})</span>
</Typography>
</TableCell>
<TableCell className="border-b-2 border-background">
<Typography variant="label/sm">{version}</Typography>
</TableCell>
<TableCell className="border-b-2 border-background">{earning}</TableCell>
<TableCell className="border-b-2 border-background">
<DropdownMenu>
<DropdownMenuTrigger>
<span className="cursor-pointer">
<DotsVerticalIcon color="white" />
</span>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={() => {}} className="cursor-pointer">
<Typography variant="label/xs">Edit</Typography>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}} className="cursor-pointer">
<Typography variant="label/xs">View product</Typography>
</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}} className="cursor-pointer">
<Typography variant="label/xs" className="text-error">
Delete
</Typography>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
</TableRow>
);
};

export { ProductTableRow };
35 changes: 35 additions & 0 deletions apps/core/app/dashboard/products/_components/tabs/product-tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"use client";
import { Tabs, TabsList, TabsTrigger } from "@repo/ui/components/tabs";
import Typography from "@repo/ui/components/typography";
import { Dispatch, SetStateAction } from "react";

interface ProductTabsProps {
tabs: { value: string; label: string }[];
setProductTab: Dispatch<SetStateAction<string>>;
}

const ProductTabs = (props: ProductTabsProps) => {
const { tabs, setProductTab } = props;
const handleValueChange = (value: string) => {
setProductTab(value);
};

return (
<Tabs defaultValue="all" onValueChange={handleValueChange}>
<TabsList className="bg-transparent gap-[8px]">
{tabs.map((tab, index) => (
<TabsTrigger
key={tab.label + "-" + index}
className="p-4 data-[state=active]:bg-primary bg-secondary rounded-lg"
value={tab.value}
>

<Typography variant="label/md">{tab.label}</Typography>
</TabsTrigger>
))}
</TabsList>
</Tabs>
);
};

export { ProductTabs };
33 changes: 33 additions & 0 deletions apps/core/app/dashboard/products/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";
import CirclePlusIcon from "@repo/icons/circle-plus";
import { Button } from "@repo/ui/components/button";
import Typography from "@repo/ui/components/typography";
import { useState } from "react";
import { ProductTabs } from "./_components/tabs/product-tabs";
import { ProductTable } from "./_components/table/product-table-head";

const tabs = [
{ value: "all", label: "Products" },
{ value: "drafts", label: "Drafts" },
];

const ProductsListPage = () => {
const [productTab, setProductTab] = useState<string>(tabs[0]?.value || "");

return (
<div className="py-5">
<Typography variant="heading/md" className="mb-4">
Products
</Typography>
<div className="flex flex-row justify-between items-center w-full mb-4">
<ProductTabs tabs={tabs} setProductTab={setProductTab} />
<Button variant="primary" size="lg">
<CirclePlusIcon color="white" />
Add Product
</Button>
</div>
<ProductTable />
</div>
);
};
export default ProductsListPage;
Loading
Loading