Code edited in Lovable Code Editor

Edited UI in Lovable
This commit is contained in:
gpt-engineer-app[bot]
2025-12-19 10:56:40 +00:00
parent d860f0296d
commit 3392932444

View File

@@ -1,12 +1,12 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { supabase } from '@/integrations/supabase/client';
import { useAuth } from '@/hooks/useAuth';
import { AppLayout } from '@/components/AppLayout';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Skeleton } from '@/components/ui/skeleton';
import { formatIDR } from '@/lib/format';
import { Package, Users, Receipt, TrendingUp, BookOpen, Calendar } from 'lucide-react';
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { supabase } from "@/integrations/supabase/client";
import { useAuth } from "@/hooks/useAuth";
import { AppLayout } from "@/components/AppLayout";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { formatIDR } from "@/lib/format";
import { Package, Users, Receipt, TrendingUp, BookOpen, Calendar } from "lucide-react";
interface Stats {
totalProducts: number;
@@ -26,22 +26,22 @@ export default function AdminDashboard() {
useEffect(() => {
if (!authLoading) {
if (!user) navigate('/auth');
else if (!isAdmin) navigate('/dashboard');
if (!user) navigate("/auth");
else if (!isAdmin) navigate("/dashboard");
else fetchData();
}
}, [user, isAdmin, authLoading]);
const fetchData = async () => {
const [productsRes, profilesRes, ordersRes, paidOrdersRes, bootcampRes] = await Promise.all([
supabase.from('products').select('id', { count: 'exact' }),
supabase.from('profiles').select('id', { count: 'exact' }),
supabase.from('orders').select('*').order('created_at', { ascending: false }).limit(5),
supabase.from('orders').select('total_amount').eq('payment_status', 'paid'),
supabase.from('products').select('id', { count: 'exact' }).eq('type', 'bootcamp').eq('is_active', true),
supabase.from("products").select("id", { count: "exact" }),
supabase.from("profiles").select("id", { count: "exact" }),
supabase.from("orders").select("*").order("created_at", { ascending: false }).limit(5),
supabase.from("orders").select("total_amount").eq("payment_status", "paid"),
supabase.from("products").select("id", { count: "exact" }).eq("type", "bootcamp").eq("is_active", true),
]);
const pendingRes = await supabase.from('orders').select('id', { count: 'exact' }).eq('payment_status', 'pending');
const pendingRes = await supabase.from("orders").select("id", { count: "exact" }).eq("payment_status", "pending");
const totalRevenue = paidOrdersRes.data?.reduce((sum, o) => sum + (o.total_amount || 0), 0) || 0;
@@ -64,7 +64,9 @@ export default function AdminDashboard() {
<div className="container mx-auto px-4 py-8">
<Skeleton className="h-10 w-1/3 mb-8" />
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{[...Array(4)].map((_, i) => <Skeleton key={i} className="h-32" />)}
{[...Array(4)].map((_, i) => (
<Skeleton key={i} className="h-32" />
))}
</div>
</div>
</AppLayout>
@@ -72,11 +74,11 @@ export default function AdminDashboard() {
}
const statCards = [
{ label: 'Total Produk', value: stats?.totalProducts || 0, icon: Package, color: 'text-primary' },
{ label: 'Total Member', value: stats?.totalMembers || 0, icon: Users, color: 'text-accent' },
{ label: 'Order Pending', value: stats?.pendingOrders || 0, icon: Receipt, color: 'text-secondary-foreground' },
{ label: 'Total Pendapatan', value: formatIDR(stats?.totalRevenue || 0), icon: TrendingUp, color: 'text-primary' },
{ label: 'Bootcamp Aktif', value: stats?.activeBootcamps || 0, icon: BookOpen, color: 'text-accent' },
{ label: "Total Produk", value: stats?.totalProducts || 0, icon: Package, color: "text-primary" },
{ label: "Total Member", value: stats?.totalMembers || 0, icon: Users, color: "text-accent" },
{ label: "Order Pending", value: stats?.pendingOrders || 0, icon: Receipt, color: "text-secondary-foreground" },
{ label: "Total Pendapatan", value: formatIDR(stats?.totalRevenue || 0), icon: TrendingUp, color: "text-primary" },
{ label: "Bootcamp Aktif", value: stats?.activeBootcamps || 0, icon: BookOpen, color: "text-accent" },
];
return (
@@ -90,7 +92,7 @@ export default function AdminDashboard() {
<Card key={stat.label} className="border-2 border-border">
<CardContent className="pt-6">
<div className="flex items-center gap-3">
<stat.icon className={`w-8 h-8 ${stat.color}`} />
<stat.icon className={`w-8 h-8 ${stat.color} text-primary`} />
<div>
<p className="text-2xl font-bold">{stat.value}</p>
<p className="text-xs text-muted-foreground">{stat.label}</p>
@@ -111,15 +113,22 @@ export default function AdminDashboard() {
) : (
<div className="space-y-4">
{recentOrders.map((order) => (
<div key={order.id} className="flex items-center justify-between py-2 border-b border-border last:border-0">
<div
key={order.id}
className="flex items-center justify-between py-2 border-b border-border last:border-0"
>
<div>
<p className="font-mono text-sm">{order.id.slice(0, 8)}</p>
<p className="text-xs text-muted-foreground">{new Date(order.created_at).toLocaleDateString('id-ID')}</p>
<p className="text-xs text-muted-foreground">
{new Date(order.created_at).toLocaleDateString("id-ID")}
</p>
</div>
<div className="text-right">
<p className="font-bold">{formatIDR(order.total_amount)}</p>
<span className={`text-xs px-2 py-0.5 ${order.payment_status === 'paid' ? 'bg-accent text-accent-foreground' : 'bg-muted text-muted-foreground'}`}>
{order.payment_status === 'paid' ? 'Lunas' : 'Pending'}
<span
className={`text-xs px-2 py-0.5 ${order.payment_status === "paid" ? "bg-accent text-accent-foreground" : "bg-muted text-muted-foreground"}`}
>
{order.payment_status === "paid" ? "Lunas" : "Pending"}
</span>
</div>
</div>