final: added personHistory
This commit is contained in:
169
apis/personHistoryApi.ts
Normal file
169
apis/personHistoryApi.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
export type PersonMini = {
|
||||
personId: number;
|
||||
name: string;
|
||||
birthDate: string | null;
|
||||
imageUrl?: string | null;
|
||||
};
|
||||
|
||||
export type PersonHistoryRecord = {
|
||||
seasonId: number;
|
||||
showId: number;
|
||||
startDate: string | null;
|
||||
endDate: string | null;
|
||||
seasonNumber: number;
|
||||
partner: PersonMini | null;
|
||||
seasonParticipants: (PersonMini & { partner?: PersonMini | null })[];
|
||||
};
|
||||
|
||||
type RawSeasonNew = {
|
||||
seasonId: number;
|
||||
showId?: number;
|
||||
show?: number;
|
||||
seasonNumber: number;
|
||||
startDate: string | null;
|
||||
endDate: string | null;
|
||||
partner?: {
|
||||
personId: number;
|
||||
name: string;
|
||||
birthDate?: string | null;
|
||||
imageUrl?: string | null;
|
||||
} | null;
|
||||
seasonParticipants?: {
|
||||
personId: number;
|
||||
name: string;
|
||||
birthDate?: string | null;
|
||||
imageUrl?: string | null;
|
||||
}[];
|
||||
};
|
||||
|
||||
type RawPersonOld = {
|
||||
personId: number;
|
||||
name: string;
|
||||
birthDate?: string | null;
|
||||
imageUrl?: string | null;
|
||||
};
|
||||
|
||||
type RawSeasonOld = {
|
||||
seasonId: number;
|
||||
show?: number;
|
||||
showId?: number;
|
||||
seasonNumber: number;
|
||||
startDate: string | null;
|
||||
endDate: string | null;
|
||||
seasonParticipants?:
|
||||
| {
|
||||
id?: { seasonId?: number; personId?: number };
|
||||
person?: RawPersonOld | null;
|
||||
partner?: RawPersonOld | null;
|
||||
}[]
|
||||
| null;
|
||||
};
|
||||
|
||||
const PERSONS_BASE_URL = "http://45.157.177.99:8080/persons";
|
||||
|
||||
function toMini(p: any | undefined | null): PersonMini | null {
|
||||
if (!p || !p.personId || !p.name) return null;
|
||||
return {
|
||||
personId: Number(p.personId),
|
||||
name: String(p.name),
|
||||
birthDate: p.birthDate ?? null,
|
||||
imageUrl: p.imageUrl ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
function isFlatSeason(s: any): s is RawSeasonNew {
|
||||
const sp = s?.seasonParticipants;
|
||||
return Array.isArray(sp) && (sp.length === 0 || "personId" in (sp[0] ?? {}));
|
||||
}
|
||||
|
||||
function mapSeason(
|
||||
s: RawSeasonNew | RawSeasonOld,
|
||||
requestedPersonId: number
|
||||
): PersonHistoryRecord {
|
||||
const showId = Number((s as any).showId ?? (s as any).show ?? 0) || 0;
|
||||
const base = {
|
||||
seasonId: s.seasonId,
|
||||
showId,
|
||||
startDate: s.startDate ?? null,
|
||||
endDate: s.endDate ?? null,
|
||||
seasonNumber: s.seasonNumber,
|
||||
};
|
||||
|
||||
if (isFlatSeason(s)) {
|
||||
const seasonParticipants = Array.isArray(s.seasonParticipants)
|
||||
? s.seasonParticipants
|
||||
.map((p) => toMini(p))
|
||||
.filter((x): x is PersonMini => !!x)
|
||||
: [];
|
||||
|
||||
const partner = toMini(s.partner ?? null);
|
||||
|
||||
return {
|
||||
...base,
|
||||
partner,
|
||||
|
||||
seasonParticipants,
|
||||
};
|
||||
}
|
||||
|
||||
const spOld = (s as RawSeasonOld).seasonParticipants;
|
||||
const seasonParticipantsOld = Array.isArray(spOld)
|
||||
? spOld
|
||||
.map((p) => {
|
||||
const pid = p.person?.personId ?? p.id?.personId;
|
||||
const name = p.person?.name ?? null;
|
||||
if (!pid || !name) return null;
|
||||
|
||||
const me: PersonMini = {
|
||||
personId: Number(pid),
|
||||
name: String(name),
|
||||
birthDate: p.person?.birthDate ?? null,
|
||||
imageUrl: p.person?.imageUrl ?? null,
|
||||
};
|
||||
|
||||
const partnerMini = toMini(p.partner ?? null);
|
||||
|
||||
return {
|
||||
...me,
|
||||
partner: partnerMini,
|
||||
};
|
||||
})
|
||||
.filter((x): x is NonNullable<typeof x> => !!x)
|
||||
: [];
|
||||
|
||||
const me =
|
||||
seasonParticipantsOld.find((pp) => pp.personId === requestedPersonId) ||
|
||||
null;
|
||||
const partner = (me?.partner ?? null) as PersonMini | null;
|
||||
|
||||
return {
|
||||
...base,
|
||||
partner,
|
||||
seasonParticipants: seasonParticipantsOld,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getPersonHistory(
|
||||
personId: number,
|
||||
signal?: AbortSignal
|
||||
): Promise<PersonHistoryRecord[]> {
|
||||
const apiKey = process.env.EXPO_PUBLIC_API_KEY;
|
||||
const url = `${PERSONS_BASE_URL}/${personId}/history`;
|
||||
|
||||
const res = await fetch(url, {
|
||||
signal,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-API-Key": apiKey ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
if (!res.ok) throw new Error("GetPersonHistory failed " + res.status);
|
||||
|
||||
const data: unknown = await res.json();
|
||||
if (!Array.isArray(data)) return [];
|
||||
|
||||
return (data as (RawSeasonNew | RawSeasonOld)[]).map((s) =>
|
||||
mapSeason(s, personId)
|
||||
);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ export type Show = {
|
||||
concept: string;
|
||||
startDate?: string;
|
||||
endDate?: string | null;
|
||||
logoUri: string;
|
||||
logoUrl: string;
|
||||
running: boolean;
|
||||
};
|
||||
|
||||
@@ -58,10 +58,36 @@ export async function getShows(): Promise<Show[]> {
|
||||
streamingService: s.streamingServices,
|
||||
concept: s.concept,
|
||||
running: s.running,
|
||||
logoUri: s.logoUrl ?? "",
|
||||
logoUrl: s.logoUrl ?? "",
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error("Fetch error:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getShowById(showId: number): Promise<Show | null> {
|
||||
const apiKey = process.env.EXPO_PUBLIC_API_KEY;
|
||||
const url = `${SHOW_API_URL}/${showId}`;
|
||||
const res = await fetch(url, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-API-Key": apiKey ?? "",
|
||||
},
|
||||
});
|
||||
if (res.status === 404) return null;
|
||||
if (!res.ok) throw new Error("getShowById failed " + res.status);
|
||||
const s = (await res.json()) as RawShow;
|
||||
return {
|
||||
id: s.showId,
|
||||
title: s.title,
|
||||
description: s.description,
|
||||
genres: s.genre ? s.genre.split(",").map((g) => g.trim()) : [],
|
||||
thumbnailUri: s.thumbnailUrl,
|
||||
bannerUri: s.bannerUrl ?? "",
|
||||
streamingService: s.streamingServices,
|
||||
concept: s.concept,
|
||||
running: s.running,
|
||||
logoUrl: s.logoUrl ?? "",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ export default function HomeScreen() {
|
||||
concept: show.concept,
|
||||
genres: show.genres,
|
||||
streamingService: show.streamingService,
|
||||
logoUri: show.logoUri,
|
||||
logoUri: show.logoUrl,
|
||||
running: String(show.running),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -22,7 +22,6 @@ export default function RootLayout() {
|
||||
<Stack.Screen
|
||||
name="participant"
|
||||
options={{
|
||||
presentation: "fullScreenModal",
|
||||
headerShown: false,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -2,56 +2,188 @@ import styles from "@/app/stackStyles/participantStyles";
|
||||
import { useShowContext } from "@/contexts/ShowContext";
|
||||
import Ionicons from "@expo/vector-icons/Ionicons";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import React, { useMemo, useState } from "react";
|
||||
import { Text, TouchableOpacity, View } from "react-native";
|
||||
import React from "react";
|
||||
import { Text, TouchableOpacity, View, Image, Dimensions } from "react-native";
|
||||
import {
|
||||
getPersonHistory,
|
||||
type PersonMini,
|
||||
type PersonHistoryRecord,
|
||||
} from "@/apis/personHistoryApi";
|
||||
import { getShowById } from "@/apis/showApi";
|
||||
import {
|
||||
GestureHandlerRootView,
|
||||
ScrollView,
|
||||
} from "react-native-gesture-handler";
|
||||
|
||||
export default function ParticipantScreen() {
|
||||
const [appearances] = useState<
|
||||
{
|
||||
showId: number;
|
||||
seasons: number[];
|
||||
}[]
|
||||
>([]);
|
||||
const { shows } = useShowContext();
|
||||
const { name } = useLocalSearchParams();
|
||||
type SeasonEntry = {
|
||||
seasonNumber: number;
|
||||
partner: PersonMini | null;
|
||||
participants: PersonMini[];
|
||||
startDate: string | null;
|
||||
};
|
||||
|
||||
const resolved = useMemo(
|
||||
() =>
|
||||
(appearances as any[])
|
||||
.map((a) => {
|
||||
const show = shows.find((s) => s.id === a.showId);
|
||||
if (!show) return null;
|
||||
return {
|
||||
show,
|
||||
seasons: a.seasons as number[],
|
||||
partners: a.partners as {
|
||||
seasonNumber: number;
|
||||
partner?: { id: number; name: string; imageUrl?: string | null };
|
||||
}[],
|
||||
type AppearanceGroup = {
|
||||
show: {
|
||||
id: number;
|
||||
title: string;
|
||||
bannerUri: string;
|
||||
thumbnailUri: string;
|
||||
};
|
||||
seasons: SeasonEntry[];
|
||||
};
|
||||
|
||||
export default function ParticipantScreen() {
|
||||
const { shows } = useShowContext();
|
||||
const { name, participantId } = useLocalSearchParams();
|
||||
|
||||
const pid = Array.isArray(participantId)
|
||||
? Number(participantId[0])
|
||||
: Number(participantId);
|
||||
|
||||
const [loading, setLoading] = React.useState(false);
|
||||
const [error, setError] = React.useState<string | null>(null);
|
||||
|
||||
const [appearances, setAppearances] = React.useState<AppearanceGroup[]>([]);
|
||||
|
||||
const formatYear = (iso?: string | null) => {
|
||||
if (!iso) return null;
|
||||
const [y] = iso.split("-");
|
||||
return y || null;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!pid || Number.isNaN(pid)) return;
|
||||
const controller = new AbortController();
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const hist = await getPersonHistory(pid, controller.signal);
|
||||
|
||||
const grouped = new Map<number, Map<number, SeasonEntry>>();
|
||||
for (const h of hist) {
|
||||
if (!Number.isFinite(h.showId) || h.showId <= 0) continue;
|
||||
const seasonsForShow =
|
||||
grouped.get(h.showId) ?? new Map<number, SeasonEntry>();
|
||||
|
||||
const existing = seasonsForShow.get(h.seasonNumber);
|
||||
if (existing) {
|
||||
seasonsForShow.set(h.seasonNumber, {
|
||||
seasonNumber: h.seasonNumber,
|
||||
partner: existing.partner ?? h.partner ?? null,
|
||||
participants: existing.participants.length
|
||||
? existing.participants
|
||||
: (h.seasonParticipants ?? []),
|
||||
startDate: existing.startDate ?? h.startDate ?? null,
|
||||
});
|
||||
} else {
|
||||
seasonsForShow.set(h.seasonNumber, {
|
||||
seasonNumber: h.seasonNumber,
|
||||
partner: h.partner ?? null,
|
||||
participants: h.seasonParticipants ?? [],
|
||||
startDate: h.startDate ?? null,
|
||||
});
|
||||
}
|
||||
|
||||
grouped.set(h.showId, seasonsForShow);
|
||||
}
|
||||
|
||||
const showIds = Array.from(grouped.keys());
|
||||
|
||||
const fromContext = showIds
|
||||
.map((id) => shows.find((s) => s.id === id))
|
||||
.filter((s): s is (typeof shows)[number] => !!s);
|
||||
|
||||
const missingIds = showIds.filter(
|
||||
(id) => !fromContext.some((s) => s.id === id)
|
||||
);
|
||||
|
||||
const fetched = await Promise.all(
|
||||
missingIds.map(async (id) => {
|
||||
try {
|
||||
const s = await getShowById(id);
|
||||
return s;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(
|
||||
(
|
||||
v
|
||||
): v is {
|
||||
show: (typeof shows)[number];
|
||||
seasons: number[];
|
||||
partners: {
|
||||
seasonNumber: number;
|
||||
partner?: { id: number; name: string; imageUrl?: string | null };
|
||||
}[];
|
||||
} => !!v
|
||||
),
|
||||
[appearances, shows]
|
||||
);
|
||||
|
||||
const allShows = [
|
||||
...fromContext,
|
||||
...fetched.filter(Boolean),
|
||||
] as typeof shows;
|
||||
|
||||
const result: AppearanceGroup[] = allShows.map((s) => {
|
||||
const seasonsMap = grouped.get(s.id)!;
|
||||
const seasonsSorted = Array.from(seasonsMap.values()).sort(
|
||||
(a, b) => a.seasonNumber - b.seasonNumber
|
||||
);
|
||||
return {
|
||||
show: {
|
||||
id: s.id,
|
||||
title: s.title,
|
||||
bannerUri: s.bannerUri,
|
||||
thumbnailUri: s.thumbnailUri,
|
||||
},
|
||||
seasons: seasonsSorted,
|
||||
};
|
||||
});
|
||||
|
||||
result.sort((a, b) =>
|
||||
a.show.title.localeCompare(b.show.title, "de", {
|
||||
sensitivity: "base",
|
||||
})
|
||||
);
|
||||
|
||||
setAppearances(result);
|
||||
} catch (e: any) {
|
||||
if (!controller.signal.aborted)
|
||||
setError(e?.message || "Fehler beim Laden");
|
||||
} finally {
|
||||
if (!controller.signal.aborted) setLoading(false);
|
||||
}
|
||||
})();
|
||||
|
||||
return () => controller.abort();
|
||||
}, [pid, shows]);
|
||||
|
||||
const [expandedShows, setExpandedShows] = React.useState<Set<number>>(
|
||||
new Set()
|
||||
);
|
||||
const toggleExpand = React.useCallback((showId: number) => {
|
||||
setExpandedShows((prev) => {
|
||||
const next = new Set(prev);
|
||||
if (next.has(showId)) next.delete(showId);
|
||||
else next.add(showId);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const goToShow = React.useCallback((id: number) => {
|
||||
router.push({ pathname: "/showDetails", params: { id: String(id) } });
|
||||
}, []);
|
||||
|
||||
const goToPerson = React.useCallback(
|
||||
(p: PersonMini) => {
|
||||
if (!p?.personId) return;
|
||||
|
||||
if (p.personId === pid) return;
|
||||
router.push({
|
||||
pathname: "/participant",
|
||||
params: { participantId: String(p.personId), name: p.name },
|
||||
});
|
||||
},
|
||||
[pid]
|
||||
);
|
||||
|
||||
return (
|
||||
<GestureHandlerRootView style={styles.mainContainer}>
|
||||
<ScrollView showsVerticalScrollIndicator={false}>
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
contentContainerStyle={{ paddingBottom: 20, paddingTop: 10 }}
|
||||
>
|
||||
<Text style={styles.participantName}>{name}</Text>
|
||||
<TouchableOpacity
|
||||
style={styles.closeIcon}
|
||||
@@ -63,42 +195,152 @@ export default function ParticipantScreen() {
|
||||
<View style={styles.performedShowsSection}>
|
||||
<Text style={styles.performedShowsTitle}>Auftritte:</Text>
|
||||
|
||||
<View style={styles.showContainer}></View>
|
||||
|
||||
{/* <ScrollView
|
||||
<ScrollView
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
style={{
|
||||
width: "100%",
|
||||
marginTop: 15,
|
||||
style={{ flex: 1 }}
|
||||
contentContainerStyle={{
|
||||
gap: 20,
|
||||
paddingHorizontal: 15,
|
||||
paddingLeft: 30,
|
||||
}}
|
||||
>
|
||||
{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}`;
|
||||
});
|
||||
{appearances.map(({ show, seasons }) => {
|
||||
const partners = Array.from(
|
||||
new Map(
|
||||
seasons
|
||||
.map((s) => s.partner)
|
||||
.filter((p): p is NonNullable<typeof p> => !!p)
|
||||
.map((p) => [p.personId, p])
|
||||
).values()
|
||||
);
|
||||
|
||||
const allParticipants = Array.from(
|
||||
new Map(
|
||||
seasons
|
||||
.flatMap((s) => s.participants)
|
||||
.filter((p) => p.personId !== pid)
|
||||
.map((p) => [p.personId, p])
|
||||
).values()
|
||||
);
|
||||
|
||||
const isExpanded = expandedShows.has(show.id);
|
||||
const visible = isExpanded
|
||||
? allParticipants
|
||||
: allParticipants.slice(0, 12);
|
||||
const restCount = Math.max(
|
||||
allParticipants.length - visible.length,
|
||||
0
|
||||
);
|
||||
|
||||
return (
|
||||
<TouchableOpacity key={show.id} style={styles.showContainer}>
|
||||
<View key={show.id} style={styles.card}>
|
||||
<TouchableOpacity
|
||||
style={styles.showContainer}
|
||||
onPress={() => goToShow(show.id)}
|
||||
>
|
||||
<Image
|
||||
source={{ uri: show.thumbnailUri }}
|
||||
source={{ uri: show.bannerUri || show.thumbnailUri }}
|
||||
style={styles.showImage}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
<Text style={styles.showTitle} numberOfLines={2}>
|
||||
</TouchableOpacity>
|
||||
<Text style={styles.showTitle} numberOfLines={1}>
|
||||
{show.title}
|
||||
</Text>
|
||||
<Text style={styles.showSeason}>
|
||||
({formatYear(seasons[0]?.startDate)})
|
||||
</Text>
|
||||
<Text style={styles.showSeason}>
|
||||
Staffel {seasons.map((s) => s.seasonNumber).join(" und ")}
|
||||
</Text>
|
||||
|
||||
<Text
|
||||
style={styles.showSeason}
|
||||
numberOfLines={seasonPartnerLines.length}
|
||||
<View style={styles.horizontalLine} />
|
||||
|
||||
<Text style={[styles.participantLabel, { marginTop: 10 }]}>
|
||||
Weitere Teilnehmer
|
||||
</Text>
|
||||
|
||||
<View style={styles.participantContainer}>
|
||||
<View style={styles.participantRow}>
|
||||
{visible.map((p) => (
|
||||
<TouchableOpacity
|
||||
key={p.personId}
|
||||
style={styles.participantChip}
|
||||
onPress={() => goToPerson(p)}
|
||||
>
|
||||
{seasonPartnerLines.join("\n")}
|
||||
<Text
|
||||
style={styles.participantChipText}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{p.name}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
|
||||
{!isExpanded && restCount > 0 && (
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleExpand(show.id)}
|
||||
style={styles.moreChip}
|
||||
>
|
||||
<Text style={styles.moreChipText}>
|
||||
+{restCount} mehr
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
{isExpanded && allParticipants.length > 12 && (
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleExpand(show.id)}
|
||||
style={styles.moreChip}
|
||||
>
|
||||
<Text style={styles.moreChipText}>Weniger</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{partners.length > 0 && (
|
||||
<>
|
||||
<View style={styles.horizontalLine} />
|
||||
<Text
|
||||
style={[styles.participantLabel, { marginTop: 10 }]}
|
||||
>
|
||||
Partner
|
||||
</Text>
|
||||
<View
|
||||
style={[
|
||||
styles.showContainer,
|
||||
{
|
||||
backgroundColor: "hsl(221, 39%, 12%)",
|
||||
width: 150,
|
||||
marginTop: 20,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Image
|
||||
style={styles.showImage}
|
||||
blurRadius={20}
|
||||
source={{
|
||||
uri: `https://i.pravatar.cc/300?img=${Math.floor(Math.random() * 70)}`,
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
{partners.map((p) => (
|
||||
<Text
|
||||
key={p.personId}
|
||||
style={styles.partnerLabel}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{p.name}
|
||||
</Text>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</ScrollView> */}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</GestureHandlerRootView>
|
||||
|
||||
@@ -4,7 +4,6 @@ import StackHeader from "@/components/ui/StackHeader";
|
||||
import { useSeasonContext } from "@/contexts/SeasonContext";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
Dimensions,
|
||||
Image,
|
||||
@@ -99,6 +98,21 @@ export default function ShowDetails() {
|
||||
});
|
||||
}, [startDate]);
|
||||
|
||||
const handleOpenParticipant = React.useCallback(
|
||||
(p: { id: number; name: string }) => {
|
||||
router.push({
|
||||
pathname: "/participant",
|
||||
params: {
|
||||
participantId: p.id,
|
||||
name: p.name,
|
||||
originShowId: String(showId),
|
||||
originSeason: String(selectedSeason),
|
||||
},
|
||||
});
|
||||
},
|
||||
[showId, selectedSeason]
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.mainContainer}>
|
||||
<StackHeader />
|
||||
@@ -210,23 +224,11 @@ export default function ShowDetails() {
|
||||
styles.participantContainer,
|
||||
{ backgroundColor: "hsl(336, 79%, 63%)" },
|
||||
]}
|
||||
onPress={() =>
|
||||
router.push({
|
||||
pathname: "/participant",
|
||||
params: {
|
||||
participantId: p.id,
|
||||
name: p.name,
|
||||
},
|
||||
})
|
||||
}
|
||||
onPress={() => handleOpenParticipant(p)}
|
||||
>
|
||||
<Image
|
||||
source={{ uri: p.imageUri }}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
borderRadius: 10,
|
||||
}}
|
||||
style={{ width: "100%", height: "100%", borderRadius: 10 }}
|
||||
resizeMode="cover"
|
||||
blurRadius={p.imageUri.includes("pravatar") ? 16 : 0}
|
||||
/>
|
||||
|
||||
@@ -7,15 +7,15 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
closeIcon: {
|
||||
position: "absolute",
|
||||
top: Dimensions.get("window").height * 0.07,
|
||||
top: Dimensions.get("window").height * 0.065,
|
||||
right: 15,
|
||||
},
|
||||
participantName: {
|
||||
color: "white",
|
||||
fontSize: 24,
|
||||
fontSize: 20,
|
||||
fontWeight: "600",
|
||||
textAlign: "center",
|
||||
marginTop: Dimensions.get("window").height * 0.075,
|
||||
marginTop: Dimensions.get("window").height * 0.06,
|
||||
},
|
||||
participantImage: {
|
||||
width: "100%",
|
||||
@@ -49,7 +49,7 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
performedShowsSection: {
|
||||
width: "100%",
|
||||
height: Dimensions.get("window").height,
|
||||
height: "100%",
|
||||
backgroundColor: "hsl(221, 39%, 0%)",
|
||||
marginTop: 20,
|
||||
},
|
||||
@@ -60,14 +60,7 @@ const styles = StyleSheet.create({
|
||||
marginTop: 15,
|
||||
marginLeft: 15,
|
||||
},
|
||||
showContainer: {
|
||||
width: "85%",
|
||||
height: 180,
|
||||
backgroundColor: "hsl(336, 79%, 63%)",
|
||||
borderRadius: 10,
|
||||
alignSelf: "center",
|
||||
marginTop: 15,
|
||||
},
|
||||
|
||||
showImage: {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
@@ -94,14 +87,89 @@ const styles = StyleSheet.create({
|
||||
fontSize: 12,
|
||||
fontWeight: "600",
|
||||
textAlign: "center",
|
||||
marginTop: 10,
|
||||
marginTop: 15,
|
||||
},
|
||||
showSeason: {
|
||||
color: "hsl(0, 0%, 80%)",
|
||||
fontSize: 12,
|
||||
fontWeight: "400",
|
||||
textAlign: "center",
|
||||
marginTop: 3,
|
||||
marginTop: 5,
|
||||
},
|
||||
showContainer: {
|
||||
width: Dimensions.get("window").width - 75,
|
||||
height: 200,
|
||||
borderRadius: 15,
|
||||
marginTop: 20,
|
||||
alignItems: "center",
|
||||
backgroundColor: "hsl(336, 79%, 63%)",
|
||||
},
|
||||
|
||||
card: {
|
||||
width: Dimensions.get("window").width - 75,
|
||||
alignItems: "center",
|
||||
},
|
||||
|
||||
horizontalLine: {
|
||||
height: 50,
|
||||
width: 2,
|
||||
backgroundColor: "hsl(0, 0%, 70%)",
|
||||
marginTop: 10,
|
||||
alignSelf: "center",
|
||||
},
|
||||
partnerLabel: {
|
||||
color: "hsl(0, 0%, 80%)",
|
||||
fontSize: 12,
|
||||
fontWeight: "400",
|
||||
textAlign: "center",
|
||||
marginTop: 10,
|
||||
},
|
||||
participantContainer: {
|
||||
width: "auto",
|
||||
height: "auto",
|
||||
borderRadius: 15,
|
||||
marginTop: 15,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "hsl(221, 39%, 12%)",
|
||||
padding: 10,
|
||||
},
|
||||
|
||||
participantLabel: {
|
||||
color: "white",
|
||||
fontSize: 12,
|
||||
},
|
||||
participantRow: {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
gap: 6,
|
||||
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
},
|
||||
|
||||
participantChip: {
|
||||
paddingVertical: 4,
|
||||
paddingHorizontal: 8,
|
||||
borderRadius: 12,
|
||||
backgroundColor: "hsl(221, 39%, 18%)",
|
||||
maxWidth: 160,
|
||||
},
|
||||
participantChipText: {
|
||||
color: "hsl(0, 0%, 85%)",
|
||||
fontSize: 11,
|
||||
},
|
||||
|
||||
moreChip: {
|
||||
paddingVertical: 4,
|
||||
paddingHorizontal: 10,
|
||||
borderRadius: 12,
|
||||
backgroundColor: "hsl(221, 39%, 28%)",
|
||||
},
|
||||
moreChipText: {
|
||||
color: "white",
|
||||
fontSize: 11,
|
||||
fontWeight: "600",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user