singsalot/src/components/common/SelectSinger.tsx

112 lines
3.4 KiB
TypeScript

import React, { useState } from 'react';
import {
IonModal,
IonContent,
IonList,
IonItem,
IonLabel
} from '@ionic/react';
import { useAppSelector } from '../../redux';
import { selectSingersArray, selectControllerName, selectQueueObject } from '../../redux';
import { queueService } from '../../firebase/services';
import { useToast } from '../../hooks/useToast';
import { ModalHeader } from './ModalHeader';
import type { Song, Singer, QueueItem } from '../../types';
interface SelectSingerProps {
isOpen: boolean;
onClose: () => void;
song: Song;
}
const SelectSinger: React.FC<SelectSingerProps> = ({ isOpen, onClose, song }) => {
const singers = useAppSelector(selectSingersArray);
const controllerName = useAppSelector(selectControllerName);
const currentQueue = useAppSelector(selectQueueObject);
const { showSuccess, showError } = useToast();
const [isLoading, setIsLoading] = useState(false);
const handleSelectSinger = async (singer: Singer) => {
if (!controllerName) {
showError('Controller not found');
return;
}
setIsLoading(true);
try {
// Calculate the next order by finding the highest order value and adding 1
const queueItems = Object.values(currentQueue) as QueueItem[];
const maxOrder = queueItems.length > 0
? Math.max(...queueItems.map(item => item.order || 0))
: 0;
const nextOrder = maxOrder + 1;
const queueItem: Omit<QueueItem, 'key'> = {
order: nextOrder,
singer: {
name: singer.name,
lastLogin: singer.lastLogin,
},
song: song,
};
await queueService.addToQueue(controllerName, queueItem);
showSuccess(`${song.title} added to queue for ${singer.name}`);
onClose();
} catch (error) {
console.error('Failed to add song to queue:', error);
showError('Failed to add song to queue');
} finally {
setIsLoading(false);
}
};
return (
<IonModal
isOpen={isOpen}
onDidDismiss={onClose}
breakpoints={[0, 0.5, 0.8]}
initialBreakpoint={0.8}
keepContentsMounted={false}
backdropDismiss={true}
>
<ModalHeader title="Select Singer" onClose={onClose} />
<IonContent>
{/* Song Information */}
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
<h2 className="text-lg font-semibold mb-2">{song.title}</h2>
<p className="text-sm text-gray-600 dark:text-gray-400 italic mb-1">{song.artist}</p>
<p className="text-xs text-gray-500 dark:text-gray-500">{song.path}</p>
</div>
{/* Singers List */}
<IonList>
{singers.map((singer) => (
<IonItem
key={singer.key}
button
onClick={() => handleSelectSinger(singer)}
disabled={isLoading}
>
<IonLabel>
<h2>{singer.name}</h2>
<p className="text-sm text-gray-500 dark:text-gray-400">
Last login: {new Date(singer.lastLogin).toLocaleDateString()}
</p>
</IonLabel>
</IonItem>
))}
</IonList>
{singers.length === 0 && (
<div className="p-4 text-center text-gray-500 dark:text-gray-400">
No singers available
</div>
)}
</IonContent>
</IonModal>
);
};
export default SelectSinger;