diff --git a/Cargo.toml b/Cargo.toml index 664d660..d62711e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,3 +24,10 @@ tower-http = { version = "0.6.6", features = ["cors", "fs", "trace"] } tracing = "0.1.41" tracing-log = "0.2.0" tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt"] } + +[profile.release] +opt-level = 3 +lto = true +codegen-units = 1 +panic = "abort" +strip = true diff --git a/Dockerfile b/Dockerfile index 7f3e93c..63628b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,7 @@ WORKDIR /app RUN apt-get update && apt-get install -y ca-certificates openssl sqlite3 && rm -rf /var/lib/apt/lists/* RUN mkdir -p /app/data COPY --from=backend-builder /app/target/release/rick-and-morty . +COPY --from=backend-builder /app/target/release/fetch_characters . COPY --from=backend-builder /app/migrations ./migrations COPY --from=frontend-builder /app/dist ./frontend/dist EXPOSE 8000 diff --git a/compose.yml b/compose.yml index 5eb14b1..2c94a1b 100644 --- a/compose.yml +++ b/compose.yml @@ -3,7 +3,7 @@ services: build: . container_name: rick_and_morty_app environment: - DATABASE_URL: "sqlite:///app/data/rick_and_morty.db" + DATABASE_URL: "sqlite:///app/data/rick_and_morty.db?mode=rwc" BIND_ADDR: 0.0.0.0:8000 ports: - "8000:8000" diff --git a/frontend/bun.lockb b/frontend/bun.lockb index 976b69b..e6a2782 100755 Binary files a/frontend/bun.lockb and b/frontend/bun.lockb differ diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 13f8ded..a18bf26 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,21 +4,22 @@ import { getCharacters, rateCharacters } from "./api"; import type { Character } from "./types"; import { Card } from "./components/card"; import { Table } from "./components/table"; -import { getId } from "./utils"; function getRandomIndex(length: number) { return Math.floor(Math.random() * length); } -function getRandomPair(characters: Character[], lastPair: [number, number]) { - if (characters.length < 2) return [null, null]; - +// Optionally: Use a lastPairRef to avoid same characters twice in a row +function getRandomPair( + characters: Character[], + lastPair: [number, number] | null +): [Character, Character] { + if (characters.length < 2) return [null, null] as never; let firstIndex = getRandomIndex(characters.length); let secondIndex = getRandomIndex(characters.length); while ( - firstIndex === lastPair[0] || - secondIndex === lastPair[1] || + (lastPair && firstIndex === lastPair[0] && secondIndex === lastPair[1]) || firstIndex === secondIndex ) { firstIndex = getRandomIndex(characters.length); @@ -57,8 +58,8 @@ const App: React.FC = () => { if (voting || !rivals[winnerIdx] || !rivals[loserIdx]) return; setVoting(true); setVotedLeft(winnerIdx === 0); - const winnerId = getId(rivals[winnerIdx]); - const loserId = getId(rivals[loserIdx]); + const winnerId = rivals[winnerIdx]!.id; + const loserId = rivals[loserIdx]!.id; if (!winnerId || !loserId) return; await rateCharacters(winnerId, loserId); const chars = await getCharacters(); diff --git a/frontend/src/api.ts b/frontend/src/api.ts index 4f92e31..086c423 100644 --- a/frontend/src/api.ts +++ b/frontend/src/api.ts @@ -2,13 +2,19 @@ import type { Character } from './types'; export const getCharacters = async (): Promise => { const res = await fetch('/characters'); + if (!res.ok) { + throw new Error('Failed to fetch characters'); + } return res.json(); }; -export const rateCharacters = async (winnerId: string, loserId: string) => { - await fetch('/rate', { +export const rateCharacters = async (winnerId: number, loserId: number) => { + const res = await fetch('/rate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ winner_id: winnerId, loser_id: loserId }), + body: JSON.stringify({ winner_id: winnerId.toString(), loser_id: loserId.toString() }), }); + if (!res.ok) { + throw new Error('Failed to rate characters'); + } }; diff --git a/frontend/src/components/card.tsx b/frontend/src/components/card.tsx index f503f4b..2afbfdf 100644 --- a/frontend/src/components/card.tsx +++ b/frontend/src/components/card.tsx @@ -1,62 +1,64 @@ -import React from 'react'; -import type { Character } from '../types'; +import React from "react"; +import type { Character } from "../types"; interface CardProps { - data: Character; - isClicked?: boolean; - skipped?: boolean; - onClick?: () => void; - isRight?: boolean; + data: Character; + isClicked?: boolean; + skipped?: boolean; + onClick?: () => void; + isRight?: boolean; } export const Card: React.FC = ({ - data, - isClicked, - skipped, - onClick, + data, + isClicked, + skipped, + onClick, }) => ( -
-
- {/* FRONT */} -
-

{data.name}

- {data.name} -

Info

-
- - - - - - - - - - - - - - - - - - - - - - - -
Species{data.species}
Gender{data.gender}
Status{data.status}
Origin{data.origin.name}
Last location{data.location.name}
-
-
- {/* BACK */} -
- {/* You can put whatever you want here, like a background or extra info */} -
+
+
+ {/* FRONT */} +
+

{data.name}

+ {data.name} +

Info

+
+ + + + + + + + + + + + + + + + + + + + + + + +
Species{data.species}
Gender{data.gender}
Status{data.status}
Origin{data.origin_name}
Last location{data.location_name}
+
+ {/* BACK */} +
+ {/* You can put whatever you want here, like a background or extra info */} +
+
); diff --git a/frontend/src/types.ts b/frontend/src/types.ts index cc39132..f15a788 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -4,17 +4,19 @@ export interface OriginOrLocation { } export interface Character { - _id: string | { $oid: string }; + id: number; rmid: number; name: string; status: string; species: string; type: string; gender: string; - origin: OriginOrLocation; - location: OriginOrLocation; + origin_name: string; + origin_url: string; + location_name: string; + location_url: string; image: string; - episode: string[]; + episode: string; // This will be a stringified JSON array! url: string; created: string; elo_rating: number; diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts index 292b1d9..75b1296 100644 --- a/frontend/src/utils.ts +++ b/frontend/src/utils.ts @@ -1,9 +1,10 @@ import type { Character } from "./types"; -export function getId(character: Character | null) { - if (!character) return undefined; - const id = character._id as string | { $oid: string } | undefined; - if (typeof id === 'string') return id; - if (id && typeof id.$oid === 'string') return id.$oid; - return undefined; +export function getEpisodes(character: Character): string[] { + if (Array.isArray(character.episode)) return character.episode; + try { + return JSON.parse(character.episode); + } catch { + return []; + } } \ No newline at end of file