Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ yarn-error.log*
# Misc
.DS_Store
*.pem

#kafka certificates
certs/
File renamed without changes.
23 changes: 12 additions & 11 deletions apps/admin/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@ import type { NextConfig } from "next";

const nextConfig: NextConfig = {
/* config options here */
images:{
remotePatterns:[

images: {
remotePatterns: [
{
protocol:"https",
hostname:"images.pexels.com",
protocol: "https",
hostname: "images.pexels.com",
},
{
protocol:"https",
hostname:"img.clerk.com",
protocol: "https",
hostname: "img.clerk.com",
},
{
protocol:"https",
hostname:"res.cloudinary.com",
}
]
}
protocol: "https",
hostname: "res.cloudinary.com",
},
],
},
};

export default nextConfig;
12 changes: 6 additions & 6 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"check-types": "tsc --noEmit"
},
"dependencies": {
"@clerk/nextjs": "^6.31.10",
"@hookform/resolvers": "^5.2.2",
"@clerk/nextjs": "^7.0.6",
"@hookform/resolvers": "^5.0.1",
"@radix-ui/react-avatar": "^1.1.4",
"@radix-ui/react-checkbox": "^1.1.5",
"@radix-ui/react-collapsible": "^1.1.4",
Expand All @@ -26,23 +26,23 @@
"@radix-ui/react-separator": "^1.1.3",
"@radix-ui/react-slot": "^1.2.0",
"@radix-ui/react-tooltip": "^1.2.0",
"@tanstack/react-query": "^5.89.0",
"@tanstack/react-query": "^5.95.2",
"@tanstack/react-table": "^8.21.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"lucide-react": "^0.488.0",
"next": "15.3.0",
"next": "15.4.5",
"next-themes": "^0.4.6",
"react": "^19.0.0",
"react-day-picker": "8.10.1",
"react-dom": "^19.0.0",
"react-hook-form": "^7.62.0",
"react-hook-form": "^7.55.0",
"react-toastify": "^11.0.5",
"recharts": "^2.15.2",
"tailwind-merge": "^3.2.0",
"tw-animate-css": "^1.2.5",
"zod": "^4.1.9"
"zod": "^4.3.6"
},
"devDependencies": {
"@repo/eslint-config": "workspace:*",
Expand Down
Binary file added apps/admin/public/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion apps/admin/public/logo.svg

This file was deleted.

Binary file removed apps/admin/public/products/1g.png
Binary file not shown.
Binary file removed apps/admin/public/products/1gr.png
Binary file not shown.
Binary file removed apps/admin/public/products/1p.png
Binary file not shown.
Binary file removed apps/admin/public/products/2g.png
Binary file not shown.
Binary file removed apps/admin/public/products/2gr.png
Binary file not shown.
Binary file removed apps/admin/public/products/3b.png
Binary file not shown.
Binary file removed apps/admin/public/products/3bl.png
Binary file not shown.
Binary file removed apps/admin/public/products/3gr.png
Binary file not shown.
Binary file removed apps/admin/public/products/4p.png
Binary file not shown.
Binary file removed apps/admin/public/products/4w.png
Binary file not shown.
Binary file removed apps/admin/public/products/5bl.png
Binary file not shown.
Binary file removed apps/admin/public/products/5o.png
Binary file not shown.
Binary file removed apps/admin/public/products/5r.png
Binary file not shown.
Binary file removed apps/admin/public/products/6g.png
Binary file not shown.
Binary file removed apps/admin/public/products/6w.png
Binary file not shown.
Binary file removed apps/admin/public/products/7g.png
Binary file not shown.
Binary file removed apps/admin/public/products/7p.png
Binary file not shown.
Binary file removed apps/admin/public/products/8b.png
Binary file not shown.
Binary file removed apps/admin/public/products/8gr.png
Binary file not shown.
Binary file removed apps/admin/public/users/1.png
Binary file not shown.
Binary file removed apps/admin/public/users/10.png
Binary file not shown.
Binary file removed apps/admin/public/users/11.png
Binary file not shown.
Binary file removed apps/admin/public/users/12.png
Binary file not shown.
Binary file removed apps/admin/public/users/13.png
Diff not rendered.
Binary file removed apps/admin/public/users/14.png
Diff not rendered.
Binary file removed apps/admin/public/users/15.png
Diff not rendered.
Binary file removed apps/admin/public/users/16.png
Diff not rendered.
Binary file removed apps/admin/public/users/17.png
Diff not rendered.
Binary file removed apps/admin/public/users/18.png
Diff not rendered.
Binary file removed apps/admin/public/users/19.png
Diff not rendered.
Binary file removed apps/admin/public/users/2.png
Diff not rendered.
Binary file removed apps/admin/public/users/20.png
Diff not rendered.
Binary file removed apps/admin/public/users/21.png
Diff not rendered.
Binary file removed apps/admin/public/users/22.png
Diff not rendered.
Binary file removed apps/admin/public/users/23.png
Diff not rendered.
Binary file removed apps/admin/public/users/24.png
Diff not rendered.
Binary file removed apps/admin/public/users/25.png
Diff not rendered.
Binary file removed apps/admin/public/users/26.png
Diff not rendered.
Binary file removed apps/admin/public/users/27.png
Diff not rendered.
Binary file removed apps/admin/public/users/28.png
Diff not rendered.
Binary file removed apps/admin/public/users/29.png
Diff not rendered.
Binary file removed apps/admin/public/users/3.png
Diff not rendered.
Binary file removed apps/admin/public/users/30.png
Diff not rendered.
Binary file removed apps/admin/public/users/31.png
Diff not rendered.
Binary file removed apps/admin/public/users/32.png
Diff not rendered.
Binary file removed apps/admin/public/users/33.png
Diff not rendered.
Binary file removed apps/admin/public/users/34.png
Diff not rendered.
Binary file removed apps/admin/public/users/35.png
Diff not rendered.
Binary file removed apps/admin/public/users/36.png
Diff not rendered.
Binary file removed apps/admin/public/users/4.png
Diff not rendered.
Binary file removed apps/admin/public/users/5.png
Diff not rendered.
Binary file removed apps/admin/public/users/6.png
Diff not rendered.
Binary file removed apps/admin/public/users/7.png
Diff not rendered.
Binary file removed apps/admin/public/users/8.png
Diff not rendered.
Binary file removed apps/admin/public/users/9.png
Diff not rendered.
3 changes: 2 additions & 1 deletion apps/admin/src/app/(auth)/unauthorized/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"use client";

import { useAuth } from "@clerk/nextjs";
import React from "react";

const Page = () => {
const { signOut } = useAuth();
return (
<div className="">
<h1>You do not have an access!</h1>
<button onClick={() => signOut()}>Sign out</button>
<button onClick={() => signOut()}></button>
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions apps/admin/src/app/(dashboard)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { SidebarProvider } from "@/components/ui/sidebar";
import { cookies } from "next/headers";
import { ToastContainer } from "react-toastify";

// dashboard layout
export default async function RootLayout({
children,
}: Readonly<{
Expand Down
21 changes: 17 additions & 4 deletions apps/admin/src/app/(dashboard)/orders/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export const columns: ColumnDef<OrderType>[] = [
accessorKey: "_id",
header: "ID",
},
{
accessorKey: "username",
header: "Username",
cell: ({ row }) => {
const order = row.original;
return <div>{order.username || "-"}</div>;
},
},
{
accessorKey: "email",
header: ({ column }) => {
Expand All @@ -74,7 +82,7 @@ export const columns: ColumnDef<OrderType>[] = [
`p-1 rounded-md w-max text-xs`,
status === "pending" && "bg-yellow-500/40",
status === "success" && "bg-green-500/40",
status === "failed" && "bg-red-500/40"
status === "failed" && "bg-red-500/40",
)}
>
{status as string}
Expand All @@ -86,11 +94,16 @@ export const columns: ColumnDef<OrderType>[] = [
accessorKey: "amount",
header: () => <div className="text-right">Amount</div>,
cell: ({ row }) => {
const amount = parseFloat(row.getValue("amount"));
const order = row.original;
const amount =
order.products?.reduce(
(sum, product) => sum + product.price * product.quantity,
0,
) ?? parseFloat(row.getValue("amount"));
const formatted = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(amount/100);
}).format(amount);

return <div className="text-right font-medium">{formatted}</div>;
},
Expand All @@ -116,7 +129,7 @@ export const columns: ColumnDef<OrderType>[] = [
Copy order ID
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href={`/users/${order.userId}`}>View customer</Link>
</DropdownMenuItem>
<DropdownMenuItem>View order details</DropdownMenuItem>
Expand Down
56 changes: 51 additions & 5 deletions apps/admin/src/app/(dashboard)/orders/data-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import {
import { DataTablePagination } from "@/components/TablePagination";
import { useState } from "react";
import { Trash2 } from "lucide-react";
import { useAuth } from "@clerk/nextjs";
import { useMutation } from "@tanstack/react-query";
import { toast } from "react-toastify";
import { OrderType } from "@repo/types";
import { useRouter } from "next/navigation";

interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
Expand Down Expand Up @@ -48,14 +53,55 @@ export function DataTable<TData, TValue>({
},
});

console.log(rowSelection);
const { getToken } = useAuth();
const router = useRouter();

const mutation = useMutation({
mutationFn: async () => {
const token = await getToken();
const selectedRows = table.getSelectedRowModel().rows;

await Promise.all(
selectedRows.map(async (row) => {
const orderId = (row.original as OrderType)._id;

const res = await fetch(
`${process.env.NEXT_PUBLIC_ORDER_SERVICE_URL}/orders/${orderId}`,
{
method: "DELETE",
headers: {
Authorization: `Bearer ${token}`,
},
},
);

if (!res.ok) {
throw new Error(`Failed to delete order ${orderId}`);
}
}),
);
},
onSuccess: () => {
toast.success("Order(s) deleted successfully");
setRowSelection({});
router.refresh();
},
onError: (error) => {
toast.error(error.message);
},
});

return (
<div className="rounded-md border">
{Object.keys(rowSelection).length > 0 && (
<div className="flex justify-end">
<button className="flex items-center gap-2 bg-red-500 text-white px-2 py-1 text-sm rounded-md m-4 cursor-pointer">
<Trash2 className="w-4 h-4"/>
Delete Payment(s)
<button
className="flex items-center gap-2 bg-red-500 text-white px-2 py-1 text-sm rounded-md m-4 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50"
onClick={() => mutation.mutate()}
disabled={mutation.isPending}
>
<Trash2 className="w-4 h-4" />
{mutation.isPending ? "Deleting" : "Delete Order(s)"}
</button>
</div>
)}
Expand All @@ -70,7 +116,7 @@ export function DataTable<TData, TValue>({
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
header.getContext(),
)}
</TableHead>
);
Expand Down
21 changes: 18 additions & 3 deletions apps/admin/src/app/(dashboard)/orders/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,31 @@ const getData = async (): Promise<OrderType[]> => {
try {
const { getToken } = await auth();
const token = await getToken();

if (!token) {
console.error("Missing Clerk token for admin orders page.");
return [];
}

const res = await fetch(
`${process.env.NEXT_PUBLIC_ORDER_SERVICE_URL}/orders`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
cache: "no-store",
},
);

if (!res.ok) {
console.error(
`Failed to fetch orders: ${res.status} ${res.statusText}`,
);
return [];
}

const data = await res.json();
return data;
return Array.isArray(data) ? data : [];
} catch (err) {
console.log(err);
return [];
Expand All @@ -28,7 +43,7 @@ const OrdersPage = async () => {
return (
<div className="">
<div className="mb-8 px-4 py-2 bg-secondary rounded-md">
<h1 className="font-semibold">All Payments</h1>
<h1 className="font-semibold">All Orders</h1>
</div>
<DataTable columns={columns} data={data} />
</div>
Expand Down
19 changes: 7 additions & 12 deletions apps/admin/src/app/(dashboard)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,35 @@ import AppAreaChart from "@/components/AppAreaChart";
import AppBarChart from "@/components/AppBarChart";
import AppPieChart from "@/components/AppPieChart";
import CardList from "@/components/CardList";
import TodoList from "@/components/TodoList";
import { auth } from "@clerk/nextjs/server";

const Homepage = async () => {
const { getToken } = await auth();
const token = await getToken();
const orderChartData = fetch(
// 由于子组件client component,父组件里fetch
const orderChartdata = fetch(
`${process.env.NEXT_PUBLIC_ORDER_SERVICE_URL}/order-chart`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
},
).then((res) => res.json());

return (
<div className="grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-4 gap-4">
<div className="bg-primary-foreground p-4 rounded-lg lg:col-span-2 xl:col-span-1 2xl:col-span-2">
<AppBarChart dataPromise={orderChartData} />
<AppBarChart dataPromise={orderChartdata} />
</div>
<div className="bg-primary-foreground p-4 rounded-lg">
<CardList title="Latest Transactions" />
<CardList title="Latest Orders" />
</div>
<div className="bg-primary-foreground p-4 rounded-lg">
<AppPieChart />
</div>
<div className="bg-primary-foreground p-4 rounded-lg">
<TodoList />
</div>
<div className="bg-primary-foreground p-4 rounded-lg lg:col-span-2 xl:col-span-1 2xl:col-span-2">
<AppAreaChart />
</div>
<div className="bg-primary-foreground p-4 rounded-lg">
<CardList title="Popular Products" />
</div>
</div>
);
};
Expand Down
Loading