looood / src /components /create-group-modal.tsx
looda3131's picture
Clean push without any binary history
cc276cc
"use client";
import { useState, useEffect } from 'react';
import { useAuth } from '@/contexts/auth-context';
import { useContacts } from '@/contexts/contacts-context';
import { useGroups } from '@/contexts/groups-context';
import { useSettings } from '@/contexts/settings-context';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Checkbox } from './ui/checkbox';
import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
import type { GroupType } from '@/lib/types';
import { RadioGroup, RadioGroupItem } from './ui/radio-group';
import { Book, Gamepad2, Users, Heart, ArrowLeft, X } from 'lucide-react';
import { cn } from '@/lib/utils';
import { ScrollArea } from './ui/scroll-area';
export function CreateGroupModal({ isOpen, onClose }: { isOpen: boolean; onClose: () => void }) {
const { currentUser } = useAuth();
const { contacts } = useContacts();
const { createGroup } = useGroups();
const { addToast, t, playSound } = useSettings();
const [groupName, setGroupName] = useState('');
const [photoURL, setPhotoURL] = useState('');
const [selectedContacts, setSelectedContacts] = useState<string[]>([]);
const [groupType, setGroupType] = useState<GroupType>('general');
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (currentUser && isOpen) {
setSelectedContacts([currentUser.uid]);
setGroupName('');
setPhotoURL('');
setGroupType('general');
}
}, [currentUser, isOpen]);
const handleToggleContact = (uid: string) => {
if (uid === currentUser?.uid) return;
playSound('touch');
setSelectedContacts(prev =>
prev.includes(uid) ? prev.filter(id => id !== uid) : [...prev, uid]
);
};
const handleCreate = async () => {
if (!groupName.trim()) {
addToast('Please enter a name for the group.', { variant: 'destructive' });
return;
}
if (!currentUser) return;
setIsLoading(true);
playSound('send');
const memberUids = selectedContacts.filter(uid => uid !== currentUser.uid);
await createGroup(groupName, photoURL, memberUids, groupType);
setIsLoading(false);
onClose();
};
const groupTypeOptions = [
{ id: 'general', label: t('general') },
{ id: 'study', label: t('study') },
{ id: 'gaming', label: t('gaming') },
{ id: 'friends', label: t('friends') },
];
if (!isOpen || !currentUser) return null;
return (
<div className="absolute inset-0 z-50 flex flex-col h-full bg-background/80 backdrop-blur-md animate-fade-in md:items-center md:justify-center md:bg-black/50">
<div className="w-full h-full flex flex-col bg-background md:max-w-2xl md:h-auto md:max-h-[90vh] md:rounded-xl md:border md:shadow-lg">
<header className="flex-shrink-0 flex items-center justify-between gap-4 p-4 border-b bg-card/80 backdrop-blur-sm z-10 sticky top-0 md:rounded-t-xl">
<div className='flex items-center gap-2'>
<Button onClick={onClose} variant="ghost" size="icon">
<X />
</Button>
<h1 className="text-xl font-bold">{t('createGroupTitle')}</h1>
</div>
<Button onClick={handleCreate} disabled={isLoading || !groupName.trim()} className="btn-gradient">
{isLoading ? 'Creating...' : t('createGroupTitle')}
</Button>
</header>
<ScrollArea className="flex-1">
<main className="p-4 md:p-8 w-full space-y-8">
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="group-name">{t('groupName')}</Label>
<Input id="group-name" value={groupName} onChange={e => setGroupName(e.target.value)} />
</div>
<div className="space-y-2">
<Label htmlFor="group-photo">{t('groupPhotoUrl')}</Label>
<Input id="group-photo" value={photoURL} onChange={e => setPhotoURL(e.target.value)} placeholder="https://example.com/image.png" />
</div>
<div className="space-y-2">
<Label>{t('groupType')}</Label>
<RadioGroup value={groupType} onValueChange={(value) => setGroupType(value as GroupType)} className="grid grid-cols-2 lg:grid-cols-4 gap-2">
{groupTypeOptions.map(option => (
<Label
key={option.id}
htmlFor={option.id}
className={cn(
"flex items-center gap-3 p-3 border rounded-lg cursor-pointer transition-colors",
"hover:bg-muted",
groupType === option.id && "bg-primary text-primary-foreground border-primary"
)}
>
<RadioGroupItem value={option.id as string} id={option.id} className="sr-only"/>
{option.id === 'general' && <Users className="h-5 w-5" />}
{option.id === 'study' && <Book className="h-5 w-5" />}
{option.id === 'gaming' && <Gamepad2 className="h-5 w-5" />}
{option.id === 'friends' && <Heart className="h-5 w-5" />}
<span>{option.label}</span>
</Label>
))}
</RadioGroup>
</div>
<div>
<Label>{t('inviteMembers')}</Label>
<div className="max-h-60 overflow-y-auto border rounded-lg p-2 mt-2 space-y-2">
<div className="flex items-center justify-between p-2 rounded-lg bg-muted/50">
<Label htmlFor={`contact-${currentUser.uid}`} className="flex items-center gap-3 cursor-not-allowed">
<Avatar>
<AvatarImage src={currentUser.photoURL} alt={currentUser.displayName} />
<AvatarFallback>{currentUser.displayName.charAt(0)}</AvatarFallback>
</Avatar>
<span className="font-medium">{currentUser.displayName} {t('you')}</span>
</Label>
<Checkbox
id={`contact-${currentUser.uid}`}
checked={true}
disabled
/>
</div>
{contacts.length > 0 ? contacts.map(contact => (
<div key={contact.uid} className="flex items-center justify-between p-2 rounded-lg hover:bg-muted">
<Label htmlFor={`contact-${contact.uid}`} className="flex items-center gap-3 cursor-pointer flex-1">
<Avatar>
<AvatarImage src={contact.photoURL} alt={contact.name} />
<AvatarFallback>{contact.name.charAt(0)}</AvatarFallback>
</Avatar>
<span className="font-medium">{contact.name}</span>
</Label>
<Checkbox
id={`contact-${contact.uid}`}
checked={selectedContacts.includes(contact.uid)}
onCheckedChange={() => handleToggleContact(contact.uid)}
/>
</div>
)) : <p className="text-muted-foreground text-center text-sm p-4">{t('noContactsToInvite')}</p>}
</div>
</div>
</div>
</main>
</ScrollArea>
</div>
</div>
);
}