diff --git a/app/(dashboard)/dashboard-client.tsx b/app/(dashboard)/dashboard-client.tsx index d9ef8cb..b0b62ec 100644 --- a/app/(dashboard)/dashboard-client.tsx +++ b/app/(dashboard)/dashboard-client.tsx @@ -1,18 +1,19 @@ "use client"; import { useState } from "react"; +import Link from "next/link"; import { Badge, Button, Card, CardContent } from "poyraz-ui/atoms"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "poyraz-ui/molecules"; import { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis, Line, LineChart } from "recharts"; -import { CheckCircle2, Wallet, FolderKanban, Activity, CalendarDays, Plus } from "lucide-react"; +import { CheckCircle2, Wallet, FolderKanban, Activity, CalendarDays, Plus, Users } from "lucide-react"; import { QuickActionsSheet } from "@/components/dashboard/quick-actions-sheet"; export type DashboardData = { tasks: { id: string; status: string; created_at: string; updated_at?: string; due_at?: string }[]; - projects: { id: string; status: string; name: string }[]; + projects: { id: string; status: string; name: string; created_at: string }[]; finances: { id: string; type: string; amount: number; transaction_date: string }[]; logs: { id: string; log_date: string; mood_score: number; energy_score: number }[]; - events: { id: string; title: string; type: string; starts_at: string }[]; + clients: { id: string; name: string; company_name: string; created_at: string }[]; }; type DashboardClientProps = { @@ -44,16 +45,16 @@ export function DashboardClient({ data }: DashboardClientProps) { }; // KPIs - const filteredFinances = data.finances.filter(f => filterByDate(f.transaction_date)); + const filteredFinances = (data.finances || []).filter(f => filterByDate(f.transaction_date)); const income = filteredFinances.filter(f => f.type === "income").reduce((acc, curr) => acc + Number(curr.amount), 0); const expense = filteredFinances.filter(f => f.type === "expense").reduce((acc, curr) => acc + Number(curr.amount), 0); const netProfit = income - expense; - const activeProjectsCount = data.projects.filter(p => p.status === "active").length; + const activeProjectsCount = (data.projects || []).filter(p => p.status === "active").length; - const completedTasksCount = data.tasks.filter(t => t.status === "completed" && filterByDate(t.updated_at || t.created_at)).length; + const completedTasksCount = (data.tasks || []).filter(t => t.status === "completed" && filterByDate(t.updated_at || t.created_at)).length; - const filteredLogs = data.logs.filter(l => filterByDate(l.log_date)); + const filteredLogs = (data.logs || []).filter(l => filterByDate(l.log_date)); const avgMood = filteredLogs.length > 0 ? (filteredLogs.reduce((acc, curr) => acc + curr.mood_score, 0) / filteredLogs.length).toFixed(1) : "0.0"; @@ -264,27 +265,62 @@ export function DashboardClient({ data }: DashboardClientProps) { - {/* Upcoming & Tasks List */} + {/* Recent Items */}
+ {/* Recent Projects */}
-

Yaklaşan Etkinlikler ve Deadlinelar

- +

Son Eklenen Projeler

+
- {data.events.length > 0 ? data.events.map((event) => ( -
-
-
-

{event.title}

-

- {new Date(event.starts_at).toLocaleDateString("tr-TR", { month: "long", day: "numeric", hour: "2-digit", minute: "2-digit" })} -

+ {(data.projects || []).slice(0, 5).map((project) => ( + +
+
+
+

{project.name}

+

+ {new Date(project.created_at).toLocaleDateString("tr-TR", { month: "short", day: "numeric" })} +

+
+ + {project.status === 'completed' ? 'Tamamlandı' : project.status === 'active' ? 'Aktif' : 'Beklemede'} +
-
+ + ))} + {data.projects.length === 0 && ( +
Henüz proje yok.
+ )} +
+ + + + {/* Recent Clients */} + + +
+

Son Eklenen Müşteriler

+ +
+
+ {(data.clients || []).length > 0 ? (data.clients || []).map((client) => ( + +
+ {client.name.charAt(0).toUpperCase()} +
+
+

{client.name}

+

{client.company_name || "Bireysel"}

+
+
+ {new Date(client.created_at).toLocaleDateString("tr-TR", { month: "short", day: "numeric" })} +
+ )) : ( -
Yaklaşan etkinlik yok.
+
Henüz müşteri yok.
)}
diff --git a/app/(dashboard)/page.tsx b/app/(dashboard)/page.tsx index a77a39a..b146619 100644 --- a/app/(dashboard)/page.tsx +++ b/app/(dashboard)/page.tsx @@ -49,20 +49,19 @@ export default async function DashboardPage() { .gte("log_date", thirtyDaysAgoStr) .order("log_date", { ascending: true }); - // 5. Fetch calendar events (upcoming) - const { data: events } = await supabase - .from("calendar_events") + // 5. Fetch recent clients + const { data: clients } = await supabase + .from("clients") .select("*") - .gte("starts_at", todayStr) - .order("starts_at", { ascending: true }) - .limit(10); + .order("created_at", { ascending: false }) + .limit(5); const dashboardData = { tasks: tasks || [], projects: projects || [], finances: finances || [], logs: logs || [], - events: events || [], + clients: clients || [], }; return ; diff --git a/app/portal/page.tsx b/app/portal/page.tsx index 061afb9..385b457 100644 --- a/app/portal/page.tsx +++ b/app/portal/page.tsx @@ -1,6 +1,6 @@ import { createClient } from "@/lib/supabase/server"; import { Card, CardContent, Badge } from "poyraz-ui/atoms"; -import { FolderKanban, CheckCircle2, Clock, ArrowRight } from "lucide-react"; +import { FolderKanban, CheckCircle2, Clock, Activity, Wallet, BarChart } from "lucide-react"; import Link from "next/link"; import { format } from "date-fns"; import { tr } from "date-fns/locale"; @@ -32,7 +32,7 @@ export default async function PortalDashboardPage() { // 2. Get Projects const { data: projectsData } = await supabase .from("projects") - .select("id, name, status, progress, due_date, budget_amount, currency") + .select("id, name, status, progress, due_date, budget_amount, currency, created_at") .eq("client_id", clientData.id) .order("created_at", { ascending: false }); @@ -41,34 +41,46 @@ export default async function PortalDashboardPage() { const activeProjects = projects.filter(p => p.status !== 'completed' && p.status !== 'cancelled'); const completedProjects = projects.filter(p => p.status === 'completed'); + const totalBudget = activeProjects.reduce((sum, p) => sum + (Number(p.budget_amount) || 0), 0); + const avgProgress = projects.length > 0 ? (projects.reduce((sum, p) => sum + (p.progress || 0), 0) / projects.length).toFixed(0) : "0"; + + const formatCurrency = (val: number) => { + return new Intl.NumberFormat("tr-TR", { + style: "currency", + currency: projects[0]?.currency || "USD", + maximumFractionDigits: 0, + }).format(val); + }; + return ( -
-
-

Hoş Geldiniz, {clientData.name}

-

İş süreçlerinizi ve aktif projelerinizi buradan takip edebilirsiniz.

+
+ {/* Header */} +
+
+
+ + Genel Bakış +
+
+

+ Müşteri Paneli +

+

+ Hoş geldiniz, {clientData.name}. Aktif projelerinizi, ilerlemeleri ve bütçe durumunuzu buradan takip edin. +

+
+
-
- - -
- -

Aktif Projeler

-
-

{activeProjects.length}

-
-
- - -
- -

Tamamlanan

-
-

{completedProjects.length}

-
-
+ {/* KPI Cards */} +
+ + + +
+ {/* Projects */}

Tüm Projeleriniz

@@ -81,25 +93,30 @@ export default async function PortalDashboardPage() { -
+
-

{project.name}

- - {project.status} - +
+
+

{project.name}

+
- {project.due_date && ( -
- - Son Teslim: {format(new Date(project.due_date), 'd MMM yyyy', { locale: tr })} -
- )} +
+ + {project.status === 'completed' ? 'Tamamlandı' : project.status === 'active' ? 'Aktif' : 'Beklemede'} + + {project.due_date && ( +
+ + Teslim: {format(new Date(project.due_date), 'd MMM yyyy', { locale: tr })} +
+ )} +
-
+
- İlerleme + İlerleme %{project.progress}
@@ -119,3 +136,36 @@ export default async function PortalDashboardPage() {
); } + +function StatCard({ + label, + value, + icon: Icon, + tone, +}: { + label: string; + value: string; + icon: any; + tone: "green" | "blue" | "amber" | "red"; +}) { + const toneClass = { + green: "bg-emerald-50 text-emerald-700", + blue: "bg-blue-50 text-blue-700", + amber: "bg-amber-50 text-amber-700", + red: "bg-primary/10 text-primary", + }[tone]; + + return ( + + +
+

{label}

+

{value}

+
+
+ +
+
+
+ ); +}