feat: scaffold monorepo with shared types and NestJS server
- pnpm workspace with packages/app, packages/server, packages/shared - @mp-pilates/shared: enums, constants, TypeScript interfaces for all 8 data models - @mp-pilates/server: NestJS bootstrap with health check, validation pipe, CORS - Base TypeScript config with strict mode
This commit is contained in:
41
.gitignore
vendored
Normal file
41
.gitignore
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Build output
|
||||
dist/
|
||||
dist-ssr/
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Test coverage
|
||||
coverage/
|
||||
|
||||
# Prisma
|
||||
packages/server/prisma/*.db
|
||||
packages/server/prisma/migrations/**/migration_lock.toml
|
||||
|
||||
# uni-app build
|
||||
packages/app/dist/
|
||||
packages/app/unpackage/
|
||||
|
||||
# Misc
|
||||
*.tgz
|
||||
.cache/
|
||||
1120
docs/superpowers/plans/2026-04-02-pilates-booking-miniprogram.md
Normal file
1120
docs/superpowers/plans/2026-04-02-pilates-booking-miniprogram.md
Normal file
File diff suppressed because it is too large
Load Diff
25
package.json
Normal file
25
package.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "mp-pilates",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev:server": "pnpm --filter @mp-pilates/server dev",
|
||||
"dev:app": "pnpm --filter @mp-pilates/app dev:mp-weixin",
|
||||
"build:shared": "pnpm --filter @mp-pilates/shared build",
|
||||
"build:server": "pnpm --filter @mp-pilates/server build",
|
||||
"build:app": "pnpm --filter @mp-pilates/app build:mp-weixin",
|
||||
"test": "pnpm -r test",
|
||||
"lint": "pnpm -r lint"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18",
|
||||
"pnpm": ">=8"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
"@nestjs/core",
|
||||
"@prisma/client",
|
||||
"@prisma/engines",
|
||||
"prisma"
|
||||
]
|
||||
}
|
||||
}
|
||||
19
packages/server/.env.example
Normal file
19
packages/server/.env.example
Normal file
@@ -0,0 +1,19 @@
|
||||
# Database
|
||||
DATABASE_URL=postgresql://user:pass@localhost:5432/mp_pilates
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=change-me-to-a-secure-random-string
|
||||
|
||||
# WeChat Mini Program
|
||||
WX_APPID=your-appid
|
||||
WX_SECRET=your-secret
|
||||
|
||||
# WeChat Pay
|
||||
WX_MCH_ID=your-mch-id
|
||||
WX_MCH_KEY=your-mch-key
|
||||
WX_MCH_SERIAL_NO=your-serial-no
|
||||
WX_MCH_CERT_PATH=./certs/apiclient_cert.pem
|
||||
WX_MCH_KEY_PATH=./certs/apiclient_key.pem
|
||||
|
||||
# Server
|
||||
PORT=3000
|
||||
8
packages/server/nest-cli.json
Normal file
8
packages/server/nest-cli.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/nest-cli",
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"deleteOutDir": true
|
||||
}
|
||||
}
|
||||
64
packages/server/package.json
Normal file
64
packages/server/package.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "@mp-pilates/server",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "nest build",
|
||||
"dev": "nest start --watch",
|
||||
"start": "nest start",
|
||||
"start:prod": "node dist/main",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:cov": "jest --coverage",
|
||||
"prisma:generate": "prisma generate",
|
||||
"prisma:migrate": "prisma migrate dev",
|
||||
"prisma:seed": "ts-node prisma/seed.ts",
|
||||
"lint": "eslint \"{src,test}/**/*.ts\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@mp-pilates/shared": "workspace:*",
|
||||
"@nestjs/common": "^10.4.0",
|
||||
"@nestjs/config": "^3.2.0",
|
||||
"@nestjs/core": "^10.4.0",
|
||||
"@nestjs/jwt": "^10.2.0",
|
||||
"@nestjs/passport": "^10.0.3",
|
||||
"@nestjs/platform-express": "^10.4.0",
|
||||
"@nestjs/schedule": "^4.1.0",
|
||||
"@prisma/client": "^5.19.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.1",
|
||||
"passport": "^0.7.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.4.0",
|
||||
"@nestjs/schematics": "^10.1.0",
|
||||
"@nestjs/testing": "^10.4.0",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/passport-jwt": "^4.0.1",
|
||||
"jest": "^29.7.0",
|
||||
"prisma": "^5.19.0",
|
||||
"source-map-support": "^0.5.21",
|
||||
"supertest": "^7.0.0",
|
||||
"ts-jest": "^29.2.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.0"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": ["js", "json", "ts"],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": ["**/*.(t|j)s", "!**/*.module.ts", "!main.ts"],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node",
|
||||
"moduleNameMapper": {
|
||||
"^@mp-pilates/shared(.*)$": "<rootDir>/../../shared/src$1"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
packages/server/src/app.controller.ts
Normal file
9
packages/server/src/app.controller.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Controller, Get } from '@nestjs/common'
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
@Get('health')
|
||||
health() {
|
||||
return { status: 'ok', timestamp: new Date().toISOString() }
|
||||
}
|
||||
}
|
||||
14
packages/server/src/app.module.ts
Normal file
14
packages/server/src/app.module.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { ConfigModule } from '@nestjs/config'
|
||||
import { AppController } from './app.controller'
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: ['.env.local', '.env'],
|
||||
}),
|
||||
],
|
||||
controllers: [AppController],
|
||||
})
|
||||
export class AppModule {}
|
||||
24
packages/server/src/main.ts
Normal file
24
packages/server/src/main.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { NestFactory } from '@nestjs/core'
|
||||
import { ValidationPipe } from '@nestjs/common'
|
||||
import { ConfigService } from '@nestjs/config'
|
||||
import { AppModule } from './app.module'
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule)
|
||||
const configService = app.get(ConfigService)
|
||||
|
||||
app.setGlobalPrefix('api')
|
||||
app.useGlobalPipes(
|
||||
new ValidationPipe({
|
||||
whitelist: true,
|
||||
forbidNonWhitelisted: true,
|
||||
transform: true,
|
||||
}),
|
||||
)
|
||||
app.enableCors()
|
||||
|
||||
const port = configService.get<number>('PORT', 3000)
|
||||
await app.listen(port)
|
||||
console.log(`Server running on http://localhost:${port}`)
|
||||
}
|
||||
bootstrap()
|
||||
7
packages/server/tsconfig.build.json
Normal file
7
packages/server/tsconfig.build.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "test", "**/*.spec.ts"]
|
||||
}
|
||||
18
packages/server/tsconfig.json
Normal file
18
packages/server/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"target": "ES2021",
|
||||
"sourceMap": true,
|
||||
"incremental": true,
|
||||
"declaration": false,
|
||||
"declarationMap": false
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist", "test"]
|
||||
}
|
||||
13
packages/shared/package.json
Normal file
13
packages/shared/package.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "@mp-pilates/shared",
|
||||
"version": "0.1.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.4.0"
|
||||
}
|
||||
}
|
||||
21
packages/shared/src/constants.ts
Normal file
21
packages/shared/src/constants.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
/** 默认免费取消截止小时数 */
|
||||
export const DEFAULT_CANCEL_HOURS_LIMIT = 2
|
||||
|
||||
/** 默认时段容量(私教 = 1) */
|
||||
export const DEFAULT_SLOT_CAPACITY = 1
|
||||
|
||||
/** 自动生成时段的天数范围 */
|
||||
export const SLOT_GENERATION_DAYS = 14
|
||||
|
||||
/** 时段筛选区间 */
|
||||
export const TIME_PERIODS = {
|
||||
MORNING: { label: '上午', start: '06:00', end: '12:00' },
|
||||
AFTERNOON: { label: '下午', start: '12:00', end: '18:00' },
|
||||
EVENING: { label: '晚上', start: '18:00', end: '22:00' },
|
||||
} as const
|
||||
|
||||
/** 日期选择器展示天数 */
|
||||
export const DATE_SELECTOR_DAYS = 7
|
||||
|
||||
/** 星期映射 */
|
||||
export const WEEKDAY_LABELS = ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日'] as const
|
||||
46
packages/shared/src/enums.ts
Normal file
46
packages/shared/src/enums.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
// ===== User =====
|
||||
export enum UserRole {
|
||||
MEMBER = 'MEMBER',
|
||||
ADMIN = 'ADMIN',
|
||||
}
|
||||
|
||||
// ===== CardType =====
|
||||
export enum CardTypeCategory {
|
||||
TIMES = 'TIMES',
|
||||
DURATION = 'DURATION',
|
||||
TRIAL = 'TRIAL',
|
||||
}
|
||||
|
||||
// ===== Membership =====
|
||||
export enum MembershipStatus {
|
||||
ACTIVE = 'ACTIVE',
|
||||
EXPIRED = 'EXPIRED',
|
||||
USED_UP = 'USED_UP',
|
||||
}
|
||||
|
||||
// ===== TimeSlot =====
|
||||
export enum TimeSlotStatus {
|
||||
OPEN = 'OPEN',
|
||||
FULL = 'FULL',
|
||||
CLOSED = 'CLOSED',
|
||||
}
|
||||
|
||||
export enum TimeSlotSource {
|
||||
TEMPLATE = 'TEMPLATE',
|
||||
MANUAL = 'MANUAL',
|
||||
}
|
||||
|
||||
// ===== Booking =====
|
||||
export enum BookingStatus {
|
||||
CONFIRMED = 'CONFIRMED',
|
||||
CANCELLED = 'CANCELLED',
|
||||
COMPLETED = 'COMPLETED',
|
||||
NO_SHOW = 'NO_SHOW',
|
||||
}
|
||||
|
||||
// ===== Order =====
|
||||
export enum OrderStatus {
|
||||
PENDING = 'PENDING',
|
||||
PAID = 'PAID',
|
||||
REFUNDED = 'REFUNDED',
|
||||
}
|
||||
52
packages/shared/src/index.ts
Normal file
52
packages/shared/src/index.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
// Enums
|
||||
export {
|
||||
UserRole,
|
||||
CardTypeCategory,
|
||||
MembershipStatus,
|
||||
TimeSlotStatus,
|
||||
TimeSlotSource,
|
||||
BookingStatus,
|
||||
OrderStatus,
|
||||
} from './enums'
|
||||
|
||||
// Constants
|
||||
export {
|
||||
DEFAULT_CANCEL_HOURS_LIMIT,
|
||||
DEFAULT_SLOT_CAPACITY,
|
||||
SLOT_GENERATION_DAYS,
|
||||
TIME_PERIODS,
|
||||
DATE_SELECTOR_DAYS,
|
||||
WEEKDAY_LABELS,
|
||||
} from './constants'
|
||||
|
||||
// Types
|
||||
export type {
|
||||
User,
|
||||
UserProfileResponse,
|
||||
UpdateProfileDto,
|
||||
UserStatsResponse,
|
||||
CardType,
|
||||
CreateCardTypeDto,
|
||||
UpdateCardTypeDto,
|
||||
Membership,
|
||||
MembershipWithCardType,
|
||||
WeekTemplate,
|
||||
WeekTemplateInput,
|
||||
TimeSlot,
|
||||
TimeSlotWithBookingStatus,
|
||||
CreateManualSlotDto,
|
||||
Booking,
|
||||
BookingWithDetails,
|
||||
CreateBookingDto,
|
||||
Order,
|
||||
OrderWithDetails,
|
||||
CreateOrderDto,
|
||||
PaymentParams,
|
||||
CreateOrderResponse,
|
||||
StudioConfig,
|
||||
UpdateStudioConfigDto,
|
||||
ApiResponse,
|
||||
PaginatedData,
|
||||
PaginatedResponse,
|
||||
PaginationQuery,
|
||||
} from './types/index'
|
||||
19
packages/shared/src/types/api.ts
Normal file
19
packages/shared/src/types/api.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export interface ApiResponse<T> {
|
||||
readonly success: boolean
|
||||
readonly data: T | null
|
||||
readonly message: string | null
|
||||
}
|
||||
|
||||
export interface PaginatedData<T> {
|
||||
readonly items: readonly T[]
|
||||
readonly total: number
|
||||
readonly page: number
|
||||
readonly limit: number
|
||||
}
|
||||
|
||||
export type PaginatedResponse<T> = ApiResponse<PaginatedData<T>>
|
||||
|
||||
export interface PaginationQuery {
|
||||
readonly page?: number
|
||||
readonly limit?: number
|
||||
}
|
||||
31
packages/shared/src/types/booking.ts
Normal file
31
packages/shared/src/types/booking.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { BookingStatus } from '../enums'
|
||||
|
||||
export interface Booking {
|
||||
readonly id: string
|
||||
readonly userId: string
|
||||
readonly timeSlotId: string
|
||||
readonly membershipId: string
|
||||
readonly status: BookingStatus
|
||||
readonly cancelledAt: string | null
|
||||
readonly createdAt: string
|
||||
readonly updatedAt: string
|
||||
}
|
||||
|
||||
export interface BookingWithDetails extends Booking {
|
||||
readonly timeSlot: {
|
||||
readonly date: string
|
||||
readonly startTime: string
|
||||
readonly endTime: string
|
||||
}
|
||||
readonly membership: {
|
||||
readonly id: string
|
||||
readonly cardType: {
|
||||
readonly name: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface CreateBookingDto {
|
||||
readonly timeSlotId: string
|
||||
readonly membershipId: string
|
||||
}
|
||||
38
packages/shared/src/types/card-type.ts
Normal file
38
packages/shared/src/types/card-type.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { CardTypeCategory } from '../enums'
|
||||
|
||||
export interface CardType {
|
||||
readonly id: string
|
||||
readonly name: string
|
||||
readonly type: CardTypeCategory
|
||||
readonly totalTimes: number | null
|
||||
readonly durationDays: number
|
||||
readonly price: number
|
||||
readonly originalPrice: number | null
|
||||
readonly description: string | null
|
||||
readonly isActive: boolean
|
||||
readonly sortOrder: number
|
||||
readonly createdAt: string
|
||||
readonly updatedAt: string
|
||||
}
|
||||
|
||||
export interface CreateCardTypeDto {
|
||||
readonly name: string
|
||||
readonly type: CardTypeCategory
|
||||
readonly totalTimes?: number
|
||||
readonly durationDays: number
|
||||
readonly price: number
|
||||
readonly originalPrice?: number
|
||||
readonly description?: string
|
||||
readonly sortOrder?: number
|
||||
}
|
||||
|
||||
export interface UpdateCardTypeDto {
|
||||
readonly name?: string
|
||||
readonly totalTimes?: number
|
||||
readonly durationDays?: number
|
||||
readonly price?: number
|
||||
readonly originalPrice?: number
|
||||
readonly description?: string
|
||||
readonly isActive?: boolean
|
||||
readonly sortOrder?: number
|
||||
}
|
||||
9
packages/shared/src/types/index.ts
Normal file
9
packages/shared/src/types/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export type { User, UserProfileResponse, UpdateProfileDto, UserStatsResponse } from './user'
|
||||
export type { CardType, CreateCardTypeDto, UpdateCardTypeDto } from './card-type'
|
||||
export type { Membership, MembershipWithCardType } from './membership'
|
||||
export type { WeekTemplate, WeekTemplateInput } from './week-template'
|
||||
export type { TimeSlot, TimeSlotWithBookingStatus, CreateManualSlotDto } from './time-slot'
|
||||
export type { Booking, BookingWithDetails, CreateBookingDto } from './booking'
|
||||
export type { Order, OrderWithDetails, CreateOrderDto, PaymentParams, CreateOrderResponse } from './order'
|
||||
export type { StudioConfig, UpdateStudioConfigDto } from './studio'
|
||||
export type { ApiResponse, PaginatedData, PaginatedResponse, PaginationQuery } from './api'
|
||||
18
packages/shared/src/types/membership.ts
Normal file
18
packages/shared/src/types/membership.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { MembershipStatus } from '../enums'
|
||||
import { CardType } from './card-type'
|
||||
|
||||
export interface Membership {
|
||||
readonly id: string
|
||||
readonly userId: string
|
||||
readonly cardTypeId: string
|
||||
readonly remainingTimes: number | null
|
||||
readonly startDate: string
|
||||
readonly expireDate: string
|
||||
readonly status: MembershipStatus
|
||||
readonly createdAt: string
|
||||
readonly updatedAt: string
|
||||
}
|
||||
|
||||
export interface MembershipWithCardType extends Membership {
|
||||
readonly cardType: CardType
|
||||
}
|
||||
42
packages/shared/src/types/order.ts
Normal file
42
packages/shared/src/types/order.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { OrderStatus } from '../enums'
|
||||
|
||||
export interface Order {
|
||||
readonly id: string
|
||||
readonly userId: string
|
||||
readonly cardTypeId: string
|
||||
readonly orderNo: string
|
||||
readonly amount: number
|
||||
readonly status: OrderStatus
|
||||
readonly wxTransactionId: string | null
|
||||
readonly paidAt: string | null
|
||||
readonly createdAt: string
|
||||
readonly updatedAt: string
|
||||
}
|
||||
|
||||
export interface OrderWithDetails extends Order {
|
||||
readonly cardType: {
|
||||
readonly name: string
|
||||
readonly type: string
|
||||
}
|
||||
readonly user?: {
|
||||
readonly nickname: string
|
||||
readonly phone: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export interface CreateOrderDto {
|
||||
readonly cardTypeId: string
|
||||
}
|
||||
|
||||
export interface PaymentParams {
|
||||
readonly timeStamp: string
|
||||
readonly nonceStr: string
|
||||
readonly package: string
|
||||
readonly signType: string
|
||||
readonly paySign: string
|
||||
}
|
||||
|
||||
export interface CreateOrderResponse {
|
||||
readonly order: Order
|
||||
readonly paymentParams: PaymentParams
|
||||
}
|
||||
25
packages/shared/src/types/studio.ts
Normal file
25
packages/shared/src/types/studio.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export interface StudioConfig {
|
||||
readonly id: string
|
||||
readonly name: string
|
||||
readonly logo: string | null
|
||||
readonly bannerUrl: string | null
|
||||
readonly address: string
|
||||
readonly phone: string
|
||||
readonly latitude: number | null
|
||||
readonly longitude: number | null
|
||||
readonly cancelHoursLimit: number
|
||||
readonly photos: string[]
|
||||
readonly updatedAt: string
|
||||
}
|
||||
|
||||
export interface UpdateStudioConfigDto {
|
||||
readonly name?: string
|
||||
readonly logo?: string
|
||||
readonly bannerUrl?: string
|
||||
readonly address?: string
|
||||
readonly phone?: string
|
||||
readonly latitude?: number
|
||||
readonly longitude?: number
|
||||
readonly cancelHoursLimit?: number
|
||||
readonly photos?: string[]
|
||||
}
|
||||
29
packages/shared/src/types/time-slot.ts
Normal file
29
packages/shared/src/types/time-slot.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { TimeSlotStatus, TimeSlotSource } from '../enums'
|
||||
|
||||
export interface TimeSlot {
|
||||
readonly id: string
|
||||
readonly date: string
|
||||
readonly startTime: string
|
||||
readonly endTime: string
|
||||
readonly capacity: number
|
||||
readonly bookedCount: number
|
||||
readonly status: TimeSlotStatus
|
||||
readonly source: TimeSlotSource
|
||||
readonly templateId: string | null
|
||||
readonly createdAt: string
|
||||
readonly updatedAt: string
|
||||
}
|
||||
|
||||
export interface TimeSlotWithBookingStatus extends TimeSlot {
|
||||
/** 当前用户是否已预约此时段 */
|
||||
readonly isBookedByMe: boolean
|
||||
/** 当前用户在此时段的预约 ID(用于取消) */
|
||||
readonly myBookingId: string | null
|
||||
}
|
||||
|
||||
export interface CreateManualSlotDto {
|
||||
readonly date: string
|
||||
readonly startTime: string
|
||||
readonly endTime: string
|
||||
readonly capacity?: number
|
||||
}
|
||||
36
packages/shared/src/types/user.ts
Normal file
36
packages/shared/src/types/user.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { UserRole } from '../enums'
|
||||
|
||||
export interface User {
|
||||
readonly id: string
|
||||
readonly openid: string
|
||||
readonly unionid: string | null
|
||||
readonly phone: string | null
|
||||
readonly nickname: string
|
||||
readonly avatarUrl: string | null
|
||||
readonly role: UserRole
|
||||
readonly createdAt: string
|
||||
readonly updatedAt: string
|
||||
}
|
||||
|
||||
export interface UserProfileResponse {
|
||||
readonly id: string
|
||||
readonly phone: string | null
|
||||
readonly nickname: string
|
||||
readonly avatarUrl: string | null
|
||||
readonly role: UserRole
|
||||
readonly activeMembershipCount: number
|
||||
readonly createdAt: string
|
||||
}
|
||||
|
||||
export interface UpdateProfileDto {
|
||||
readonly nickname?: string
|
||||
readonly avatarUrl?: string
|
||||
}
|
||||
|
||||
export interface UserStatsResponse {
|
||||
readonly totalBookings: number
|
||||
readonly totalDays: number
|
||||
readonly monthBookings: number
|
||||
readonly monthDays: number
|
||||
readonly monthHours: number
|
||||
}
|
||||
18
packages/shared/src/types/week-template.ts
Normal file
18
packages/shared/src/types/week-template.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export interface WeekTemplate {
|
||||
readonly id: string
|
||||
readonly dayOfWeek: number
|
||||
readonly startTime: string
|
||||
readonly endTime: string
|
||||
readonly capacity: number
|
||||
readonly isActive: boolean
|
||||
readonly createdAt: string
|
||||
readonly updatedAt: string
|
||||
}
|
||||
|
||||
export interface WeekTemplateInput {
|
||||
readonly dayOfWeek: number
|
||||
readonly startTime: string
|
||||
readonly endTime: string
|
||||
readonly capacity?: number
|
||||
readonly isActive?: boolean
|
||||
}
|
||||
10
packages/shared/tsconfig.json
Normal file
10
packages/shared/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"declaration": true,
|
||||
"declarationMap": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
5657
pnpm-lock.yaml
generated
Normal file
5657
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
pnpm-workspace.yaml
Normal file
2
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- 'packages/*'
|
||||
20
tsconfig.base.json
Normal file
20
tsconfig.base.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2021",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"paths": {
|
||||
"@mp-pilates/shared": ["./packages/shared/src/index.ts"],
|
||||
"@mp-pilates/shared/*": ["./packages/shared/src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user