feat: implement podcast subscription management, library page, and associated service methods

This commit is contained in:
Michael committed 2026-04-16 13:28:23 +02:00
1 parent 8156b7b228
commit d81b3a6516
3 files changed
+33 -14

No files matched your search

+24 -8
View File
@@ -29,7 +29,13 @@ export const getUserSubscriptions = async (req: Request, res: Response) => {
.populate('podcastId')
.sort({ subscribedAt: -1 });
const podcasts = subscriptions.map((sub) => sub.podcastId);
const podcasts = subscriptions.map((sub) => {
const podcastObj = (sub.podcastId as any).toJSON();
return {
...podcastObj,
subscriptionId: sub._id.toString(),
};
});
res.json({ podcasts, count: podcasts.length });
} catch (error) {
@@ -107,21 +113,31 @@ export const unsubscribe = async (req: Request, res: Response) => {
const { podcastId } = req.params;
// Log for debugging on the server
console.log(`[Unsubscribe] User ${req.user.id} attempting to unsubscribe from podcast ${podcastId}`);
// Log the request
console.log(`[Unsubscribe] User ${req.user.id} attempting to remove: ${podcastId}`);
const subscription = await UserSubscription.findOneAndDelete({
// Method 1: Try deletion by Subscription ID (New robust method)
let subscription = await UserSubscription.findOneAndDelete({
_id: new mongoose.Types.ObjectId(podcastId),
userId: new mongoose.Types.ObjectId(req.user.id),
podcastId: new mongoose.Types.ObjectId(podcastId),
});
// Method 2: Fallback to Podcast ID if Method 1 found nothing (Old compatibility method)
if (!subscription) {
console.warn(`[Unsubscribe] No subscription found for user ${req.user.id} and podcast ${podcastId}`);
console.log(`[Unsubscribe] Not found by Subscription ID, trying by Podcast ID: ${podcastId}`);
subscription = await UserSubscription.findOneAndDelete({
userId: new mongoose.Types.ObjectId(req.user.id),
podcastId: new mongoose.Types.ObjectId(podcastId),
});
}
if (!subscription) {
console.warn(`[Unsubscribe] No subscription record found for deletion.`);
return res.status(404).json({ message: 'Subscription not found' });
}
console.log(`[Unsubscribe] Successfully removed subscription for user ${req.user.id}`);
res.json({ message: 'Unsubscribed successfully' });
console.log(`[Unsubscribe] Successfully removed subscription ${subscription._id}`);
res.json({ message: 'Unsubscribed successfully', deletedId: subscription._id });
} catch (error) {
console.error('Unsubscribe error:', error);
res.status(500).json({ message: 'Failed to unsubscribe' });
+8 -6
View File
@@ -40,8 +40,10 @@ export default function Library() {
['podcasts', 'subscriptions'],
(old: any) => {
if (!old || !old.podcasts) return old;
// Ensure we compare strings to avoid type issues
const filtered = old.podcasts.filter((p: any) => String(p._id) !== String(podcastId));
// Optimistically filter by subscriptionId or _id as fallback
const filtered = old.podcasts.filter((p: any) =>
String(p.subscriptionId || p._id) !== String(id)
);
return { ...old, podcasts: filtered, count: filtered.length };
}
);
@@ -73,9 +75,9 @@ export default function Library() {
}
};
const handleUnsubscribeRequest = (podcastId: string) => {
console.log("[UI] Demande de désabonnement reçue pour l'ID:", podcastId);
setConfirmDeleteId(podcastId);
const handleUnsubscribeRequest = (id: string) => {
console.log("[UI] Demande de désabonnement reçue pour l'ID (Sub/Pod):", id);
setConfirmDeleteId(id);
};
const handleConfirmUnsubscribe = () => {
@@ -230,7 +232,7 @@ export default function Library() {
</div>
) : (
<button
onClick={() => handleUnsubscribeRequest(podcast._id)}
onClick={() => handleUnsubscribeRequest(podcast.subscriptionId || podcast._id)}
className="mt-auto pt-3 border-t border-light-100 flex items-center gap-2 text-sm text-light-500 hover:text-red-600 transition-colors w-full"
>
<Trash2 className="w-4 h-4" />
+1
View File
@@ -13,6 +13,7 @@ export interface Podcast {
lastEpisodeTitle?: string;
lastEpisodeDate?: string;
lastFetched: string;
subscriptionId?: string;
}
export interface PodcastResponse {