108 lines
3.3 KiB
TypeScript
108 lines
3.3 KiB
TypeScript
import { UserTestResponse } from "@/api/types";
|
|
import formatISODate from "@/utils/format-iso-date";
|
|
import { getUserTestStatus } from "@/utils/get-user-test-status";
|
|
import getUserTestTitle from "@/utils/get-user-test-title";
|
|
import { FontAwesome5 } from "@expo/vector-icons";
|
|
import { Pressable, StyleSheet, View } from "react-native";
|
|
import { Badge, BadgeText } from "./ui/badge";
|
|
import { Divider } from "./ui/divider";
|
|
import Panel from "./ui/panel";
|
|
import { Skeleton } from "./ui/skeleton";
|
|
import { ThemedText } from "./ui/themed-text";
|
|
|
|
type BadgeType = "muted" | "success" | "info" | "warning" | "error";
|
|
enum TestStatus {
|
|
Completed = "Completed",
|
|
Expired = "Expired",
|
|
InProgress = "In Progress",
|
|
}
|
|
|
|
interface UserTestProps {
|
|
userTest?: UserTestResponse;
|
|
onPress?: (userTest: UserTestResponse) => void;
|
|
}
|
|
|
|
const UserTest = ({ userTest, onPress }: UserTestProps) => {
|
|
if (!userTest) return <Skeleton className="h-20" />;
|
|
|
|
const title = getUserTestTitle(userTest);
|
|
|
|
const testStatus = getUserTestStatus(userTest);
|
|
let scoreType: BadgeType = "muted";
|
|
|
|
if (userTest.is_completed || !userTest.is_available) {
|
|
if (userTest.score >= 80) scoreType = "success";
|
|
else if (userTest.score >= 60) scoreType = "info";
|
|
else if (userTest.score >= 40) scoreType = "warning";
|
|
else if (userTest.score >= 0) scoreType = "error";
|
|
}
|
|
const successAnswers = userTest.answers.filter(answer => answer.is_correct).length;
|
|
|
|
let testStatusType: BadgeType = "warning";
|
|
if (testStatus === TestStatus.Completed) testStatusType = "success";
|
|
else if (testStatus === TestStatus.Expired) testStatusType = "error";
|
|
|
|
return (
|
|
<Pressable onPress={() => onPress?.(userTest)}>
|
|
<Panel>
|
|
<View className="justify-between flex-row items-center">
|
|
<Badge action={testStatusType}>
|
|
<BadgeText>
|
|
<FontAwesome5 name="info-circle" /> {testStatus}
|
|
</BadgeText>
|
|
</Badge>
|
|
<Badge action={scoreType}>
|
|
<BadgeText>
|
|
<FontAwesome5 name="star" /> {userTest.score}
|
|
</BadgeText>
|
|
</Badge>
|
|
</View>
|
|
<Divider className="mt-2 mb-2" />
|
|
|
|
<ThemedText style={styles.testTitle}>{title}</ThemedText>
|
|
|
|
<View className="flex-row flex-wrap">
|
|
<View className="mr-6">
|
|
<View>
|
|
<ThemedText type="meta">Started at:</ThemedText>
|
|
</View>
|
|
<View>
|
|
<ThemedText>{formatISODate(userTest.created_at)}</ThemedText>
|
|
</View>
|
|
</View>
|
|
<View>
|
|
<View>
|
|
<ThemedText type="meta">Closed at:</ThemedText>
|
|
</View>
|
|
<View>
|
|
<ThemedText>{formatISODate(userTest.closed_at)}</ThemedText>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
|
|
<Divider className="mt-2 mb-2" />
|
|
|
|
<View className="justify-between flex-row items-center">
|
|
<ThemedText type="meta">
|
|
{userTest.answers.length} Questions
|
|
</ThemedText>
|
|
|
|
{testStatus !== TestStatus.InProgress && <ThemedText type="meta">
|
|
{successAnswers} / {userTest.answers.length} Correct
|
|
</ThemedText>}
|
|
</View>
|
|
</Panel>
|
|
</Pressable>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
testTitle: {
|
|
fontSize: 18,
|
|
fontWeight: "600",
|
|
marginBottom: 10,
|
|
},
|
|
});
|
|
|
|
export default UserTest;
|