Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
ead4252441
commit
d2d9d9691b
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { IonItem, IonLabel, IonIcon, IonItemSliding, IonItemOptions, IonItemOption } from '@ionic/react';
|
||||
import { IonItem, IonLabel, IonIcon } from '@ionic/react';
|
||||
import { trash } from 'ionicons/icons';
|
||||
import { InfiniteScrollList, PageHeader } from '../../components/common';
|
||||
import { useSingers } from '../../hooks';
|
||||
@ -23,27 +23,24 @@ const Singers: React.FC = () => {
|
||||
|
||||
// Render singer item for InfiniteScrollList
|
||||
const renderSingerItem = (singer: Singer) => (
|
||||
<IonItemSliding key={singer.key}>
|
||||
<IonItem detail={false}>
|
||||
<IonLabel>
|
||||
<h3 className="text-sm font-medium text-gray-900">
|
||||
{singer.name}
|
||||
</h3>
|
||||
</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem detail={false}>
|
||||
<IonLabel>
|
||||
<h3 className="text-sm font-medium text-gray-900">
|
||||
{singer.name}
|
||||
</h3>
|
||||
</IonLabel>
|
||||
|
||||
{/* Swipe to Remove (Admin Only) */}
|
||||
{/* Delete Icon (Admin Only) */}
|
||||
{isAdmin && (
|
||||
<IonItemOptions side="end">
|
||||
<IonItemOption
|
||||
color="danger"
|
||||
onClick={() => handleRemoveSinger(singer)}
|
||||
>
|
||||
<IonIcon icon={trash} slot="icon-only" />
|
||||
</IonItemOption>
|
||||
</IonItemOptions>
|
||||
<IonIcon
|
||||
icon={trash}
|
||||
slot="end"
|
||||
color="danger"
|
||||
className="cursor-pointer"
|
||||
onClick={() => handleRemoveSinger(singer)}
|
||||
/>
|
||||
)}
|
||||
</IonItemSliding>
|
||||
</IonItem>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
update
|
||||
} from 'firebase/database';
|
||||
import { database } from './config';
|
||||
import type { Song, QueueItem, Controller } from '../types';
|
||||
import type { Song, QueueItem, Controller, Singer } from '../types';
|
||||
|
||||
// Basic CRUD operations for controllers
|
||||
export const controllerService = {
|
||||
@ -199,4 +199,62 @@ export const favoritesService = {
|
||||
|
||||
return () => off(favoritesRef);
|
||||
}
|
||||
};
|
||||
|
||||
// Singer management operations
|
||||
export const singerService = {
|
||||
// Remove singer and all their queue items
|
||||
removeSinger: async (controllerName: string, singerName: string) => {
|
||||
// First, remove all queue items for this singer
|
||||
const queueRef = ref(database, `controllers/${controllerName}/player/queue`);
|
||||
const queueSnapshot = await get(queueRef);
|
||||
|
||||
if (queueSnapshot.exists()) {
|
||||
const queue = queueSnapshot.val();
|
||||
const updates: Record<string, QueueItem | null> = {};
|
||||
|
||||
// Find all queue items for this singer and mark them for removal
|
||||
Object.entries(queue).forEach(([key, item]) => {
|
||||
if (item && (item as QueueItem).singer.name === singerName) {
|
||||
updates[key] = null; // Mark for removal
|
||||
}
|
||||
});
|
||||
|
||||
// Remove the queue items
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await update(queueRef, updates);
|
||||
}
|
||||
}
|
||||
|
||||
// Then, remove the singer from the singers list
|
||||
const singersRef = ref(database, `controllers/${controllerName}/player/singers`);
|
||||
const singersSnapshot = await get(singersRef);
|
||||
|
||||
if (singersSnapshot.exists()) {
|
||||
const singers = singersSnapshot.val();
|
||||
const updates: Record<string, Singer | null> = {};
|
||||
|
||||
// Find the singer by name and mark for removal
|
||||
Object.entries(singers).forEach(([key, singer]) => {
|
||||
if (singer && (singer as Singer).name === singerName) {
|
||||
updates[key] = null; // Mark for removal
|
||||
}
|
||||
});
|
||||
|
||||
// Remove the singer
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await update(singersRef, updates);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Listen to singers changes
|
||||
subscribeToSingers: (controllerName: string, callback: (data: Record<string, Singer>) => void) => {
|
||||
const singersRef = ref(database, `controllers/${controllerName}/player/singers`);
|
||||
onValue(singersRef, (snapshot) => {
|
||||
callback(snapshot.exists() ? snapshot.val() : {});
|
||||
});
|
||||
|
||||
return () => off(singersRef);
|
||||
}
|
||||
};
|
||||
@ -1,11 +1,13 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useAppSelector, selectSingersArray, selectIsAdmin } from '../redux';
|
||||
import { useAppSelector, selectSingersArray, selectIsAdmin, selectControllerName } from '../redux';
|
||||
import { useToast } from './useToast';
|
||||
import { singerService } from '../firebase/services';
|
||||
import type { Singer } from '../types';
|
||||
|
||||
export const useSingers = () => {
|
||||
const singers = useAppSelector(selectSingersArray);
|
||||
const isAdmin = useAppSelector(selectIsAdmin);
|
||||
const controllerName = useAppSelector(selectControllerName);
|
||||
const { showSuccess, showError } = useToast();
|
||||
|
||||
const handleRemoveSinger = useCallback(async (singer: Singer) => {
|
||||
@ -14,13 +16,19 @@ export const useSingers = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!controllerName) {
|
||||
showError('Controller not found');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// TODO: Implement remove singer functionality
|
||||
showSuccess(`${singer.name} removed from singers list`);
|
||||
} catch {
|
||||
await singerService.removeSinger(controllerName, singer.name);
|
||||
showSuccess(`${singer.name} removed from singers list and queue`);
|
||||
} catch (error) {
|
||||
console.error('Failed to remove singer:', error);
|
||||
showError('Failed to remove singer');
|
||||
}
|
||||
}, [isAdmin, showSuccess, showError]);
|
||||
}, [isAdmin, controllerName, showSuccess, showError]);
|
||||
|
||||
return {
|
||||
singers,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user