Files
mcma-webui/src/api/types.ts
T
Senko-san 61dbb1abd2 feat(upload): wire A8 local track upload to backend
Implement the A8 upload screen against the existing /upload contract:
- UploadResponse type ({track_id, title, already_exists}) + mutation typed to it
- buildUploadFormData helper (single file under field `file`, per FastAPI)
- UploadPage: drag-and-drop + file picker, client-side queue with
  concurrency cap (3), per-file status badges, retry on error,
  already_exists -> "Already in library", deep-link to A7 metadata editor
- i18n upload.* section (en/ru) incl. "metadata pending" hint

Indeterminate spinner per file; percent progress is a follow-up
(needs an XHR baseQuery — fetchBaseQuery gives no upload progress).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 18:47:59 +03:00

139 lines
2.5 KiB
TypeScript

export type TrackAvailability = 'server' | 'downloading' | 'error' | 'missing';
export interface Track {
id: string;
title: string;
artistId: string;
artistName: string;
albumId: string;
albumTitle: string;
albumArtUrl?: string;
durationMs: number;
trackNumber?: number;
discNumber?: number;
year?: number;
genre?: string;
availability: TrackAvailability;
fileSize?: number;
format?: string;
bitrate?: number;
liked: boolean;
}
export interface Album {
id: string;
title: string;
artistId: string;
artistName: string;
artUrl?: string;
year?: number;
trackCount: number;
totalDurationMs: number;
genre?: string;
}
export interface Artist {
id: string;
name: string;
artUrl?: string;
albumCount: number;
trackCount: number;
}
export interface Playlist {
id: string;
name: string;
description?: string;
ownerId: string;
trackCount: number;
totalDurationMs: number;
artUrl?: string;
isPublic: boolean;
createdAt: string;
updatedAt: string;
}
export interface PlaylistTrack extends Track {
position: number;
addedAt: string;
}
export interface DownloadJob {
id: string;
url: string;
title?: string;
artist?: string;
album?: string;
status: 'queued' | 'downloading' | 'processing' | 'done' | 'error';
progress: number;
errorMessage?: string;
trackId?: string;
createdAt: string;
updatedAt: string;
}
export interface UploadResponse {
track_id: string;
title: string;
already_exists: boolean;
}
export interface StorageStats {
totalBytes: number;
usedBytes: number;
trackCount: number;
albumCount: number;
artistCount: number;
}
export interface User {
id: string;
username: string;
email?: string;
role: 'admin' | 'user';
createdAt: string;
lastActiveAt?: string;
}
export interface AuthTokens {
accessToken: string;
refreshToken: string;
expiresIn: number;
}
export interface LoginRequest {
username: string;
password: string;
}
export interface LoginResponse {
user: User;
tokens: AuthTokens;
}
export interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
pageSize: number;
hasMore: boolean;
}
export interface LibraryFilters {
search?: string;
genre?: string;
artistId?: string;
albumId?: string;
liked?: boolean;
page?: number;
pageSize?: number;
sortBy?: 'title' | 'artist' | 'album' | 'year' | 'dateAdded';
sortOrder?: 'asc' | 'desc';
}
export interface ApiError {
status: number;
message: string;
code?: string;
}