moved files to monorepo and updated controllers to start with /api

This commit is contained in:
2026-05-31 21:04:32 +02:00
parent e4cb598193
commit d6657d83dd
118 changed files with 19894 additions and 0 deletions
+130
View File
@@ -0,0 +1,130 @@
import React, { useEffect, useState } from "react";
import {
View, Text, ScrollView, TouchableOpacity,
ActivityIndicator, useColorScheme,
} from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { Ionicons } from "@expo/vector-icons";
import { Subject, subjectsApi } from "../services/api";
import { useAuth } from "../context/AuthContext";
export default function ManageSubscriptions({ onClose }: { onClose: () => void }) {
const dark = useColorScheme() === "dark";
const { user, isSubscribed, subscribe, unsubscribe } = useAuth();
const accent = dark ? "#E07B45" : "#C4622D";
const [subjects, setSubjects] = useState<Subject[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState("");
const [toggling, setToggling] = useState<string | null>(null);
useEffect(() => {
subjectsApi.getAll(user?.token)
.then(setSubjects)
.catch(() => setError("Couldn't load subjects."))
.finally(() => setLoading(false));
}, []);
const toggle = async (subject: Subject) => {
setToggling(subject.id);
try {
if (isSubscribed(subject.id)) await unsubscribe(subject.id);
else await subscribe(subject.id);
} finally {
setToggling(null);
}
};
return (
<SafeAreaView className={`flex-1 ${dark ? "bg-obsidian-200" : "bg-parchment-50"}`}>
{/* Header */}
<View className={`flex-row items-center px-4 py-4 border-b ${
dark ? "border-border-dark" : "border-border-light"
}`}>
<Text className={`flex-1 text-xl font-display font-bold ${dark ? "text-ink-dark" : "text-ink-light"}`}>
Manage Subscriptions
</Text>
<TouchableOpacity
onPress={onClose}
className={`w-8 h-8 rounded-full items-center justify-center ${dark ? "bg-obsidian-50" : "bg-parchment-200"}`}
>
<Ionicons name="close" size={18} color={dark ? "#706D67" : "#8A8278"} />
</TouchableOpacity>
</View>
{/* Body */}
{loading ? (
<View className="flex-1 items-center justify-center">
<ActivityIndicator color={accent} />
</View>
) : error ? (
<View className="flex-1 items-center justify-center px-8">
<Text className="text-3xl mb-3"></Text>
<Text className={`text-sm font-sans text-center ${dark ? "text-muted-dark" : "text-muted-light"}`}>
{error}
</Text>
</View>
) : (
<ScrollView
contentContainerStyle={{ padding: 16, paddingBottom: 40 }}
showsVerticalScrollIndicator={false}
>
<View className={`rounded-2xl overflow-hidden border ${
dark ? "bg-obsidian-100 border-border-dark" : "bg-surface-light border-border-light"
}`}>
{subjects.map((subject, index) => {
const subscribed = isSubscribed(subject.id);
const busy = toggling === subject.id;
const isLast = index === subjects.length - 1;
return (
<View
key={subject.id}
className={`flex-row items-center px-4 py-3.5 ${
!isLast ? `border-b ${dark ? "border-border-dark" : "border-border-light"}` : ""
}`}
>
{/* Subscribed indicator dot */}
<View
className="w-2 h-2 rounded-full mr-3"
style={{
backgroundColor: subscribed ? accent : "transparent",
borderWidth: subscribed ? 0 : 1.5,
borderColor: dark ? "#706D67" : "#8A8278",
}}
/>
<Text className={`flex-1 text-sm font-sans ${dark ? "text-ink-dark" : "text-ink-light"}`}>
{subject.name}
</Text>
<TouchableOpacity
onPress={() => toggle(subject)}
disabled={!!toggling}
className="px-3 py-1.5 rounded-xl"
style={{
backgroundColor: subscribed
? dark ? "#2C2A27" : "#F0EDE8"
: accent + "20",
}}
activeOpacity={0.7}
>
{busy ? (
<ActivityIndicator size="small" color={accent} style={{ width: 40 }} />
) : (
<Text className="text-xs font-sans font-semibold" style={{ color: accent }}>
{subscribed ? "Unsubscribe" : "Subscribe"}
</Text>
)}
</TouchableOpacity>
</View>
);
})}
</View>
</ScrollView>
)}
</SafeAreaView>
);
}