From 74ef1108e1d222337e6bc4420f306e192b33308a Mon Sep 17 00:00:00 2001 From: ivannoskov Date: Mon, 2 Feb 2026 11:17:50 +0300 Subject: [PATCH] feat: some fixes --- .../creatives/[creativeId]/page.tsx | 386 ++++++++++++------ .../[workspaceId]/creatives/new/page.tsx | 23 +- .../[workspaceId]/creatives/page.tsx | 278 ++++++++----- .../[workspaceId]/placements/new/page.tsx | 31 +- .../[workspaceId]/placements/page.tsx | 43 +- .../purchase-plans/[projectId]/page.tsx | 17 +- components/dialog-create-placements.tsx | 147 ++++++- components/telegram-post-preview.tsx | 226 ++++++++++ lib/demo/mock-data.ts | 40 +- lib/types/api.ts | 16 + 10 files changed, 945 insertions(+), 262 deletions(-) create mode 100644 components/telegram-post-preview.tsx diff --git a/app/dashboard/[workspaceId]/creatives/[creativeId]/page.tsx b/app/dashboard/[workspaceId]/creatives/[creativeId]/page.tsx index 75cd707..82f2837 100644 --- a/app/dashboard/[workspaceId]/creatives/[creativeId]/page.tsx +++ b/app/dashboard/[workspaceId]/creatives/[creativeId]/page.tsx @@ -12,10 +12,15 @@ import { ArrowLeft, Pencil, Archive, - Trash2, Copy, Check, - ExternalLink, + Eye, + LayoutList, + Plus, + BarChart3, + FileText, + Image, + Video, } from "lucide-react"; import { DashboardHeader } from "@/components/layout/dashboard-header"; import { useWorkspace } from "@/components/providers/workspace-provider"; @@ -43,6 +48,19 @@ import { AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@/components/ui/tabs"; +import { TelegramPostPreview } from "@/components/telegram-post-preview"; import type { Creative } from "@/lib/types/api"; // ============================================================================ @@ -62,8 +80,8 @@ export default function CreativeDetailPage() { const [isEditing, setIsEditing] = useState(searchParams.get("edit") === "true"); const [isSaving, setIsSaving] = useState(false); const [copied, setCopied] = useState(false); + const [viewMode, setViewMode] = useState<"preview" | "data">("preview"); - // Edit form state const [name, setName] = useState(""); const [text, setText] = useState(""); const [error, setError] = useState(null); @@ -72,6 +90,7 @@ export default function CreativeDetailPage() { useEffect(() => { loadCreative(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [workspaceId, creativeId]); const loadCreative = async () => { @@ -110,8 +129,9 @@ export default function CreativeDetailPage() { setCreative(updated); setIsEditing(false); - } catch (err: any) { - setError(err?.detail || "Не удалось сохранить"); + } catch (err) { + const errorMessage = err && typeof err === 'object' && 'detail' in err ? (err as { detail?: string }).detail ?? "Не удалось сохранить" : "Не удалось сохранить"; + setError(errorMessage); } finally { setIsSaving(false); } @@ -121,8 +141,7 @@ export default function CreativeDetailPage() { if (!creative) return; try { - // Toggle archive status by updating via delete endpoint (soft delete) - await creativesApi.delete(workspaceId, creativeId); + await creativesApi.update(workspaceId, creativeId, { status: "archived" }); router.push(`/dashboard/${workspaceId}/creatives`); } catch (err) { console.error("Failed to archive:", err); @@ -173,6 +192,8 @@ export default function CreativeDetailPage() { ); } + const isActive = creative.status === "active"; + return ( <> -
+

@@ -214,6 +231,38 @@ export default function CreativeDetailPage() { {canWrite && !isEditing && (

+ {isActive && ( + + )} + + + + + + + + + Все размещения + + + + + + Аналитика + + + +
- {isEditing ? ( - - - Редактирование - - Изменения не повлияют на существующие размещения - - - -
- - setName(e.target.value)} - disabled={isSaving} - /> -
- -
- -