From 3beabcfe7f184babc7b61c29778f45bb2f4f2c51 Mon Sep 17 00:00:00 2001 From: claude Date: Thu, 12 Mar 2026 15:17:31 +0000 Subject: [PATCH] update migrate --- src/components/DashboardNav.vue | 2 +- src/routes/admin/AdTemplates.vue | 225 +++++++++++--- src/routes/admin/Agents.vue | 255 ++++++++++++---- src/routes/admin/Jobs.vue | 275 ++++++++++++----- src/routes/admin/Layout.vue | 85 +++++- src/routes/admin/Logs.vue | 92 ++++-- src/routes/admin/Overview.vue | 107 +++++-- src/routes/admin/Payments.vue | 249 ++++++++++++--- src/routes/admin/Plans.vue | 165 +++++++--- src/routes/admin/Users.vue | 269 ++++++++++++---- src/routes/admin/Videos.vue | 287 ++++++++++++++---- .../admin/components/AdminSectionShell.vue | 37 ++- src/server/middlewares/setup.ts | 48 ++- 13 files changed, 1660 insertions(+), 436 deletions(-) diff --git a/src/components/DashboardNav.vue b/src/components/DashboardNav.vue index e9c2494..09952c8 100644 --- a/src/components/DashboardNav.vue +++ b/src/components/DashboardNav.vue @@ -44,7 +44,7 @@ const links = computed>(() => { ...baseLinks, { href: "/admin/overview", - label: "Admin", + label: "Admin Console", icon: LayoutDashboard, action: null, className, diff --git a/src/routes/admin/AdTemplates.vue b/src/routes/admin/AdTemplates.vue index 24089a3..dfd41a9 100644 --- a/src/routes/admin/AdTemplates.vue +++ b/src/routes/admin/AdTemplates.vue @@ -6,18 +6,27 @@ import AppInput from "@/components/app/AppInput.vue"; import { computed, onMounted, reactive, ref } from "vue"; import AdminSectionShell from "./components/AdminSectionShell.vue"; -type AdminAdTemplateRow = any; +type ListTemplatesResponse = Awaited>; +type AdminAdTemplateRow = NonNullable[number]; + +const formatOptions = ["pre-roll", "mid-roll", "post-roll"] as const; const loading = ref(true); const submitting = ref(false); const error = ref(null); const actionError = ref(null); const rows = ref([]); +const total = ref(0); +const limit = ref(12); +const page = ref(1); const selectedRow = ref(null); +const search = ref(""); +const appliedSearch = ref(""); +const ownerFilter = ref(""); +const appliedOwnerFilter = ref(""); const createOpen = ref(false); const editOpen = ref(false); const deleteOpen = ref(false); -const formatOptions = ["pre-roll", "mid-roll", "post-roll"]; const createForm = reactive({ userId: "", @@ -44,13 +53,43 @@ const editForm = reactive({ const canCreate = computed(() => createForm.userId.trim() && createForm.name.trim() && createForm.vastTagUrl.trim()); const canUpdate = computed(() => editForm.id.trim() && editForm.userId.trim() && editForm.name.trim() && editForm.vastTagUrl.trim()); +const totalPages = computed(() => Math.max(1, Math.ceil((total.value || 0) / limit.value))); +const summary = computed(() => [ + { label: "Visible templates", value: rows.value.length }, + { label: "Active", value: rows.value.filter((row) => row.isActive).length }, + { label: "Default", value: rows.value.filter((row) => row.isDefault).length }, + { label: "Total records", value: total.value }, +]); +const selectedMeta = computed(() => { + if (!selectedRow.value) return []; + return [ + { label: "Owner", value: selectedRow.value.ownerEmail || selectedRow.value.userId || "—" }, + { label: "Format", value: selectedRow.value.adFormat || "—" }, + { label: "Status", value: selectedRow.value.isActive ? "ACTIVE" : "INACTIVE" }, + { label: "Default", value: selectedRow.value.isDefault ? "YES" : "NO" }, + { label: "Duration", value: selectedRow.value.duration ? `${selectedRow.value.duration}s` : "—" }, + { label: "Created", value: formatDate(selectedRow.value.createdAt) }, + ]; +}); const loadTemplates = async () => { loading.value = true; error.value = null; try { - const response = await rpcClient.listAdminAdTemplates({ page: 1, limit: 20 }); + const response = await rpcClient.listAdminAdTemplates({ + page: page.value, + limit: limit.value, + userId: appliedOwnerFilter.value.trim() || undefined, + search: appliedSearch.value.trim() || undefined, + }); rows.value = response.templates ?? []; + total.value = response.total ?? rows.value.length; + limit.value = response.limit ?? limit.value; + page.value = response.page ?? page.value; + if (selectedRow.value?.id) { + const fresh = rows.value.find((row) => row.id === selectedRow.value?.id); + if (fresh) selectedRow.value = fresh; + } } catch (err: any) { error.value = err?.message || "Failed to load admin ad templates"; } finally { @@ -73,10 +112,16 @@ const closeDialogs = () => { createOpen.value = false; editOpen.value = false; deleteOpen.value = false; - selectedRow.value = null; actionError.value = null; }; +const applyFilters = async () => { + page.value = 1; + appliedSearch.value = search.value; + appliedOwnerFilter.value = ownerFilter.value; + await loadTemplates(); +}; + const openEditDialog = (row: AdminAdTemplateRow) => { selectedRow.value = row; actionError.value = null; @@ -140,7 +185,6 @@ const submitEdit = async () => { isDefault: editForm.isDefault, }); editOpen.value = false; - selectedRow.value = null; await loadTemplates(); } catch (err: any) { actionError.value = err?.message || "Failed to update ad template"; @@ -157,6 +201,7 @@ const submitDelete = async () => { await rpcClient.deleteAdminAdTemplate({ id: selectedRow.value.id }); deleteOpen.value = false; selectedRow.value = null; + if (page.value > 1 && rows.value.length === 1) page.value -= 1; await loadTemplates(); } catch (err: any) { actionError.value = err?.message || "Failed to delete ad template"; @@ -165,59 +210,143 @@ const submitDelete = async () => { } }; +const previousPage = async () => { + if (page.value <= 1) return; + page.value -= 1; + await loadTemplates(); +}; + +const nextPage = async () => { + if (page.value >= totalPages.value) return; + page.value += 1; + await loadTemplates(); +}; + +const formatDate = (value?: string) => { + if (!value) return "—"; + const date = new Date(value); + return Number.isNaN(date.getTime()) ? value : date.toLocaleString(); +}; + onMounted(loadTemplates);