feat: add SPA, serve at /app/, update Dockerfile and README
- React + TanStack Router + shadcn/ui SPA under spa/ - serve spa/dist at /app/ with index.html fallback for client routing - Dockerfile: node build stage for SPA, copy dist into runtime image - README: document SPA, CORS_ORIGINS env var, architecture entry - vite base set to /app/, manifest.json paths fixed
This commit is contained in:
87
spa/src/lib/api/search.ts
Normal file
87
spa/src/lib/api/search.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { z } from "zod"
|
||||
import { paginatedSchema } from "./common"
|
||||
import { get } from "./client"
|
||||
|
||||
export const searchQueryParamsSchema = z.object({
|
||||
q: z.string().optional(),
|
||||
genre: z.string().optional(),
|
||||
year: z.number().optional(),
|
||||
person_id: z.string().uuid().optional(),
|
||||
department: z.string().optional(),
|
||||
language: z.string().optional(),
|
||||
limit: z.number().optional(),
|
||||
offset: z.number().optional(),
|
||||
})
|
||||
export type SearchQueryParams = z.infer<typeof searchQueryParamsSchema>
|
||||
|
||||
export const movieSearchHitDtoSchema = z.object({
|
||||
movie_id: z.string().uuid(),
|
||||
title: z.string(),
|
||||
release_year: z.number().optional(),
|
||||
director: z.string().optional(),
|
||||
poster_path: z.string().optional(),
|
||||
genres: z.array(z.string()),
|
||||
})
|
||||
export type MovieSearchHitDto = z.infer<typeof movieSearchHitDtoSchema>
|
||||
|
||||
export const personSearchHitDtoSchema = z.object({
|
||||
person_id: z.string().uuid(),
|
||||
name: z.string(),
|
||||
known_for_department: z.string().optional(),
|
||||
profile_path: z.string().optional(),
|
||||
known_for_titles: z.array(z.string()),
|
||||
})
|
||||
export type PersonSearchHitDto = z.infer<typeof personSearchHitDtoSchema>
|
||||
|
||||
export const searchResponseSchema = z.object({
|
||||
movies: paginatedSchema(movieSearchHitDtoSchema),
|
||||
people: paginatedSchema(personSearchHitDtoSchema),
|
||||
})
|
||||
export type SearchResponse = z.infer<typeof searchResponseSchema>
|
||||
|
||||
export const personDtoSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
external_id: z.string(),
|
||||
name: z.string(),
|
||||
known_for_department: z.string().optional(),
|
||||
profile_path: z.string().optional(),
|
||||
})
|
||||
export type PersonDto = z.infer<typeof personDtoSchema>
|
||||
|
||||
export const castCreditDtoSchema = z.object({
|
||||
movie_id: z.string().uuid(),
|
||||
title: z.string(),
|
||||
release_year: z.number().optional(),
|
||||
character: z.string(),
|
||||
poster_path: z.string().optional(),
|
||||
})
|
||||
export type CastCreditDto = z.infer<typeof castCreditDtoSchema>
|
||||
|
||||
export const crewCreditDtoSchema = z.object({
|
||||
movie_id: z.string().uuid(),
|
||||
title: z.string(),
|
||||
release_year: z.number().optional(),
|
||||
job: z.string(),
|
||||
department: z.string(),
|
||||
poster_path: z.string().optional(),
|
||||
})
|
||||
export type CrewCreditDto = z.infer<typeof crewCreditDtoSchema>
|
||||
|
||||
export const personCreditsDtoSchema = z.object({
|
||||
person: personDtoSchema,
|
||||
cast: z.array(castCreditDtoSchema),
|
||||
crew: z.array(crewCreditDtoSchema),
|
||||
})
|
||||
export type PersonCreditsDto = z.infer<typeof personCreditsDtoSchema>
|
||||
|
||||
export function search(params: SearchQueryParams) {
|
||||
return get<SearchResponse>("/search", params)
|
||||
}
|
||||
|
||||
export function getPerson(id: string) {
|
||||
return get<PersonDto>(`/people/${id}`)
|
||||
}
|
||||
|
||||
export function getPersonCredits(id: string) {
|
||||
return get<PersonCreditsDto>(`/people/${id}/credits`)
|
||||
}
|
||||
Reference in New Issue
Block a user