From aedd87416fc9ff9e8ec0166c5677c1f942c7b09a Mon Sep 17 00:00:00 2001 From: Cron1cle <118773725+Cron1cle@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:20:40 +0200 Subject: [PATCH] updated --- apis/personApi.ts | 30 +++++++++-- apis/seasonApi.ts | 2 +- apis/showApi.ts | 2 + app/(tabs)/index.tsx | 2 +- app/participant.tsx | 75 +++++++++++++++++---------- app/showDetails.tsx | 19 +++++-- app/stackStyles/participantStyles.tsx | 2 +- components/ui/ShowInfo.tsx | 4 ++ constants/colors.ts | 20 +++++++ contexts/PersonContext.tsx | 35 +++++++++---- 10 files changed, 141 insertions(+), 50 deletions(-) create mode 100644 constants/colors.ts diff --git a/apis/personApi.ts b/apis/personApi.ts index 22c3c2e..3f5f2ff 100644 --- a/apis/personApi.ts +++ b/apis/personApi.ts @@ -11,6 +11,12 @@ export type PersonHistoryEntry = { showId: number; seasonId: number; seasonNumber: number; + partner?: { + id: number; + name: string; + birthDate?: string; + imageUri: string | null; + } | null; }; const PERSON_API_BASE = "http://45.157.177.99:8080/persons"; @@ -28,11 +34,25 @@ export async function getPersonHistory( console.warn("History expected array, got:", data); return []; } - return (data as PersonHistorySeasonRaw[]).map((s) => ({ - showId: s.show, - seasonId: s.seasonId, - seasonNumber: s.seasonNumber, - })); + return (data as PersonHistorySeasonRaw[]).map((season) => { + const me = season.seasonParticipants.find( + (p) => p.person.personId === personId + ); + let partner: PersonHistoryEntry["partner"] = null; + if (me?.partner?.person) { + partner = { + id: me.partner.person.personId, + name: me.partner.person.name, + imageUri: me.partner.person.imageUrl ?? null, + }; + } + return { + showId: season.show, + seasonId: season.seasonId, + seasonNumber: season.seasonNumber, + partner, + }; + }); } catch (e) { console.error("getPersonHistory error:", e); return []; diff --git a/apis/seasonApi.ts b/apis/seasonApi.ts index d58e0d1..262271d 100644 --- a/apis/seasonApi.ts +++ b/apis/seasonApi.ts @@ -58,7 +58,7 @@ export async function getSeason( : undefined, imageUri: p.person.imageUrl ?? - "https://via.placeholder.com/300x400.png?text=No+Image", + `https://i.pravatar.cc/300?img=${Math.random() * 70}`, }) ); return { diff --git a/apis/showApi.ts b/apis/showApi.ts index 1e0e87e..0661433 100644 --- a/apis/showApi.ts +++ b/apis/showApi.ts @@ -52,6 +52,8 @@ export async function getShows(): Promise { concept: s.concept, running: s.running, logoUri: s.logoUrl ?? "", + startDate: s.startDate, + endDate: s.endDate, })); } catch (error) { console.error("Fetch error:", error); diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 2c9f745..f9f03e2 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -99,7 +99,7 @@ export default function HomeScreen() { ({ showId: id, seasons: data.byShow[id], + partners: data.partnersByShow[id] || [], })); - setAppearances(grouped); + setAppearances(grouped as any); })(); return () => { active = false; @@ -44,14 +45,30 @@ export default function ParticipantScreen() { const resolved = useMemo( () => - appearances + (appearances as any[]) .map((a) => { const show = shows.find((s) => s.id === a.showId); if (!show) return null; - return { show, seasons: a.seasons }; + return { + show, + seasons: a.seasons as number[], + partners: a.partners as { + seasonNumber: number; + partner?: { id: number; name: string; imageUrl?: string | null }; + }[], + }; }) .filter( - (v): v is { show: (typeof shows)[number]; seasons: number[] } => !!v + ( + v + ): v is { + show: (typeof shows)[number]; + seasons: number[]; + partners: { + seasonNumber: number; + partner?: { id: number; name: string; imageUrl?: string | null }; + }[]; + } => !!v ), [appearances, shows] ); @@ -75,12 +92,6 @@ export default function ParticipantScreen() { Köln - Auftritte: @@ -107,23 +118,31 @@ export default function ParticipantScreen() { marginTop: 15, }} > - {resolved.map(({ show, seasons }) => ( - - - - {show.title} - - - Staffel - {seasons.length === 1 - ? ` ${seasons[0]}` - : `n ${seasons.join(", ")}`} - - - ))} + {resolved.map(({ show, seasons, partners }) => { + const seasonPartnerLines = partners.map((p) => { + const label = `Staffel ${p.seasonNumber}`; + if (!p.partner) return label; + return `${label} • Partner: ${p.partner.name}`; + }); + return ( + + + + {show.title} + + + + {seasonPartnerLines.join("\n")} + + + ); + })} diff --git a/app/showDetails.tsx b/app/showDetails.tsx index e494ab1..8c27900 100644 --- a/app/showDetails.tsx +++ b/app/showDetails.tsx @@ -4,6 +4,7 @@ import ShowInfo from "@/components/ui/ShowInfo"; import ParticipantDetails from "@/components/ParticipantDeatails"; import React from "react"; import { useSeasonContext } from "@/contexts/SeasonContext"; +import { getShowColors } from "@/constants/colors"; import { Dimensions, Image, @@ -12,7 +13,6 @@ import { TouchableOpacity, View, } from "react-native"; -import * as WebBrowser from "expo-web-browser"; import styles from "./stackStyles/showDetailStyles"; export default function ShowDetails() { @@ -23,6 +23,8 @@ export default function ShowDetails() { genres, streamingService, id, + startDate, + endDate, logoUri, } = useLocalSearchParams(); const [selectedParticipants, setSelectedParticipants] = @@ -37,6 +39,8 @@ export default function ShowDetails() { const [pLoading, setPLoading] = React.useState(false); const [pError, setPError] = React.useState(null); + const { tabColor, seasonColor } = getShowColors(Number(id)); + React.useEffect(() => { if (!showId) return; let active = true; @@ -85,6 +89,8 @@ export default function ShowDetails() { seasons={seasonCount} participants={participants.length} streamingService={streamingService as string} + startDate={startDate as string} + endDate={endDate as string | null} /> @@ -103,7 +109,7 @@ export default function ShowDetails() { styles.infoLabel, { fontWeight: selectedParticipants ? "bold" : "normal", - color: selectedParticipants ? "#199edb" : "hsl(0, 0%, 65%)", + color: selectedParticipants ? tabColor : "hsl(0, 0%, 65%)", }, ]} > @@ -142,7 +148,7 @@ export default function ShowDetails() { { backgroundColor: selectedSeason === season - ? "#199edb" + ? seasonColor : "hsl(0, 0%, 20%)", }, ]} @@ -172,7 +178,10 @@ export default function ShowDetails() { {participants.map((p) => ( router.push({ pathname: "/participant", @@ -190,6 +199,8 @@ export default function ShowDetails() { height: "100%", borderRadius: 10, }} + resizeMode="cover" + blurRadius={p.imageUri.includes("pravatar") ? 16 : 0} /> {p.name} diff --git a/app/stackStyles/participantStyles.tsx b/app/stackStyles/participantStyles.tsx index f1182e5..fd61c1b 100644 --- a/app/stackStyles/participantStyles.tsx +++ b/app/stackStyles/participantStyles.tsx @@ -50,7 +50,7 @@ const styles = StyleSheet.create({ }, performedShowsSection: { width: "100%", - height: 375, + height: "100%", paddingLeft: 15, paddingBottom: 20, backgroundColor: "hsl(221, 39%, 0%)", diff --git a/components/ui/ShowInfo.tsx b/components/ui/ShowInfo.tsx index 3390e1e..9493e97 100644 --- a/components/ui/ShowInfo.tsx +++ b/components/ui/ShowInfo.tsx @@ -4,12 +4,16 @@ type ShowInfoProps = { seasons: number; participants: number; streamingService: string; + startDate: string; + endDate?: string | null; }; const ShowInfo = ({ seasons, participants, streamingService, + startDate, + endDate, }: ShowInfoProps) => { return ( diff --git a/constants/colors.ts b/constants/colors.ts new file mode 100644 index 0000000..add52a2 --- /dev/null +++ b/constants/colors.ts @@ -0,0 +1,20 @@ +export type ShowDetailColors = { + tabColor: string; + seasonColor: string; +}; + +export const ShowColors: Record = { + 1: { tabColor: "#009fe2", seasonColor: "#ec5691" }, + 2: { tabColor: "#ffffff", seasonColor: "#3fa8f3" }, + 3: { tabColor: "#ffffff", seasonColor: "#000000" }, + 4: { tabColor: "#8fb4f3", seasonColor: "#4b046c" }, + 5: { tabColor: "#ffffff", seasonColor: "#000000" }, + 6: { tabColor: "#ffffff", seasonColor: "#ff0000" }, + 7: { tabColor: "#25322c", seasonColor: "#957a45" }, + 8: { tabColor: "#ffffff", seasonColor: "#0179b5" }, +}; + +export function getShowColors(showId: number): ShowDetailColors { + if (!showId) return { tabColor: "#009fe2", seasonColor: "#ec5691" }; + return ShowColors[showId] || { tabColor: "#009fe2", seasonColor: "#ec5691" }; +} diff --git a/contexts/PersonContext.tsx b/contexts/PersonContext.tsx index a4bf3ee..e271931 100644 --- a/contexts/PersonContext.tsx +++ b/contexts/PersonContext.tsx @@ -11,6 +11,10 @@ type PersonAppearances = { raw: PersonHistoryEntry[]; byShow: Record; showIds: number[]; + partnersByShow: Record< + number, + { seasonNumber: number; partner?: PersonHistoryEntry["partner"] }[] + >; }; type PersonContextType = { @@ -32,23 +36,34 @@ export const PersonProvider = ({ children }: { children: ReactNode }) => { const buildAppearances = ( entries: PersonHistoryEntry[] ): PersonAppearances => { - const byShow: Record> = {}; + const byShowSet: Record> = {}; + const partnersByShow: PersonAppearances["partnersByShow"] = {}; for (const e of entries) { - if (!byShow[e.showId]) byShow[e.showId] = new Set(); - byShow[e.showId].add(e.seasonNumber); + if (!byShowSet[e.showId]) byShowSet[e.showId] = new Set(); + byShowSet[e.showId].add(e.seasonNumber); + if (!partnersByShow[e.showId]) partnersByShow[e.showId] = []; + partnersByShow[e.showId].push({ + seasonNumber: e.seasonNumber, + partner: e.partner ?? undefined, + }); } - const byShowSorted: Record = Object.fromEntries( - Object.entries(byShow).map(([showId, seasonsSet]) => [ + const byShow: Record = Object.fromEntries( + Object.entries(byShowSet).map(([showId, seasons]) => [ Number(showId), - Array.from(seasonsSet).sort((a, b) => a - b), + Array.from(seasons).sort((a, b) => a - b), ]) ); + + Object.values(partnersByShow).forEach((arr) => + arr.sort((a, b) => a.seasonNumber - b.seasonNumber) + ); return { raw: entries, - byShow: byShowSorted, - showIds: Object.keys(byShowSorted) + byShow, + showIds: Object.keys(byShow) .map(Number) .sort((a, b) => a - b), + partnersByShow, }; }; @@ -65,7 +80,7 @@ export const PersonProvider = ({ children }: { children: ReactNode }) => { ...err, [personId]: e?.message || "Fehler beim Laden", })); - return { raw: [], byShow: {}, showIds: [] }; + return { raw: [], byShow: {}, showIds: [], partnersByShow: {} }; } finally { setLoading((l) => ({ ...l, [personId]: false })); } @@ -90,7 +105,7 @@ export const PersonProvider = ({ children }: { children: ReactNode }) => { const getSeasonsForShow = useCallback( async (personId: number, showId: number) => { const app = await getPersonAppearances(personId); - return app.byShow[showId] || []; + return (app.byShow as Record)[showId] || []; }, [getPersonAppearances] );