From 1d318e1ea08ee09b730fc156a6991d8e0a3c62c0 Mon Sep 17 00:00:00 2001 From: poyrazavsever Date: Sat, 18 Jul 2026 20:18:39 +0300 Subject: [PATCH] fix: clean dashboard client type issues --- .../analytics/analytics-client.tsx | 2 +- .../business/invoices/invoices-client.tsx | 2 +- .../business/proposals/proposals-client.tsx | 2 +- app/(dashboard)/clients/clients-client.tsx | 53 +++++-------- app/(dashboard)/clients/page.tsx | 2 - app/(dashboard)/dashboard-client.tsx | 4 +- app/(dashboard)/finance/finance-client.tsx | 6 +- app/(dashboard)/projects/[id]/page.tsx | 3 +- .../projects/[id]/project-detail-client.tsx | 77 ++++++++++++++----- app/(dashboard)/projects/projects-client.tsx | 33 ++++---- app/(dashboard)/tasks/tasks-client.tsx | 39 ++++++---- 11 files changed, 131 insertions(+), 92 deletions(-) diff --git a/app/(dashboard)/analytics/analytics-client.tsx b/app/(dashboard)/analytics/analytics-client.tsx index fb772d7..6b29c0e 100644 --- a/app/(dashboard)/analytics/analytics-client.tsx +++ b/app/(dashboard)/analytics/analytics-client.tsx @@ -120,7 +120,7 @@ export function AnalyticsClient({ data }: AnalyticsClientProps) {

{label}

- {payload.map((entry: any, index: number) => ( + {payload.map((entry, index) => (
diff --git a/app/(dashboard)/business/invoices/invoices-client.tsx b/app/(dashboard)/business/invoices/invoices-client.tsx index 6b39516..d78f284 100644 --- a/app/(dashboard)/business/invoices/invoices-client.tsx +++ b/app/(dashboard)/business/invoices/invoices-client.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { format } from "date-fns"; import { tr } from "date-fns/locale"; -import { Receipt, Plus, MoreHorizontal, FileEdit, Trash2, Send, Download, CheckCircle2 } from "lucide-react"; +import { Plus, MoreHorizontal, FileEdit, Trash2, Send, Download, CheckCircle2 } from "lucide-react"; import { Button, Card, CardContent, Badge } from "poyraz-ui/atoms"; import { DropdownMenu, diff --git a/app/(dashboard)/business/proposals/proposals-client.tsx b/app/(dashboard)/business/proposals/proposals-client.tsx index 083cf20..b620c7e 100644 --- a/app/(dashboard)/business/proposals/proposals-client.tsx +++ b/app/(dashboard)/business/proposals/proposals-client.tsx @@ -3,7 +3,7 @@ import { useState } from "react"; import { format } from "date-fns"; import { tr } from "date-fns/locale"; -import { FileText, Plus, MoreHorizontal, FileEdit, Trash2, Mail, CheckCircle2, XCircle } from "lucide-react"; +import { Plus, MoreHorizontal, FileEdit, Trash2, Mail, CheckCircle2, XCircle } from "lucide-react"; import { Button, Card, CardContent, Badge } from "poyraz-ui/atoms"; import { DropdownMenu, diff --git a/app/(dashboard)/clients/clients-client.tsx b/app/(dashboard)/clients/clients-client.tsx index ed4e37e..37e0034 100644 --- a/app/(dashboard)/clients/clients-client.tsx +++ b/app/(dashboard)/clients/clients-client.tsx @@ -1,7 +1,6 @@ "use client"; import { - archiveClientRecord, createClientRecord, updateClientRecord, updateClientPipelineStage, @@ -28,10 +27,7 @@ import { toast, } from "poyraz-ui/molecules"; import { - Archive, - ExternalLink, Mail, - PauseCircle, Pencil, Phone, Plus, @@ -45,7 +41,6 @@ import Link from "next/link"; import { useState } from "react"; import { format, isPast, isToday } from "date-fns"; import { tr } from "date-fns/locale"; -import { useEffect } from "react"; import { cn } from "@/lib/utils"; import { StatCard } from "@/components/system/stat-card"; @@ -68,19 +63,13 @@ export type ClientListItem = { client_value_score: number; }; -const statusLabels = { - active: "Aktif", - paused: "Duraklatıldı", - archived: "Arşivlendi", -}; +type ClientPipelineStage = ClientListItem["pipeline_stage"]; -const statusClasses = { - active: "border-emerald-200 bg-emerald-50 text-emerald-700", - paused: "border-amber-200 bg-amber-50 text-amber-700", - archived: "border-zinc-200 bg-zinc-50 text-zinc-600", -}; - -const pipelineStages = [ +const pipelineStages: Array<{ + id: ClientPipelineStage; + label: string; + color: string; +}> = [ { id: "lead", label: "Potansiyel (Lead)", color: "border-slate-200 bg-slate-50 text-slate-700" }, { id: "contacted", label: "İletişime Geçildi", color: "border-blue-200 bg-blue-50 text-blue-700" }, { id: "proposal_sent", label: "Teklif İletildi", color: "border-amber-200 bg-amber-50 text-amber-700" }, @@ -92,26 +81,24 @@ type ClientsClientProps = { clients: ClientListItem[]; totalRevenue: number; activeCount: number; - pausedCount: number; - archivedCount: number; }; export function ClientsClient({ clients, totalRevenue, activeCount, - pausedCount, - archivedCount, }: ClientsClientProps) { const [query, setQuery] = useState(""); const normalizedQuery = query.trim().toLowerCase(); const [draggedClientId, setDraggedClientId] = useState(null); - const [localClients, setLocalClients] = useState(clients); - - useEffect(() => { - setLocalClients(clients); - }, [clients]); + const [pipelineOverrides, setPipelineOverrides] = useState< + Partial> + >({}); + const localClients = clients.map((client) => ({ + ...client, + pipeline_stage: pipelineOverrides[client.id] ?? client.pipeline_stage, + })); function handleDragStart(event: React.DragEvent, clientId: string) { setDraggedClientId(clientId); @@ -119,7 +106,7 @@ export function ClientsClient({ event.dataTransfer.setData("text/plain", clientId); } - async function handleDrop(newStage: string) { + async function handleDrop(newStage: ClientPipelineStage) { if (!draggedClientId) return; const clientId = draggedClientId; @@ -128,15 +115,17 @@ export function ClientsClient({ const client = localClients.find(c => c.id === clientId); if (!client || client.pipeline_stage === newStage) return; - setLocalClients(prev => - prev.map(c => c.id === clientId ? { ...c, pipeline_stage: newStage as any } : c) - ); + const previousStage = client.pipeline_stage; + setPipelineOverrides((current) => ({ ...current, [clientId]: newStage })); try { - await updateClientPipelineStage(clientId, newStage as any); + await updateClientPipelineStage(clientId, newStage); toast.success("Müşteri aşaması güncellendi."); } catch (error) { - setLocalClients(clients); + setPipelineOverrides((current) => ({ + ...current, + [clientId]: previousStage, + })); toast.error( error instanceof Error ? error.message diff --git a/app/(dashboard)/clients/page.tsx b/app/(dashboard)/clients/page.tsx index 721cee8..9780bba 100644 --- a/app/(dashboard)/clients/page.tsx +++ b/app/(dashboard)/clients/page.tsx @@ -57,8 +57,6 @@ export default async function ClientsPage() { clients={clients} totalRevenue={clients.reduce((sum, client) => sum + client.revenueTotal, 0)} activeCount={clients.filter((client) => client.status === "active").length} - pausedCount={clients.filter((client) => client.status === "paused").length} - archivedCount={clients.filter((client) => client.status === "archived").length} /> ); } diff --git a/app/(dashboard)/dashboard-client.tsx b/app/(dashboard)/dashboard-client.tsx index 9d2470c..4e91863 100644 --- a/app/(dashboard)/dashboard-client.tsx +++ b/app/(dashboard)/dashboard-client.tsx @@ -125,14 +125,14 @@ export function DashboardClient({ data }: DashboardClientProps) {

{label}

- {payload.map((entry: any, index: number) => ( + {payload.map((entry, index) => (
{entry.name === 'income' ? 'Gelir' : 'Gider'}
- {formatCurrency(entry.value)} + {formatCurrency(Number(entry.value ?? 0))}
))} diff --git a/app/(dashboard)/finance/finance-client.tsx b/app/(dashboard)/finance/finance-client.tsx index 80b9102..866172d 100644 --- a/app/(dashboard)/finance/finance-client.tsx +++ b/app/(dashboard)/finance/finance-client.tsx @@ -644,8 +644,10 @@ function AIFinanceDialog() { throw new Error(data.error || "Bilinmeyen bir hata oluştu."); } setResult(data.text); - } catch (err: any) { - setResult("Hata: " + err.message); + } catch (error) { + setResult( + `Hata: ${error instanceof Error ? error.message : "Bilinmeyen bir hata oluştu."}`, + ); } finally { setLoading(false); } diff --git a/app/(dashboard)/projects/[id]/page.tsx b/app/(dashboard)/projects/[id]/page.tsx index 1bdc742..eaa509d 100644 --- a/app/(dashboard)/projects/[id]/page.tsx +++ b/app/(dashboard)/projects/[id]/page.tsx @@ -5,6 +5,7 @@ import { type ProjectDetailTaskItem, type ProjectFinanceItem, type ProjectPlanningSectionItem, + type ProjectRevisionItem, } from "@/app/(dashboard)/projects/[id]/project-detail-client"; import { DomainError } from "@/server/domain/errors"; import { requireFreelancerBackend } from "@/server/web/freelancer"; @@ -18,7 +19,7 @@ export default async function ProjectDetailPage({ params }: { params: Promise<{ sections: ProjectPlanningSectionItem[]; tasks: ProjectDetailTaskItem[]; financeTransactions: ProjectFinanceItem[]; - revisions: Array>; + revisions: ProjectRevisionItem[]; }; try { const row = service.getProject(actor, id); diff --git a/app/(dashboard)/projects/[id]/project-detail-client.tsx b/app/(dashboard)/projects/[id]/project-detail-client.tsx index b983579..84d0d4a 100644 --- a/app/(dashboard)/projects/[id]/project-detail-client.tsx +++ b/app/(dashboard)/projects/[id]/project-detail-client.tsx @@ -46,7 +46,8 @@ import { Trash2, Wallet, } from "lucide-react"; -import { useEffect, useState, useTransition, type DragEvent } from "react"; +import Image from "next/image"; +import { useState, useTransition, type DragEvent } from "react"; export type ProjectDetail = { id: string; @@ -105,12 +106,20 @@ export type ProjectFinanceItem = { category: string | null; }; +export type ProjectRevisionItem = { + id: string; + description: string; + status: "pending" | "in_progress" | "completed" | "rejected"; + created_at: string; + requested_by: string; +}; + type ProjectDetailClientProps = { project: ProjectDetail; sections: ProjectPlanningSectionItem[]; tasks: ProjectDetailTaskItem[]; financeTransactions: ProjectFinanceItem[]; - revisions: any[]; + revisions: ProjectRevisionItem[]; }; const typeLabels = { @@ -239,11 +248,14 @@ export function ProjectDetailClient({ {project.coverImageUrl ? ( -
- + {project.cover_image_alt
) : ( @@ -339,16 +351,29 @@ export function ProjectDetailClient({ ); } -function RevisionsPanel({ projectId, revisions }: { projectId: string; revisions: any[] }) { +function RevisionsPanel({ + projectId, + revisions, +}: { + projectId: string; + revisions: ProjectRevisionItem[]; +}) { const [isUpdating, setIsUpdating] = useState(false); - async function handleStatusChange(id: string, status: string) { + async function handleStatusChange( + id: string, + status: ProjectRevisionItem["status"], + ) { setIsUpdating(true); try { const { updateRevisionStatus } = await import("@/app/(dashboard)/projects/actions"); await updateRevisionStatus(id, projectId, status); - } catch (err: any) { - console.error(err); + } catch (error) { + toast.error( + error instanceof Error + ? error.message + : "Revizyon durumu güncellenemedi.", + ); } finally { setIsUpdating(false); } @@ -370,7 +395,12 @@ function RevisionsPanel({ projectId, revisions }: { projectId: string; revisions