diff --git a/app/(dashboard)/analytics/analytics-client.tsx b/app/(dashboard)/analytics/analytics-client.tsx
new file mode 100644
index 0000000..2c1230f
--- /dev/null
+++ b/app/(dashboard)/analytics/analytics-client.tsx
@@ -0,0 +1,166 @@
+"use client";
+
+import { useState } from "react";
+import { Card, CardContent } from "poyraz-ui/atoms";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "poyraz-ui/molecules";
+import {
+ Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis,
+ PieChart, Pie, Cell, Legend
+} from "recharts";
+import { BarChart3, Filter } from "lucide-react";
+
+export type AnalyticsData = {
+ tasks: { id: string; status: string; created_at: string; due_at?: string }[];
+ projects: { id: string; name: string }[];
+ finances: { id: string; type: string; amount: number; transaction_date: string; project_id?: string }[];
+};
+
+type AnalyticsClientProps = {
+ data: AnalyticsData;
+};
+
+const COLORS = ["hsl(var(--primary))", "hsl(var(--destructive))", "#eab308", "#3b82f6", "#8b5cf6"];
+
+export function AnalyticsClient({ data }: AnalyticsClientProps) {
+ const [dateRange, setDateRange] = useState("this_month");
+
+ const now = new Date();
+
+ const filterByDate = (dateStr: string | null) => {
+ if (!dateStr) return false;
+ const date = new Date(dateStr);
+ if (dateRange === "this_week") {
+ const firstDay = new Date(now.setDate(now.getDate() - now.getDay() + (now.getDay() === 0 ? -6 : 1)));
+ return date >= firstDay;
+ }
+ if (dateRange === "this_month") {
+ return date.getMonth() === now.getMonth() && date.getFullYear() === now.getFullYear();
+ }
+ if (dateRange === "this_year") {
+ return date.getFullYear() === now.getFullYear();
+ }
+ return true;
+ };
+
+ const filteredFinances = data.finances.filter(f => filterByDate(f.transaction_date));
+ const filteredTasks = data.tasks.filter(t => filterByDate(t.created_at || t.due_at));
+
+ // Project-based income
+ const projectIncomeMap = new Map();
+ filteredFinances.filter(f => f.type === "income" && f.project_id).forEach(f => {
+ const project = data.projects.find(p => p.id === f.project_id);
+ const name = project ? project.name : "Bilinmeyen";
+ if (!projectIncomeMap.has(name)) {
+ projectIncomeMap.set(name, { name, value: 0 });
+ }
+ projectIncomeMap.get(name).value += Number(f.amount);
+ });
+ const projectIncomeData = Array.from(projectIncomeMap.values());
+
+ // Task completion stats
+ const completedTasks = filteredTasks.filter(t => t.status === "completed").length;
+ const activeTasks = filteredTasks.filter(t => t.status !== "completed" && t.status !== "cancelled").length;
+
+ const taskStatusData = [
+ { name: "Tamamlanan", value: completedTasks },
+ { name: "Devam Eden", value: activeTasks }
+ ];
+
+ return (
+
+
+
+
+
+ Analizler
+
+
+
+ Performans ve Finans Analizi
+
+
+ Müşteri bazlı gelirler, görev tamamlama oranları ve proje ilerleme grafikleri.
+
+
+
+
+
+
+
+
+
+
+
+
+ Proje Bazlı Gelir Dağılımı
+
+ {projectIncomeData.length > 0 ? (
+
+
+
+ {projectIncomeData.map((entry, index) => (
+ |
+ ))}
+
+ `₺${value}`}
+ contentStyle={{
+ backgroundColor: 'hsl(var(--background))',
+ borderColor: 'hsl(var(--border))',
+ borderRadius: '0.375rem',
+ }}
+ />
+
+
+
+ ) : (
+
Veri bulunamadı.
+ )}
+
+
+
+
+
+
+ Görev Durumu Analizi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/app/(dashboard)/analytics/page.tsx b/app/(dashboard)/analytics/page.tsx
index 0d2348e..e6fd239 100644
--- a/app/(dashboard)/analytics/page.tsx
+++ b/app/(dashboard)/analytics/page.tsx
@@ -1,255 +1,39 @@
-"use client";
+import { createClient } from "@/lib/supabase/server";
+import { AnalyticsClient } from "./analytics-client";
+import { redirect } from "next/navigation";
-import { useState } from "react";
-import {
- ArrowUpRight, Brain, TrendingUp, Zap, Target, ArrowDownRight,
- BarChart3, Filter, Download, Info, CheckCircle2, AlertCircle
-} from "lucide-react";
-import {
- Area, AreaChart, Bar, BarChart, CartesianGrid, ResponsiveContainer,
- Tooltip, XAxis, YAxis, Radar, RadarChart, PolarGrid, PolarAngleAxis, Cell
-} from "recharts";
-import { motion, AnimatePresence } from "framer-motion";
+export const metadata = {
+ title: "Analizler - Cognis",
+};
-// Mock Data
-const productivityTrend = [
- { date: "May 1", focus: 65, energy: 40 },
- { date: "May 4", focus: 75, energy: 55 },
- { date: "May 8", focus: 60, energy: 50 },
- { date: "May 12", focus: 85, energy: 70 },
- { date: "May 16", focus: 72, energy: 65 },
- { date: "May 20", focus: 95, energy: 85 },
- { date: "May 24", focus: 88, energy: 80 },
-];
+export default async function AnalyticsPage() {
+ const supabase = await createClient();
+ const { data: { user } } = await supabase.auth.getUser();
-const habitCompletion = [
- { name: "Reading", completed: 85, missed: 15, color: "#6C5BB0" },
- { name: "Workout", completed: 60, missed: 40, color: "#a798e8" },
- { name: "Meditation", completed: 90, missed: 10, color: "#10b981" },
- { name: "Coding", completed: 75, missed: 25, color: "#3b82f6" },
-];
+ if (!user) {
+ redirect("/login");
+ }
-const focusRadarData = [
- { subject: "Deep Work", A: 120, fullMark: 150 },
- { subject: "Learning", A: 98, fullMark: 150 },
- { subject: "Health", A: 86, fullMark: 150 },
- { subject: "Networking", A: 65, fullMark: 150 },
- { subject: "Admin", A: 40, fullMark: 150 },
-];
+ // 1. Fetch tasks
+ const { data: tasks } = await supabase
+ .from("tasks")
+ .select("*");
-export default function AnalyticsPage() {
- const [isExporting, setIsExporting] = useState(false);
- const [activeInsight, setActiveInsight] = useState(null);
+ // 2. Fetch projects
+ const { data: projects } = await supabase
+ .from("projects")
+ .select("*");
- const handleExport = () => {
- setIsExporting(true);
- setTimeout(() => setIsExporting(false), 3000);
+ // 3. Fetch finances
+ const { data: finances } = await supabase
+ .from("finance_transactions")
+ .select("*");
+
+ const analyticsData = {
+ tasks: tasks || [],
+ projects: projects || [],
+ finances: finances || [],
};
- return (
-
-
- {/* Top Header */}
-
-
- Analytics / Performance Metrics
-
-
-
-
-
-
-
-
-
-
- {/* KPI Row */}
-
-
-
-
-
- {/* Dynamic AI Score Ring */}
-
-
-
Strategic Readiness
-
94%
-
Optimal alignment with goals.
-
-
-
-
-
- {/* Main Analysis Area */}
-
-
- {/* Productivity Chart with Hotspots */}
-
-
-
-
Correlation: Focus vs Energy
-
Detailed visual mapping of biological energy impact on focus output.
-
-
-
-
- {/* Chart Interaction Layer */}
-
-
-
-
-
- {activeInsight && (
-
-
- AI Observation
-
- {activeInsight}
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Sidebar Insights */}
-
-
-
-
Effort Distribution
-
-
-
-
-
Strategic Alerts
-
-
-
-
-
Habit Streak Maintained
-
Reading streak is now at 12 days. Energy levels are correlating positively.
-
-
-
-
-
-
Admin Overload
-
Admin tasks have increased by 15%. Consider automating these via Cognis AI.
-
-
-
-
-
-
-
-
- );
-}
-
-function KpiCard({ title, value, change, icon: Icon, trend, color = "primary" }: any) {
- const isUp = trend === "up";
- const trendColor = isUp ? "text-emerald-500" : "text-rose-500";
-
- return (
-
-
-
-
-
{title}
-
-
{value}
-
- {isUp ? : } {change}
-
-
-
vs previous 30 days
-
- );
+ return ;
}
diff --git a/app/(dashboard)/dashboard-client.tsx b/app/(dashboard)/dashboard-client.tsx
new file mode 100644
index 0000000..49bfe80
--- /dev/null
+++ b/app/(dashboard)/dashboard-client.tsx
@@ -0,0 +1,299 @@
+"use client";
+
+import { useState } from "react";
+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 { 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 }[];
+ 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 }[];
+};
+
+type DashboardClientProps = {
+ data: DashboardData;
+};
+
+export function DashboardClient({ data }: DashboardClientProps) {
+ const [dateRange, setDateRange] = useState("this_month");
+ const [isQuickActionOpen, setIsQuickActionOpen] = useState(false);
+
+ // Calculate real metrics from the `data` prop depending on `dateRange`
+ const now = new Date();
+
+ // Helper to filter by date
+ const filterByDate = (dateStr: string | null) => {
+ if (!dateStr) return false;
+ const date = new Date(dateStr);
+ if (dateRange === "today") {
+ return date.toDateString() === now.toDateString();
+ }
+ if (dateRange === "this_week") {
+ const firstDay = new Date(now.setDate(now.getDate() - now.getDay() + (now.getDay() === 0 ? -6 : 1))); // Monday
+ return date >= firstDay;
+ }
+ if (dateRange === "this_month") {
+ return date.getMonth() === now.getMonth() && date.getFullYear() === now.getFullYear();
+ }
+ return true;
+ };
+
+ // KPIs
+ 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 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 avgMood = filteredLogs.length > 0
+ ? (filteredLogs.reduce((acc, curr) => acc + curr.mood_score, 0) / filteredLogs.length).toFixed(1)
+ : "0.0";
+
+ // Recharts Data Prep
+ // Group finances by date
+ const financeMap = new Map();
+ filteredFinances.forEach(f => {
+ const d = new Date(f.transaction_date).toLocaleDateString("tr-TR", { month: "short", day: "numeric" });
+ if (!financeMap.has(d)) {
+ financeMap.set(d, { name: d, income: 0, expense: 0 });
+ }
+ const entry = financeMap.get(d);
+ if (f.type === "income") entry.income += Number(f.amount);
+ if (f.type === "expense") entry.expense += Number(f.amount);
+ });
+ const incomeTrendData = Array.from(financeMap.values());
+
+ // Group logs by date
+ const moodTrendData = filteredLogs.map(l => ({
+ date: new Date(l.log_date).toLocaleDateString("tr-TR", { month: "short", day: "numeric" }),
+ mood: l.mood_score,
+ energy: l.energy_score,
+ }));
+
+ // Format currency
+ const formatCurrency = (val: number) => {
+ return new Intl.NumberFormat("tr-TR", {
+ style: "currency",
+ currency: "USD",
+ maximumFractionDigits: 0,
+ }).format(val);
+ };
+
+ return (
+
+ {/* Header */}
+
+
+
+
+
+ Dashboard
+
+
+ İş performansını, gelirlerini ve günlük durumunu takip et.
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* KPI Cards */}
+
+
+
+
+
+
+
+ {/* Charts */}
+
+
+
+ Gelir / Gider Özeti
+
+ {incomeTrendData.length > 0 ? (
+
+
+
+
+
+
+
+
+
+
+ ) : (
+
Bu tarih aralığında finansal veri yok.
+ )}
+
+
+
+
+
+
+ Mood & Enerji Trendi
+
+ {moodTrendData.length > 0 ? (
+
+
+
+
+
+
+
+
+
+
+ ) : (
+
Bu tarih aralığında günlük verisi yok.
+ )}
+
+
+
+
+
+ {/* Upcoming & Tasks List */}
+
+
+
+
+
Yaklaşan Etkinlikler ve Deadlinelar
+
+
+
+ {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" })}
+
+
+
+ )) : (
+
Yaklaşan etkinlik yok.
+ )}
+
+
+
+
+
+ );
+}
+
+function StatCard({
+ label,
+ value,
+ icon: Icon,
+ tone,
+}: {
+ label: string;
+ value: string;
+ icon: typeof FolderKanban;
+ 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 (
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/app/(dashboard)/page.tsx b/app/(dashboard)/page.tsx
index 266c540..fd00340 100644
--- a/app/(dashboard)/page.tsx
+++ b/app/(dashboard)/page.tsx
@@ -1,395 +1,69 @@
-"use client";
+import { createClient } from "@/lib/supabase/server";
+import { DashboardClient } from "./dashboard-client";
+import { redirect } from "next/navigation";
-import { useState } from "react";
-import {
- Bar,
- BarChart,
- CartesianGrid,
- Cell,
- Line,
- LineChart,
- Pie,
- PieChart,
- ResponsiveContainer,
- Tooltip,
- XAxis,
- YAxis,
-} from "recharts";
-import {
- CheckSquare2, Droplets, Moon, Target, Activity,
- MoreHorizontal, PenTool, Plus, GripVertical, Maximize2
-} from "lucide-react";
-import { motion, Reorder } from "framer-motion";
-import { QuickActionsSheet } from "@/components/dashboard/quick-actions-sheet";
-import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
+export const metadata = {
+ title: "Dashboard - Cognis",
+};
-// Mock Data
-const focusTrendData = [
- { date: "May 12", value: 55 },
- { date: "May 13", value: 42 },
- { date: "May 14", value: 60 },
- { date: "May 15", value: 85 },
- { date: "May 16", value: 72 },
- { date: "May 17", value: 87 },
- { date: "May 18", value: 100 },
-];
+export default async function DashboardPage() {
+ const supabase = await createClient();
+ const { data: { user } } = await supabase.auth.getUser();
-const sleepData = [
- { day: "M", value: 6.5 },
- { day: "T", value: 7.2 },
- { day: "W", value: 5.8 },
- { day: "T", value: 6.1 },
- { day: "F", value: 8.0 },
- { day: "S", value: 7.5 },
- { day: "S", value: 8.5 },
-];
+ if (!user) {
+ redirect("/login");
+ }
-const waterData = [
- { day: "M", value: 1.5 },
- { day: "T", value: 2.1 },
- { day: "W", value: 1.8 },
- { day: "T", value: 2.5 },
- { day: "F", value: 2.0 },
- { day: "S", value: 3.0 },
- { day: "S", value: 2.8 },
-];
-
-const moodData = [
- { day: "M", value: 60 },
- { day: "T", value: 85 },
- { day: "W", value: 70 },
- { day: "T", value: 65 },
- { day: "F", value: 80 },
- { day: "S", value: 90 },
- { day: "S", value: 95 },
-];
-
-const focusDistributionData = [
- { name: "Deep Work", value: 45, color: "#6C5BB0" },
- { name: "Shallow Work", value: 30, color: "#54468B" },
- { name: "Meetings", value: 15, color: "#3B3161" },
- { name: "Breaks", value: 10, color: "#221C38" },
-];
-
-const upcomingEvents = [
- { time: "10:00 AM", title: "Deep Work Session", category: "FOCUS", color: "border-l-pink-500" },
- { time: "12:30 PM", title: "Team Standup", category: "MEETING", color: "border-l-orange-500" },
- { time: "02:00 PM", title: "Project Review", category: "WORK", color: "border-l-blue-500" },
- { time: "04:00 PM", title: "Workout", category: "HEALTH", color: "border-l-emerald-500" },
- { time: "07:00 PM", title: "Daily Reflection", category: "PERSONAL", color: "border-l-purple-500" },
-];
-
-type WidgetId = "sleep" | "water" | "mood" | "distribution";
-
-export default function DashboardPage() {
- const [isQuickActionOpen, setIsQuickActionOpen] = useState(false);
- const [selectedKpi, setSelectedKpi] = useState(null);
+ // Get current date and date 30 days ago
+ const today = new Date();
+ const thirtyDaysAgo = new Date();
+ thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
- // Widget ordering state
- const [widgetOrder, setWidgetOrder] = useState(["sleep", "water", "mood", "distribution"]);
+ const todayStr = today.toISOString();
+ const thirtyDaysAgoStr = thirtyDaysAgo.toISOString();
- return (
-
-
- {/* Top Header */}
-
-
- Dashboard / Overview
-
-
-
+ // 1. Fetch tasks
+ const { data: tasks } = await supabase
+ .from("tasks")
+ .select("*")
+ .or(`due_at.gte.${thirtyDaysAgoStr},created_at.gte.${thirtyDaysAgoStr}`)
+ .order("due_at", { ascending: true });
-
-
- {/* LEFT COLUMN: Focus Trend (Takes 2 columns on XL) */}
-
-
-
-
-
Focus Trend
-
87%
-
Average Focus Score
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ // 2. Fetch projects
+ const { data: projects } = await supabase
+ .from("projects")
+ .select("*")
+ .order("created_at", { ascending: false });
- {/* RIGHT COLUMN: Quick Add & Upcoming */}
-
-
- {/* AI Strategy Suggestion (Replacing Quick Add Input) */}
-
-
-
-
- AI Insight
-
-
- "Based on your 100% focus score yesterday, you have high mental momentum. Schedule your hardest task for 10:00 AM today."
-
-
-
+ // 3. Fetch finances
+ const { data: finances } = await supabase
+ .from("finance_transactions")
+ .select("*")
+ .gte("transaction_date", thirtyDaysAgoStr)
+ .order("transaction_date", { ascending: true });
- {/* Upcoming */}
-
-
-
Upcoming
-
-
-
- {upcomingEvents.map((event, idx) => (
-
-
-
{event.time}
-
{event.title}
-
{event.category}
-
- ))}
-
-
+ // 4. Fetch daily logs
+ const { data: logs } = await supabase
+ .from("daily_logs")
+ .select("*")
+ .gte("log_date", thirtyDaysAgoStr)
+ .order("log_date", { ascending: true });
-
-
+ // 5. Fetch calendar events (upcoming)
+ const { data: events } = await supabase
+ .from("calendar_events")
+ .select("*")
+ .gte("starts_at", todayStr)
+ .order("starts_at", { ascending: true })
+ .limit(10);
- {/* BOTTOM ROW: Draggable Widgets */}
-
- {widgetOrder.map((id) => (
-
- {id === "sleep" && (
- setSelectedKpi("sleep")}
- />
- )}
- {id === "water" && (
- setSelectedKpi("water")}
- />
- )}
- {id === "mood" && (
- setSelectedKpi("mood")}
- />
- )}
- {id === "distribution" && (
-
-
-
Focus Distribution
-
-
-
-
-
- {focusDistributionData.map((entry, index) => (
- |
- ))}
-
-
-
-
-
- {focusDistributionData.slice(0, 3).map((item, idx) => (
-
- ))}
-
-
-
- )}
-
- ))}
-
+ const dashboardData = {
+ tasks: tasks || [],
+ projects: projects || [],
+ finances: finances || [],
+ logs: logs || [],
+ events: events || [],
+ };
- {/* Quote Footer */}
-
-
-
-
-
-
-
SYSTEM REMINDER
-
"Discipline is the bridge between goals and accomplishment."
-
-
-
- Jim Rohn
-
-
- {/* Sheet & Modals */}
-
setIsQuickActionOpen(false)}
- />
-
-
-
-
- );
-}
-
-function WidgetCard({ title, icon: Icon, value, unit, goal, data, onExpand }: any) {
- return (
-
-
-
-
{title}
-
-
-
-
- {value}
- {unit}
-
-
-
-
-
-
-
-
-
-
-
Goal: {goal}
-
-
- );
+ return ;
}