import { defineStore } from 'pinia' export type PageStatus = 'live' | 'draft' | 'paused' export type PageSortBy = | 'updated' | 'name' | 'leads' | 'visitors' | 'variants' export interface CampaignLabel { id: string name: string } export interface AdminPage { id: string campaignId: string name: string domain: string routePath: string status: PageStatus leadCount: number visitorCount: number variantCount: number updatedAt: string } const campaigns: CampaignLabel[] = [ { id: 'p1', name: 'Q3 마케팅 캠페인' }, { id: 'p2', name: '블랙프라이데이 2023' }, { id: 'p3', name: 'SaaS 웨비나 시리즈' }, { id: 'p4', name: 'Product Hunt 론칭' } ] const pageSource: AdminPage[] = [ { id: 'lp01', campaignId: 'p1', name: '메인 랜딩', domain: 'summer.ad-camp.kr', routePath: '/', status: 'live', leadCount: 124, visitorCount: 2400, variantCount: 2, updatedAt: '2026-03-04T09:12:00.000Z' }, { id: 'lp02', campaignId: 'p1', name: '오퍼 페이지 B', domain: 'summer.ad-camp.kr', routePath: '/offer', status: 'draft', leadCount: 16, visitorCount: 420, variantCount: 1, updatedAt: '2026-03-03T18:05:00.000Z' }, { id: 'lp03', campaignId: 'p2', name: '구글 전용 랜딩', domain: 'weekend.offer.kr', routePath: '/google', status: 'live', leadCount: 88, visitorCount: 1210, variantCount: 3, updatedAt: '2026-03-01T13:40:00.000Z' }, { id: 'lp04', campaignId: 'p2', name: '일반 버전', domain: 'weekend.offer.kr', routePath: '/', status: 'paused', leadCount: 22, visitorCount: 540, variantCount: 1, updatedAt: '2026-02-28T06:25:00.000Z' }, { id: 'lp05', campaignId: 'p4', name: '리타겟 랜딩', domain: 'retarget.example.com', routePath: '/', status: 'draft', leadCount: 0, visitorCount: 40, variantCount: 1, updatedAt: '2026-03-02T22:17:00.000Z' } ] const statusRank: Record = { live: 0, draft: 1, paused: 2 } const statusLabel = (status: PageStatus) => { if (status === 'live') { return '라이브' } if (status === 'paused') { return '일시정지' } return '초안' } export const usePagesStore = defineStore('admin-pages', { state: () => ({ pages: pageSource, campaigns, searchQuery: '', campaignFilter: 'all' as 'all' | string, statusFilter: 'all' as 'all' | PageStatus, sortBy: 'updated' as PageSortBy }), getters: { filteredPages: (state): AdminPage[] => { const query = state.searchQuery.trim().toLowerCase() const result = state.pages .filter((page) => { const text = `${page.name} ${page.domain} ${page.routePath}`.toLowerCase() const searchOk = query === '' || text.includes(query) const campaignOk = state.campaignFilter === 'all' || page.campaignId === state.campaignFilter const statusOk = state.statusFilter === 'all' || page.status === state.statusFilter return searchOk && campaignOk && statusOk }) .sort((a, b) => { if (state.sortBy === 'name') { return a.name.localeCompare(b.name) } if (state.sortBy === 'leads') { return b.leadCount - a.leadCount } if (state.sortBy === 'visitors') { return b.visitorCount - a.visitorCount } if (state.sortBy === 'variants') { return b.variantCount - a.variantCount } return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime() }) return result }, campaignOptions: (state): CampaignLabel[] => state.campaigns }, actions: { setSearchQuery(value: string) { this.searchQuery = value }, setCampaignFilter(value: 'all' | string) { this.campaignFilter = value }, setStatusFilter(value: 'all' | PageStatus) { this.statusFilter = value }, setSortBy(value: PageSortBy) { this.sortBy = value }, removePage(pageId: string) { this.pages = this.pages.filter((page) => page.id !== pageId) }, createQuickPage() { const campaign = this.campaigns[this.pages.length % this.campaigns.length] this.createPage({ name: `새 페이지 ${this.pages.length + 1}`, campaignId: campaign.id, domain: 'ad-camp-temp.test', routePath: `/lp-${this.pages.length + 1}` }) }, createPage(payload: { name: string campaignId: string domain: string routePath: string }) { const normalizedRoute = payload.routePath.trim().startsWith('/') ? payload.routePath.trim() : `/${payload.routePath.trim()}` const normalizedDomain = payload.domain.trim() const newPage: AdminPage = { id: `lp-${Date.now()}`, campaignId: payload.campaignId, name: payload.name.trim(), domain: normalizedDomain, routePath: normalizedRoute, status: 'draft', leadCount: 0, visitorCount: 0, variantCount: 1, updatedAt: new Date().toISOString() } this.pages.unshift(newPage) }, statusClass(status: PageStatus) { if (status === 'live') { return { label: statusLabel(status), chipClass: 'text-emerald-200 bg-emerald-400/10', dotClass: 'bg-emerald-300' } } if (status === 'paused') { return { label: statusLabel(status), chipClass: 'text-slate-300 bg-slate-500/10', dotClass: 'bg-slate-400' } } return { label: statusLabel(status), chipClass: 'text-amber-200 bg-amber-400/10', dotClass: 'bg-amber-300' } }, campaignName(campaignId: string) { return ( this.campaigns.find((campaign) => campaign.id === campaignId)?.name || campaignId || '미지정' ) }, previewUrl(page: AdminPage) { return `https://${page.domain}${page.routePath}` } } })