118 lines
4.8 KiB
TypeScript
118 lines
4.8 KiB
TypeScript
import React, { useState } from "react";
|
|
import {
|
|
View, Text, Modal, TouchableOpacity,
|
|
ActivityIndicator, useColorScheme,
|
|
} from "react-native";
|
|
import { Ionicons } from "@expo/vector-icons";
|
|
import { Subject } from "../services/api";
|
|
import { useAuth } from "../context/AuthContext";
|
|
|
|
interface Props {
|
|
subject: Subject | null; // null = closed
|
|
onClose: () => void;
|
|
}
|
|
|
|
export default function SubjectSheet({ subject, onClose }: Props) {
|
|
const dark = useColorScheme() === "dark";
|
|
const { isSubscribed, subscribe, unsubscribe, user } = useAuth();
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
if (!subject) return null;
|
|
|
|
const subscribed = isSubscribed(subject.id);
|
|
const accent = dark ? "#E07B45" : "#C4622D";
|
|
|
|
const toggle = async () => {
|
|
setLoading(true);
|
|
try {
|
|
if (subscribed) await unsubscribe(subject.id);
|
|
else await subscribe(subject.id);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
visible={!!subject}
|
|
transparent
|
|
animationType="fade"
|
|
onRequestClose={onClose}
|
|
>
|
|
{/* Backdrop */}
|
|
<TouchableOpacity
|
|
className="flex-1 justify-end"
|
|
style={{ backgroundColor: "rgba(0,0,0,0.45)" }}
|
|
activeOpacity={1}
|
|
onPress={onClose}
|
|
>
|
|
{/* Sheet — stop tap propagation */}
|
|
<TouchableOpacity activeOpacity={1} onPress={() => { }}>
|
|
<View
|
|
className={`rounded-t-3xl px-6 pt-4 pb-10 ${dark ? "bg-obsidian-100" : "bg-surface-light"
|
|
}`}
|
|
>
|
|
{/* Drag handle */}
|
|
<View className={`w-10 h-1 rounded-full self-center mb-5 ${dark ? "bg-obsidian-50" : "bg-parchment-300"}`} />
|
|
|
|
{/* Group pill */}
|
|
<View
|
|
className="self-start px-2.5 py-1 rounded-full mb-3"
|
|
style={{ backgroundColor: accent + "20" }}
|
|
>
|
|
</View>
|
|
|
|
{/* Subject name */}
|
|
<Text className={`text-2xl font-display font-bold mb-1 ${dark ? "text-ink-dark" : "text-ink-light"}`}>
|
|
{subject.name}
|
|
</Text>
|
|
|
|
<Text className={`text-sm font-sans mb-6 ${dark ? "text-muted-dark" : "text-muted-light"}`}>
|
|
{subscribed
|
|
? "You're subscribed to this subject."
|
|
: "Subscribe to see this subject in your feed."}
|
|
</Text>
|
|
|
|
{/* Subscribe / Unsubscribe button */}
|
|
{user ? (
|
|
<TouchableOpacity
|
|
onPress={toggle}
|
|
disabled={loading}
|
|
className="py-4 rounded-2xl items-center flex-row justify-center gap-2"
|
|
style={{
|
|
backgroundColor: subscribed
|
|
? dark ? "#2C2A27" : "#F0EDE8"
|
|
: accent,
|
|
}}
|
|
activeOpacity={0.8}
|
|
>
|
|
{loading ? (
|
|
<ActivityIndicator color={subscribed ? accent : "#fff"} />
|
|
) : (
|
|
<>
|
|
<Ionicons
|
|
name={subscribed ? "bookmark" : "bookmark-outline"}
|
|
size={17}
|
|
color={subscribed ? accent : "#fff"}
|
|
/>
|
|
<Text
|
|
className="text-sm font-sans font-semibold"
|
|
style={{ color: subscribed ? accent : "#fff" }}
|
|
>
|
|
{subscribed ? "Unsubscribe" : "Subscribe"}
|
|
</Text>
|
|
</>
|
|
)}
|
|
</TouchableOpacity>
|
|
) : (
|
|
<Text className={`text-center text-sm font-sans ${dark ? "text-muted-dark" : "text-muted-light"}`}>
|
|
Sign in to subscribe to subjects.
|
|
</Text>
|
|
)}
|
|
</View>
|
|
</TouchableOpacity>
|
|
</TouchableOpacity>
|
|
</Modal>
|
|
);
|
|
}
|