fix: resolve notification ui bugs, audio playback, and team deletion

- Fixed audio playback by rendering a hidden audio tag to comply with browser policies.

- Renamed DELETE /notifications to /notifications/clear-all to prevent route conflicts.

- Notifications badge now clears automatically when the tray is opened.

- Translated notification types to Portuguese (SUCESSO, AVISO, ERRO, INFO).

- Implemented team deletion functionality for Admins.
This commit is contained in:
Cauê Faleiros
2026-03-13 15:52:27 -03:00
parent 4b0d84f2a0
commit 750ad525c8
4 changed files with 183 additions and 86 deletions

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect, useMemo } from 'react';
import { Building2, Users, Plus, Search, Target, ArrowUpRight, Loader2, Edit2, X } from 'lucide-react';
import { getTeams, getUsers, getAttendances, createTeam, updateTeam, getUserById } from '../services/dataService';
import { Building2, Users, Plus, Search, Target, ArrowUpRight, Loader2, Edit2, X, Trash2 } from 'lucide-react';
import { getTeams, getUsers, getAttendances, createTeam, updateTeam, deleteTeam, getUserById } from '../services/dataService';
import { User, Attendance } from '../types';
export const Teams: React.FC = () => {
@@ -46,13 +46,19 @@ export const Teams: React.FC = () => {
setIsSaving(true);
try {
const tid = localStorage.getItem('ctms_tenant_id') || '';
const success = editingTeam
const success = editingTeam
? await updateTeam(editingTeam.id, formData)
: await createTeam({ ...formData, tenantId: tid });
if (success) { setIsModalOpen(false); loadData(); }
} catch (err) { alert('Erro ao salvar'); } finally { setIsSaving(false); }
};
const handleDeleteTeam = async (id: string) => {
if (confirm('Tem certeza que deseja excluir este time? Todos os usuários deste time ficarão sem time atribuído.')) {
await deleteTeam(id);
loadData();
}
};
if (loading && teams.length === 0) return <div className="p-12 text-center text-zinc-400 dark:text-dark-muted transition-colors">Carregando...</div>;
const canManage = currentUser?.role === 'admin' || currentUser?.role === 'super_admin';
@@ -81,7 +87,10 @@ export const Teams: React.FC = () => {
<div className="flex justify-between mb-6">
<div className="p-3 bg-zinc-50 dark:bg-dark-bg text-zinc-600 dark:text-dark-muted rounded-xl border border-zinc-100 dark:border-dark-border"><Building2 size={24} /></div>
{canManage && (
<button onClick={() => { setEditingTeam(t); setFormData({name:t.name, description:t.description||''}); setIsModalOpen(true); }} className="text-zinc-400 dark:text-dark-muted hover:text-zinc-900 dark:hover:text-dark-text p-2 rounded-lg hover:bg-zinc-50 dark:hover:bg-dark-bg transition-all"><Edit2 size={18} /></button>
<div className="flex items-center gap-2">
<button onClick={() => { setEditingTeam(t); setFormData({name:t.name, description:t.description||''}); setIsModalOpen(true); }} className="text-zinc-400 dark:text-dark-muted hover:text-zinc-900 dark:hover:text-dark-text p-2 rounded-lg hover:bg-zinc-50 dark:hover:bg-dark-bg transition-all"><Edit2 size={18} /></button>
<button onClick={() => handleDeleteTeam(t.id)} className="text-zinc-400 dark:text-dark-muted hover:text-red-600 dark:hover:text-red-500 p-2 rounded-lg hover:bg-red-50 dark:hover:bg-red-900/30 transition-all"><Trash2 size={18} /></button>
</div>
)}
</div>
<h3 className="text-lg font-bold text-zinc-900 dark:text-zinc-50 mb-1">{t.name}</h3>