Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Admin Dashboard Page with Metrics and Recent Sales #283

Merged
merged 2 commits into from
Nov 10, 2024
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
30 changes: 30 additions & 0 deletions alimento-nextjs/actions/Admin/admin-login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use server';
import { generateAndSendOTP } from '@/lib/auth';
import prismadb from '@/lib/prismadb';
import { Prisma, Admin } from '@prisma/client';

export async function AdminVerify({
email,
}: {
email: string;
}): Promise<{ success: boolean; error?: string; data?: Admin }> {
const exitingAdmin = await prismadb.admin.findUnique({
where: {
email: email,
},
});

if (!exitingAdmin) {
return {
success: false,
error: 'Admin does not exists',
};
}
const resp = await generateAndSendOTP(email, 'admin');

if (!resp) {
return { success: false, error: 'Error occured in sending otp' };
}

return { success: true };
}
36 changes: 36 additions & 0 deletions alimento-nextjs/app/admin/[adminId]/components/overview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use client";
import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis } from "recharts";

interface graphData{
name:string,
total:number
}
interface OverviewProps {
data:graphData[]
}

const Overview: React.FC<OverviewProps> = ({ data }) => {
return (
<ResponsiveContainer width="100%" height={350}>
<BarChart data={data}>
<XAxis
dataKey={"name"}
stroke="#888888"
fontSize={12}
tickLine={false}
axisLine={false}
/>
<YAxis
stroke="#888888"
fontSize={12}
tickLine={false}
axisLine={false}
tickFormatter={(value) => `₹${value}`}
/>
<Bar dataKey="total" fill="#5a64f2" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
);
};

export default Overview;
82 changes: 82 additions & 0 deletions alimento-nextjs/app/admin/[adminId]/components/recentSales.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";

interface Listing {
name: string;
email: string;
avatarSrc: string;
avatarText: string;
amount: number; // Price for a dish or restaurant
listingType: string; // Restaurant or Dish type
}

const listingsData: Listing[] = [
{
name: "Tandoori Delights",
email: "[email protected]",
avatarSrc: "/avatars/tandoori.png",
avatarText: "TD",
amount: 300.0,
listingType: "Restaurant - Indian Cuisine",
},
{
name: "Pasta Mania",
email: "[email protected]",
avatarSrc: "/avatars/pasta.png",
avatarText: "PM",
amount: 250.0,
listingType: "Restaurant - Italian Cuisine",
},
{
name: "Sushi World",
email: "[email protected]",
avatarSrc: "/avatars/sushi.png",
avatarText: "SW",
amount: 450.0,
listingType: "Restaurant - Japanese Cuisine",
},
{
name: "Burger Shack",
email: "[email protected]",
avatarSrc: "/avatars/burger.png",
avatarText: "BS",
amount: 120.0,
listingType: "Restaurant - Fast Food",
},
{
name: "Vegan Bites",
email: "[email protected]",
avatarSrc: "/avatars/vegan.png",
avatarText: "VB",
amount: 180.0,
listingType: "Restaurant - Vegan",
},
];

export function RecentSales() {
return (
<div className="space-y-8 flex items-center justify-center flex-col">
{listingsData.map((listing, index) => (
<div className="flex items-center w-full lg:w-3/4 bg-gray-200 dark:bg-gray-700 p-2 rounded-xl" key={index}>
<Avatar className="h-9 w-9">
<AvatarImage src={listing.avatarSrc} alt={listing.name} />
<AvatarFallback>{listing.avatarText}</AvatarFallback>
</Avatar>
<div className="grid grid-cols-1 gap-2 lg:grid-cols-2">
<div className="ml-4 space-y-1 p-2 col-span-1">
<p className="text-sm font-medium leading-none">{listing.name}</p>
<p className="text-sm text-muted-foreground">{listing.email}</p>
</div>
<div className="ml-4 space-y-1 p-2 col-span-1">
<div className="ml-auto text-sm font-medium">
₹{listing.amount.toLocaleString()}
</div>
<p className="ml-auto text-sm text-muted-foreground">
{listing.listingType}
</p>
</div>
</div>
</div>
))}
</div>
);
}
131 changes: 125 additions & 6 deletions alimento-nextjs/app/admin/[adminId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,126 @@
const AdminPage = () => {
return (
<div> hi from admin</div>
);

import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Heading } from "@/components/ui/heading";
import { Separator } from "@/components/ui/separator";
import { Activity, CreditCard, IndianRupee, Package, Store, User } from "lucide-react";
import { RecentSales } from "./components/recentSales";
import Overview from "./components/overview";

interface AdminPageProps {
params: { storeId: string };
}

export default AdminPage;

const mockGraphData = [
{ name: "Jan", total: 5000 },
{ name: "Feb", total: 4500 },
{ name: "Mar", total: 6000 },
{ name: "Apr", total: 5500 },
{ name: "May", total: 7000 },
{ name: "Jun", total: 8000 },
{ name: "Jul", total: 7500 },
{ name: "Aug", total: 7000 },
{ name: "Sep", total: 8500 },
{ name: "Oct", total: 9000 },
{ name: "Nov", total: 9500 },
{ name: "Dec", total: 10000 },
];

const AdminPage: React.FC<AdminPageProps> = async () => {

return (
<div className="flex-col">
<div className="flex-1 space-y-4 p-8 pt-6">
<Heading title="Alimento Dashboard" description="Overview of the website" />
<Separator />
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
<Card className="bg-gray-200 dark:bg-gray-700">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Total Revenue
</CardTitle>

<IndianRupee className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
₹ 2,10,789
</div>
</CardContent>
</Card>
<Card className="bg-gray-200 dark:bg-gray-700">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">Sales</CardTitle>

<CreditCard className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
+577
</CardContent>
</Card>
<Card className="bg-gray-200 dark:bg-gray-700">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Sellers Associated
</CardTitle>

<Store className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
43
</CardContent>
</Card>
<Card className="bg-gray-200 dark:bg-gray-700">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Customer Associated
</CardTitle>

<User className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
1450
</CardContent>
</Card>
<Card className="bg-gray-200 dark:bg-gray-700">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Website Visits
</CardTitle>

<Activity className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
100,223
</CardContent>
</Card>
<Card className="bg-gray-200 dark:bg-gray-700">
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Successful Orders
</CardTitle>

<Package className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
20455+
</CardContent>
</Card>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
<Card className="col-span-1">
<CardHeader>Overview</CardHeader>
<CardContent className="pl-2">
<Overview data={mockGraphData} />
</CardContent>
</Card>
<div className="col-span-1">
<Heading title="Some recent figures" description="We have made 114 sales this week!"/>
<RecentSales />
</div>
</div>
</div>
</div>
);
};

export default AdminPage;
Loading