feat(app): implement all sub-pages and admin management pages
Sub-pages: card purchase with WeChat Pay flow, my memberships with progress bars, my bookings with tabs, personal info editor Admin: management center grid, week template CRUD, slot adjustment, member management with search, order list with filters, card type CRUD with form modal, studio settings editor Admin Pinia store for all admin API calls
This commit is contained in:
170
packages/app/src/stores/admin.ts
Normal file
170
packages/app/src/stores/admin.ts
Normal file
@@ -0,0 +1,170 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import { get, post, put, del } from '../utils/request'
|
||||
import type {
|
||||
WeekTemplate,
|
||||
WeekTemplateInput,
|
||||
CardType,
|
||||
CreateCardTypeDto,
|
||||
UpdateCardTypeDto,
|
||||
StudioConfig,
|
||||
UpdateStudioConfigDto,
|
||||
OrderWithDetails,
|
||||
TimeSlot,
|
||||
CreateManualSlotDto,
|
||||
PaginatedData,
|
||||
} from '@mp-pilates/shared'
|
||||
|
||||
export interface AdminStats {
|
||||
todayBookings: number
|
||||
totalOrders: number
|
||||
totalBookings: number
|
||||
}
|
||||
|
||||
export interface MemberSummary {
|
||||
userId: string
|
||||
nickname: string
|
||||
phone: string | null
|
||||
avatarUrl: string | null
|
||||
totalBookings: number
|
||||
completedBookings: number
|
||||
cancelledBookings: number
|
||||
}
|
||||
|
||||
export const useAdminStore = defineStore('admin', () => {
|
||||
// ── Week templates ───────────────────────────────────────────────
|
||||
const weekTemplates = ref<WeekTemplate[]>([])
|
||||
|
||||
async function fetchWeekTemplates(): Promise<WeekTemplate[]> {
|
||||
const data = await get<WeekTemplate[]>('/admin/week-template')
|
||||
weekTemplates.value = data
|
||||
return data
|
||||
}
|
||||
|
||||
async function saveWeekTemplates(templates: WeekTemplateInput[]): Promise<WeekTemplate[]> {
|
||||
const data = await put<WeekTemplate[]>('/admin/week-template', templates)
|
||||
weekTemplates.value = data
|
||||
return data
|
||||
}
|
||||
|
||||
// ── Card types ───────────────────────────────────────────────────
|
||||
const cardTypes = ref<CardType[]>([])
|
||||
|
||||
async function fetchCardTypes(): Promise<CardType[]> {
|
||||
const data = await get<CardType[]>('/admin/card-types')
|
||||
cardTypes.value = [...data].sort((a, b) => a.sortOrder - b.sortOrder)
|
||||
return cardTypes.value
|
||||
}
|
||||
|
||||
async function createCardType(dto: CreateCardTypeDto): Promise<CardType> {
|
||||
const data = await post<CardType>('/admin/card-types', dto)
|
||||
await fetchCardTypes()
|
||||
return data
|
||||
}
|
||||
|
||||
async function updateCardType(id: string, dto: UpdateCardTypeDto): Promise<CardType> {
|
||||
const data = await put<CardType>(`/admin/card-types/${id}`, dto)
|
||||
await fetchCardTypes()
|
||||
return data
|
||||
}
|
||||
|
||||
async function deleteCardType(id: string): Promise<void> {
|
||||
await del(`/admin/card-types/${id}`)
|
||||
await fetchCardTypes()
|
||||
}
|
||||
|
||||
// ── Studio config ────────────────────────────────────────────────
|
||||
const studioConfig = ref<StudioConfig | null>(null)
|
||||
|
||||
async function fetchStudioConfig(): Promise<StudioConfig> {
|
||||
const data = await get<StudioConfig>('/studio/info')
|
||||
studioConfig.value = data
|
||||
return data
|
||||
}
|
||||
|
||||
async function saveStudioConfig(dto: UpdateStudioConfigDto): Promise<StudioConfig> {
|
||||
const data = await put<StudioConfig>('/admin/studio/info', dto)
|
||||
studioConfig.value = data
|
||||
return data
|
||||
}
|
||||
|
||||
// ── Orders ───────────────────────────────────────────────────────
|
||||
async function fetchAdminOrders(params: {
|
||||
page?: number
|
||||
limit?: number
|
||||
status?: string
|
||||
}): Promise<PaginatedData<OrderWithDetails>> {
|
||||
return get<PaginatedData<OrderWithDetails>>('/admin/orders', params)
|
||||
}
|
||||
|
||||
// ── Bookings ─────────────────────────────────────────────────────
|
||||
async function fetchAdminBookings(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
userId?: string
|
||||
}): Promise<PaginatedData<any>> {
|
||||
return get<PaginatedData<any>>('/admin/bookings', params)
|
||||
}
|
||||
|
||||
// ── Members ──────────────────────────────────────────────────────
|
||||
async function fetchMembers(params?: {
|
||||
page?: number
|
||||
limit?: number
|
||||
search?: string
|
||||
}): Promise<PaginatedData<MemberSummary>> {
|
||||
return get<PaginatedData<MemberSummary>>('/admin/members', params)
|
||||
}
|
||||
|
||||
// ── Time slots ───────────────────────────────────────────────────
|
||||
async function fetchSlotsByDate(date: string): Promise<TimeSlot[]> {
|
||||
return get<TimeSlot[]>('/admin/time-slots', { date })
|
||||
}
|
||||
|
||||
async function createManualSlot(dto: CreateManualSlotDto): Promise<TimeSlot> {
|
||||
return post<TimeSlot>('/admin/time-slot/manual', dto)
|
||||
}
|
||||
|
||||
async function closeSlot(id: string): Promise<TimeSlot> {
|
||||
return put<TimeSlot>(`/admin/time-slot/${id}/close`, {})
|
||||
}
|
||||
|
||||
async function generateSlots(startDate: string, endDate: string): Promise<{ count: number }> {
|
||||
return post<{ count: number }>('/admin/generate-slots', { startDate, endDate })
|
||||
}
|
||||
|
||||
// ── Dashboard stats ──────────────────────────────────────────────
|
||||
async function fetchDashboardStats(): Promise<AdminStats> {
|
||||
return get<AdminStats>('/admin/stats')
|
||||
}
|
||||
|
||||
return {
|
||||
// State
|
||||
weekTemplates,
|
||||
cardTypes,
|
||||
studioConfig,
|
||||
// Week templates
|
||||
fetchWeekTemplates,
|
||||
saveWeekTemplates,
|
||||
// Card types
|
||||
fetchCardTypes,
|
||||
createCardType,
|
||||
updateCardType,
|
||||
deleteCardType,
|
||||
// Studio
|
||||
fetchStudioConfig,
|
||||
saveStudioConfig,
|
||||
// Orders
|
||||
fetchAdminOrders,
|
||||
// Bookings
|
||||
fetchAdminBookings,
|
||||
// Members
|
||||
fetchMembers,
|
||||
// Time slots
|
||||
fetchSlotsByDate,
|
||||
createManualSlot,
|
||||
closeSlot,
|
||||
generateSlots,
|
||||
// Stats
|
||||
fetchDashboardStats,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user