macbook 에서 리눅스로 이동
This commit is contained in:
156
frontend/app/stores/projects.ts
Normal file
156
frontend/app/stores/projects.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export type ProjectStatus = 'active' | 'archived' | 'draft'
|
||||
|
||||
export type ProjectSortBy = 'newest' | 'oldest' | 'most-leads' | 'most-variants'
|
||||
|
||||
export type ProjectStatusFilter = 'all' | ProjectStatus
|
||||
|
||||
export interface ProjectCard {
|
||||
id: string
|
||||
title: string
|
||||
subtitle: string
|
||||
status: ProjectStatus
|
||||
leads: string
|
||||
metricLabel: string
|
||||
metricValue: string
|
||||
trend: string
|
||||
trendUp: boolean
|
||||
variants: number
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
const projectSource: ProjectCard[] = [
|
||||
{
|
||||
id: 'p1',
|
||||
title: 'Q3 마케팅 캠페인',
|
||||
subtitle: '2일 전 생성',
|
||||
status: 'active',
|
||||
leads: '1,240',
|
||||
metricLabel: '전환율',
|
||||
metricValue: '4.8%',
|
||||
trend: '+12%',
|
||||
trendUp: true,
|
||||
variants: 3,
|
||||
createdAt: '2026-03-01T09:00:00.000Z'
|
||||
},
|
||||
{
|
||||
id: 'p2',
|
||||
title: '블랙프라이데이 2023',
|
||||
subtitle: '2023년 12월 1일 종료',
|
||||
status: 'archived',
|
||||
leads: '5,100',
|
||||
metricLabel: '방문자',
|
||||
metricValue: '42.5k',
|
||||
trend: '종료',
|
||||
trendUp: false,
|
||||
variants: 3,
|
||||
createdAt: '2023-12-01T03:00:00.000Z'
|
||||
},
|
||||
{
|
||||
id: 'p3',
|
||||
title: 'SaaS 웨비나 시리즈',
|
||||
subtitle: '4시간 전 수정됨',
|
||||
status: 'draft',
|
||||
leads: '0',
|
||||
metricLabel: '노출 수',
|
||||
metricValue: '12k',
|
||||
trend: '+18%',
|
||||
trendUp: true,
|
||||
variants: 2,
|
||||
createdAt: '2026-03-04T01:20:00.000Z'
|
||||
},
|
||||
{
|
||||
id: 'p4',
|
||||
title: 'Product Hunt 런칭',
|
||||
subtitle: '2주간 운영중',
|
||||
status: 'active',
|
||||
leads: '892',
|
||||
metricLabel: '클릭률',
|
||||
metricValue: '2.1%',
|
||||
trend: '-2%',
|
||||
trendUp: false,
|
||||
variants: 1,
|
||||
createdAt: '2026-02-12T16:30:00.000Z'
|
||||
}
|
||||
]
|
||||
|
||||
const toLeadNumber = (value: string) => {
|
||||
const trimmed = value.trim().toLowerCase().replace(/,/g, '')
|
||||
const numeric = Number(trimmed.replace('k', ''))
|
||||
|
||||
if (Number.isNaN(numeric)) {
|
||||
return 0
|
||||
}
|
||||
|
||||
return trimmed.endsWith('k') ? numeric * 1000 : numeric
|
||||
}
|
||||
|
||||
export const useProjectsStore = defineStore('admin-projects', {
|
||||
state: () => ({
|
||||
projects: projectSource,
|
||||
searchQuery: '',
|
||||
statusFilter: 'all' as ProjectStatusFilter,
|
||||
sortBy: 'newest' as ProjectSortBy
|
||||
}),
|
||||
getters: {
|
||||
filteredProjects: (state): ProjectCard[] => {
|
||||
const query = state.searchQuery.trim().toLowerCase()
|
||||
const list = state.projects
|
||||
.filter((project) => {
|
||||
const target = `${project.title} ${project.subtitle}`.toLowerCase()
|
||||
const matchQuery = query === '' || target.includes(query)
|
||||
const matchStatus =
|
||||
state.statusFilter === 'all' || project.status === state.statusFilter
|
||||
|
||||
return matchQuery && matchStatus
|
||||
})
|
||||
.sort((a, b) => {
|
||||
if (state.sortBy === 'oldest') {
|
||||
return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
|
||||
}
|
||||
|
||||
if (state.sortBy === 'most-leads') {
|
||||
return toLeadNumber(b.leads) - toLeadNumber(a.leads)
|
||||
}
|
||||
|
||||
if (state.sortBy === 'most-variants') {
|
||||
return b.variants - a.variants
|
||||
}
|
||||
|
||||
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
||||
})
|
||||
|
||||
return list
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
createProject(input: { name: string; campaignName: string }) {
|
||||
const now = new Date().toISOString()
|
||||
const id = `p-${Date.now().toString(36)}`
|
||||
|
||||
this.projects.unshift({
|
||||
id,
|
||||
title: input.name.trim(),
|
||||
subtitle: `${input.campaignName.trim()}에서 생성`,
|
||||
status: 'draft',
|
||||
leads: '0',
|
||||
metricLabel: '전환율',
|
||||
metricValue: '-',
|
||||
trend: '신규',
|
||||
trendUp: true,
|
||||
variants: 0,
|
||||
createdAt: now
|
||||
})
|
||||
},
|
||||
setSearchQuery(value: string) {
|
||||
this.searchQuery = value
|
||||
},
|
||||
setStatusFilter(value: ProjectStatusFilter) {
|
||||
this.statusFilter = value
|
||||
},
|
||||
setSortBy(value: ProjectSortBy) {
|
||||
this.sortBy = value
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user