Files
chore/frontend/vue-app/src/common/models.ts
Ryan Kegel 0d651129cb
All checks were successful
Gitea Actions Demo / build-and-push (push) Successful in 23s
feat: Implement account deletion (mark for removal) feature
- Added `marked_for_deletion` and `marked_for_deletion_at` fields to User model (Python and TypeScript) with serialization updates
- Created POST /api/user/mark-for-deletion endpoint with JWT auth, error handling, and SSE event trigger
- Blocked login and password reset for marked users; added new error codes ACCOUNT_MARKED_FOR_DELETION and ALREADY_MARKED
- Updated UserProfile.vue with "Delete My Account" button, confirmation modal (email input), loading state, success/error modals, and sign-out/redirect logic
- Synced error codes and model fields between backend and frontend
- Added and updated backend and frontend tests to cover all flows and edge cases
- All Acceptance Criteria from the spec are complete and verified
2026-02-06 16:19:08 -05:00

135 lines
3.0 KiB
TypeScript

export interface Task {
id: string
name: string
points: number
is_good: boolean
image_id: string | null
image_url?: string | null // optional, for resolved URLs
}
export const TASK_FIELDS = ['id', 'name', 'points', 'is_good', 'image_id'] as const
export interface User {
id: string
first_name: string
last_name: string
email: string
image_id: string | null
marked_for_deletion: boolean
marked_for_deletion_at: string | null
}
export interface Child {
id: string
name: string
age: number
tasks: string[]
rewards: string[]
points: number
image_id: string | null
image_url?: string | null // optional, for resolved URLs
}
export const CHILD_FIELDS = ['id', 'name', 'age', 'tasks', 'rewards', 'points', 'image_id'] as const
export interface Reward {
id: string
name: string
cost: number
points_needed: number
image_id: string | null
image_url?: string | null // optional, for resolved URLs
}
export const REWARD_FIELDS = ['id', 'name', 'cost', 'points_needed', 'image_id'] as const
export interface RewardStatus {
id: string
name: string
points_needed: number
cost: number
redeeming: boolean
image_id: string | null
image_url?: string | null // optional, for resolved URLs
}
export const REWARD_STATUS_FIELDS = [
'id',
'name',
'points_needed',
'cost',
'redeeming',
'image_id',
] as const
export interface PendingReward {
id: string
child_id: string
child_name: string
child_image_id: string | null
child_image_url?: string | null // optional, for resolved URLs
reward_id: string
reward_name: string
reward_image_id: string | null
reward_image_url?: string | null // optional, for resolved URLs
}
export const PENDING_REWARD_FIELDS = [
'id',
'child_id',
'child_name',
'child_image_id',
'reward_id',
'reward_name',
'reward_image_id',
] as const
export interface Event {
type: string
payload:
| ChildModifiedEventPayload
| ChildTaskTriggeredEventPayload
| ChildRewardTriggeredEventPayload
| ChildRewardRequestEventPayload
| ChildTasksSetEventPayload
| ChildRewardsSetEventPayload
| TaskModifiedEventPayload
| RewardModifiedEventPayload
}
export interface ChildModifiedEventPayload {
child_id: string
operation: 'ADD' | 'DELETE' | 'EDIT'
}
export interface ChildTaskTriggeredEventPayload {
task_id: string
child_id: string
points: number
}
export interface ChildRewardTriggeredEventPayload {
task_id: string
child_id: string
points: number
}
export interface ChildRewardRequestEventPayload {
child_id: string
reward_id: string
operation: 'GRANTED' | 'CREATED' | 'CANCELLED'
}
export interface ChildTasksSetEventPayload {
child_id: string
task_ids: string[]
}
export interface ChildRewardsSetEventPayload {
child_id: string
reward_ids: string[]
}
export interface TaskModifiedEventPayload {
task_id: string
operation: 'ADD' | 'DELETE' | 'EDIT'
}
export interface RewardModifiedEventPayload {
reward_id: string
operation: 'ADD' | 'DELETE' | 'EDIT'
}