Refatoracao geral: limpeza de logs, correcoes de fim de linha, animacoes framer-motion e automacao de deploy no package.json
This commit is contained in:
@@ -9,7 +9,8 @@
|
|||||||
"build:analyze": "vite build --analyze",
|
"build:analyze": "vite build --analyze",
|
||||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"type-check": "tsc --noEmit"
|
"type-check": "tsc --noEmit",
|
||||||
|
"deploy": "npm run build && git add . && git commit -m 'build and deploy auto' && git push"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@supabase/supabase-js": "^2.38.4",
|
"@supabase/supabase-js": "^2.38.4",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||||
import { FolderOpen, FileText, Clock, CheckCircle, Edit, Copy, Trash2 } from 'lucide-react'
|
import { FolderOpen, FileText, Clock, CheckCircle, Edit, Copy, Trash2 } from 'lucide-react'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
@@ -9,6 +8,7 @@ import { useNavigate } from 'react-router-dom'
|
|||||||
import { supabase } from '@/lib/supabase'
|
import { supabase } from '@/lib/supabase'
|
||||||
import { deleteDatabook } from '@/lib/mutations'
|
import { deleteDatabook } from '@/lib/mutations'
|
||||||
import { toast } from '@/lib/toast'
|
import { toast } from '@/lib/toast'
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion'
|
||||||
|
|
||||||
// Função para obter cores do status
|
// Função para obter cores do status
|
||||||
const getStatusColor = (status: string) => {
|
const getStatusColor = (status: string) => {
|
||||||
@@ -58,37 +58,24 @@ export default function Dashboard() {
|
|||||||
|
|
||||||
if (error) throw error
|
if (error) throw error
|
||||||
|
|
||||||
// Calcular progresso real baseado em documentos
|
|
||||||
const projetosComProgresso = await Promise.all(
|
const projetosComProgresso = await Promise.all(
|
||||||
((data as any) || []).map(async (projeto: any) => {
|
((data as any) || []).map(async (projeto: any) => {
|
||||||
// Buscar total de tópicos do template
|
|
||||||
const { count: totalTopicos } = await supabase
|
const { count: totalTopicos } = await supabase
|
||||||
.from('templates_topicos')
|
.from('templates_topicos')
|
||||||
.select('*', { count: 'exact' })
|
.select('*', { count: 'exact' })
|
||||||
|
|
||||||
// Buscar documentos do projeto
|
const { data: documentos } = await supabase
|
||||||
const { data: documentos, count: totalDocumentos } = await supabase
|
|
||||||
.from('documentos_auto_indexados')
|
.from('documentos_auto_indexados')
|
||||||
.select('secao_numero', { count: 'exact' })
|
.select('secao_numero')
|
||||||
.eq('databook_id', (projeto as any).id)
|
.eq('databook_id',projeto.id)
|
||||||
|
|
||||||
// Contar seções únicas com documentos
|
const secoesUnicas = new Set((documentos as any)?.map((d: any) => d.secao_numero).filter(Boolean))
|
||||||
const secoesUnicas = new Set(documentos?.map(d => d.secao_numero).filter(Boolean))
|
|
||||||
const secoesComDocs = secoesUnicas.size
|
const secoesComDocs = secoesUnicas.size
|
||||||
|
|
||||||
// Calcular percentual
|
|
||||||
const progresso = (totalTopicos && totalTopicos > 0)
|
const progresso = (totalTopicos && totalTopicos > 0)
|
||||||
? Math.round((secoesComDocs / totalTopicos) * 100)
|
? Math.round((secoesComDocs / totalTopicos) * 100)
|
||||||
: 0
|
: 0
|
||||||
|
|
||||||
console.log(`Projeto ${projeto.numero_projeto}:`, {
|
|
||||||
totalTopicos,
|
|
||||||
totalDocumentos,
|
|
||||||
secoesComDocs,
|
|
||||||
progresso
|
|
||||||
})
|
|
||||||
|
|
||||||
// Atualizar progresso no banco se mudou
|
|
||||||
if (progresso !== projeto.progresso_percentual) {
|
if (progresso !== projeto.progresso_percentual) {
|
||||||
await supabase
|
await supabase
|
||||||
.from('projetos')
|
.from('projetos')
|
||||||
@@ -145,13 +132,11 @@ export default function Dashboard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleEdit = (projeto: any) => {
|
const handleEdit = (projeto: any) => {
|
||||||
// Navegar para página de edição (a ser implementada)
|
|
||||||
navigate(`/databook/${projeto.id}/editar`)
|
navigate(`/databook/${projeto.id}/editar`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClone = async (projeto: any) => {
|
const handleClone = async (projeto: any) => {
|
||||||
try {
|
try {
|
||||||
// Buscar dados completos do projeto
|
|
||||||
const { data: projetoCompleto } = await supabase
|
const { data: projetoCompleto } = await supabase
|
||||||
.from('projetos')
|
.from('projetos')
|
||||||
.select('*, databooks_mestres(*)')
|
.select('*, databooks_mestres(*)')
|
||||||
@@ -163,7 +148,6 @@ export default function Dashboard() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Criar cópia do projeto
|
|
||||||
const { data: novoProjeto } = await supabase
|
const { data: novoProjeto } = await supabase
|
||||||
.from('projetos')
|
.from('projetos')
|
||||||
.insert([{
|
.insert([{
|
||||||
@@ -177,9 +161,8 @@ export default function Dashboard() {
|
|||||||
.select()
|
.select()
|
||||||
.single()
|
.single()
|
||||||
|
|
||||||
if (novoProjeto && projetoCompleto.databooks_mestres) {
|
if (novoProjeto && (projetoCompleto as any).databooks_mestres) {
|
||||||
// Copiar databook mestre
|
const databookMestre = (projetoCompleto as any).databooks_mestres
|
||||||
const databookMestre = projetoCompleto.databooks_mestres
|
|
||||||
await supabase
|
await supabase
|
||||||
.from('databooks_mestres')
|
.from('databooks_mestres')
|
||||||
.insert([{
|
.insert([{
|
||||||
@@ -206,7 +189,6 @@ export default function Dashboard() {
|
|||||||
queryClient.invalidateQueries({ queryKey: ['projetos'] })
|
queryClient.invalidateQueries({ queryKey: ['projetos'] })
|
||||||
toast.success('Projeto clonado com sucesso!')
|
toast.success('Projeto clonado com sucesso!')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao clonar projeto:', error)
|
|
||||||
toast.error('Erro ao clonar projeto')
|
toast.error('Erro ao clonar projeto')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,25 +198,25 @@ export default function Dashboard() {
|
|||||||
name: 'Total Projetos',
|
name: 'Total Projetos',
|
||||||
value: projetos?.length || 0,
|
value: projetos?.length || 0,
|
||||||
icon: FolderOpen,
|
icon: FolderOpen,
|
||||||
color: 'bg-blue-500',
|
color: 'bg-blue-600',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Em Andamento',
|
name: 'Em Andamento',
|
||||||
value: projetos?.filter(p => p.status === 'em_andamento').length || 0,
|
value: projetos?.filter(p => p.status === 'em_andamento').length || 0,
|
||||||
icon: Clock,
|
icon: Clock,
|
||||||
color: 'bg-yellow-500',
|
color: 'bg-amber-500',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Finalizados',
|
name: 'Finalizados',
|
||||||
value: projetos?.filter(p => p.status === 'finalizado').length || 0,
|
value: projetos?.filter(p => p.status === 'finalizado').length || 0,
|
||||||
icon: CheckCircle,
|
icon: CheckCircle,
|
||||||
color: 'bg-green-500',
|
color: 'bg-emerald-500',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Templates',
|
name: 'Templates',
|
||||||
value: templates?.length || 0,
|
value: (templates as any)?.length || 0,
|
||||||
icon: FileText,
|
icon: FileText,
|
||||||
color: 'bg-purple-500',
|
color: 'bg-violet-600',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -250,126 +232,123 @@ export default function Dashboard() {
|
|||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h1 className="text-3xl font-bold text-gray-900 dark:text-gray-100">Dashboard</h1>
|
<h1 className="text-3xl font-bold text-gray-900 dark:text-gray-100">Dashboard</h1>
|
||||||
<Button onClick={() => navigate('/databook/novo')}>
|
<Button onClick={() => navigate('/databook/novo')} className="shadow-lg shadow-primary/20">
|
||||||
Novo Databook
|
Novo Databook
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats Cards */}
|
{/* Stats Cards */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
{stats.map((stat) => (
|
{stats.map((stat, i) => (
|
||||||
<div key={stat.name} className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
|
<motion.div
|
||||||
|
key={stat.name}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: i * 0.1 }}
|
||||||
|
className="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-100 dark:border-gray-700 p-6 hover:shadow-md transition-shadow"
|
||||||
|
>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-gray-600 dark:text-gray-400">{stat.name}</p>
|
<p className="text-sm font-medium text-gray-500 dark:text-gray-400">{stat.name}</p>
|
||||||
<p className="text-3xl font-bold text-gray-900 dark:text-gray-100 mt-2">{stat.value}</p>
|
<p className="text-3xl font-bold text-gray-900 dark:text-gray-100 mt-2">{stat.value}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={`${stat.color} p-3 rounded-lg`}>
|
<div className={`${stat.color} p-3 rounded-xl shadow-inner`}>
|
||||||
<stat.icon className="text-white" size={24} />
|
<stat.icon className="text-white" size={24} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Recent Projects */}
|
{/* Recent Projects */}
|
||||||
<div className="bg-white dark:bg-gray-800 rounded-lg shadow">
|
<motion.div
|
||||||
<div className="p-6 border-b border-gray-200 dark:border-gray-700">
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ delay: 0.4 }}
|
||||||
|
className="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-100 dark:border-gray-700 overflow-hidden"
|
||||||
|
>
|
||||||
|
<div className="p-6 border-b border-gray-100 dark:border-gray-700">
|
||||||
<h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100">Projetos Recentes</h2>
|
<h2 className="text-xl font-semibold text-gray-900 dark:text-gray-100">Projetos Recentes</h2>
|
||||||
</div>
|
</div>
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto">
|
||||||
<table className="w-full">
|
<table className="w-full">
|
||||||
<thead className="bg-gray-50 dark:bg-gray-900">
|
<thead className="bg-gray-50/50 dark:bg-gray-900/50">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
<th className="px-6 py-4 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Projeto</th>
|
||||||
Projeto
|
<th className="px-6 py-4 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Cliente</th>
|
||||||
</th>
|
<th className="px-6 py-4 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Status</th>
|
||||||
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
<th className="px-6 py-4 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Progresso</th>
|
||||||
Cliente
|
<th className="px-6 py-4 text-left text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">Ações</th>
|
||||||
</th>
|
|
||||||
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
|
||||||
Status
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
|
||||||
Progresso
|
|
||||||
</th>
|
|
||||||
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
|
|
||||||
Ações
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
|
<tbody className="divide-y divide-gray-100 dark:divide-gray-700">
|
||||||
{projetos && projetos.length > 0 ? (
|
<AnimatePresence>
|
||||||
projetos.map((projeto) => (
|
{projetos && projetos.length > 0 ? (
|
||||||
<tr key={projeto.id} className="hover:bg-gray-50 dark:hover:bg-gray-700">
|
projetos.map((projeto: any, i) => (
|
||||||
<td className="px-6 py-4 whitespace-nowrap">
|
<motion.tr
|
||||||
<div className="text-sm font-medium text-gray-900 dark:text-gray-100">{projeto.nome_projeto}</div>
|
key={projeto.id}
|
||||||
<div className="text-sm text-gray-500 dark:text-gray-400">{projeto.numero_projeto}</div>
|
initial={{ opacity: 0, x: -10 }}
|
||||||
</td>
|
animate={{ opacity: 1, x: 0 }}
|
||||||
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900 dark:text-gray-100">
|
transition={{ delay: 0.5 + (i * 0.05) }}
|
||||||
{projeto.clientes?.nome || '-'}
|
className="hover:bg-gray-50/50 dark:hover:bg-gray-700/50 transition-colors"
|
||||||
</td>
|
>
|
||||||
<td className="px-6 py-4 whitespace-nowrap">
|
<td className="px-6 py-4 whitespace-nowrap">
|
||||||
<span className={`px-2 py-1 text-xs font-medium rounded-full ${getStatusColor(projeto.status)}`}>
|
<div className="text-sm font-semibold text-gray-900 dark:text-gray-100">{projeto.nome_projeto}</div>
|
||||||
{getStatusLabel(projeto.status)}
|
<div className="text-xs text-gray-500 dark:text-gray-400 font-mono mt-0.5">{projeto.numero_projeto}</div>
|
||||||
</span>
|
</td>
|
||||||
</td>
|
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300">
|
||||||
<td className="px-6 py-4 whitespace-nowrap">
|
{projeto.clientes?.nome || '-'}
|
||||||
<div className="flex items-center">
|
</td>
|
||||||
<div className="w-full bg-gray-200 rounded-full h-2 mr-2">
|
<td className="px-6 py-4 whitespace-nowrap">
|
||||||
<div
|
<span className={`px-2.5 py-1 text-xs font-bold rounded-full uppercase tracking-wider ${getStatusColor(projeto.status)}`}>
|
||||||
className="bg-primary h-2 rounded-full"
|
{getStatusLabel(projeto.status)}
|
||||||
style={{ width: `${projeto.progresso_percentual}%` }}
|
</span>
|
||||||
></div>
|
</td>
|
||||||
|
<td className="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="flex-1 bg-gray-100 dark:bg-gray-700 rounded-full h-2 min-w-[100px]">
|
||||||
|
<motion.div
|
||||||
|
initial={{ width: 0 }}
|
||||||
|
animate={{ width: `${projeto.progresso_percentual || 0}%` }}
|
||||||
|
className="bg-primary-600 h-full rounded-full shadow-sm"
|
||||||
|
></motion.div>
|
||||||
|
</div>
|
||||||
|
<span className="text-xs font-bold text-gray-600 dark:text-gray-400">{projeto.progresso_percentual || 0}%</span>
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm text-gray-600 dark:text-gray-300">{projeto.progresso_percentual}%</span>
|
</td>
|
||||||
</div>
|
<td className="px-6 py-4 whitespace-nowrap text-sm">
|
||||||
</td>
|
<div className="flex items-center gap-1">
|
||||||
<td className="px-6 py-4 whitespace-nowrap text-sm">
|
{[
|
||||||
<div className="flex items-center gap-2">
|
{ icon: FileText, color: 'text-gray-600 hover:text-blue-600', onClick: () => navigate(`/databook/${projeto.id}`), title: 'Ver detalhes' },
|
||||||
<button
|
{ icon: Edit, color: 'text-gray-600 hover:text-blue-600', onClick: () => handleEdit(projeto), title: 'Editar' },
|
||||||
onClick={() => navigate(`/databook/${projeto.id}`)}
|
{ icon: Copy, color: 'text-gray-600 hover:text-emerald-600', onClick: () => handleClone(projeto), title: 'Clonar' },
|
||||||
className="text-blue-600 hover:text-blue-800 p-1 hover:bg-blue-50 rounded transition-colors"
|
{ icon: Trash2, color: 'text-gray-600 hover:text-red-600', onClick: () => handleDelete(projeto), title: 'Deletar' },
|
||||||
title="Ver detalhes"
|
].map((action, actionIdx) => (
|
||||||
>
|
<button
|
||||||
<FileText size={18} />
|
key={actionIdx}
|
||||||
</button>
|
onClick={action.onClick}
|
||||||
<button
|
className={`${action.color} p-2 hover:bg-white dark:hover:bg-gray-600 rounded-lg transition-all border border-transparent hover:border-gray-200 dark:hover:border-gray-500 shadow-sm hover:shadow`}
|
||||||
onClick={() => handleEdit(projeto)}
|
title={action.title}
|
||||||
className="text-blue-600 hover:text-blue-800 p-1 hover:bg-blue-50 rounded transition-colors"
|
>
|
||||||
title="Editar"
|
<action.icon size={16} />
|
||||||
>
|
</button>
|
||||||
<Edit size={18} />
|
))}
|
||||||
</button>
|
</div>
|
||||||
<button
|
</td>
|
||||||
onClick={() => handleClone(projeto)}
|
</motion.tr>
|
||||||
className="text-green-600 hover:text-green-800 p-1 hover:bg-green-50 rounded transition-colors"
|
))
|
||||||
title="Clonar"
|
) : (
|
||||||
>
|
<tr>
|
||||||
<Copy size={18} />
|
<td colSpan={5} className="px-6 py-12 text-center text-gray-500 dark:text-gray-400 italic">
|
||||||
</button>
|
Nenhum projeto encontrado. Comece criando um novo databook.
|
||||||
<button
|
|
||||||
onClick={() => handleDelete(projeto)}
|
|
||||||
className="text-red-600 hover:text-red-800 p-1 hover:bg-red-50 rounded transition-colors"
|
|
||||||
title="Deletar"
|
|
||||||
>
|
|
||||||
<Trash2 size={18} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
)}
|
||||||
) : (
|
</AnimatePresence>
|
||||||
<tr>
|
|
||||||
<td colSpan={5} className="px-6 py-12 text-center text-gray-500">
|
|
||||||
Nenhum projeto encontrado. Crie seu primeiro databook!
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Modal de Confirmação de Exclusão */}
|
{/* Modal de Confirmação de Exclusão */}
|
||||||
<Modal
|
<Modal
|
||||||
@@ -378,13 +357,15 @@ export default function Dashboard() {
|
|||||||
title="Deletar Projeto"
|
title="Deletar Projeto"
|
||||||
>
|
>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<p className="text-gray-600">
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
Tem certeza que deseja deletar o projeto <strong>{projetoToDelete?.nome_projeto}</strong>?
|
Tem certeza que deseja deletar o projeto <strong>{projetoToDelete?.nome_projeto}</strong>?
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-gray-500">
|
<div className="bg-red-50 dark:bg-red-900/20 p-3 rounded-lg border border-red-100 dark:border-red-900/30">
|
||||||
Esta ação não pode ser desfeita e todos os dados relacionados serão perdidos.
|
<p className="text-sm text-red-700 dark:text-red-400 font-medium">
|
||||||
</p>
|
Esta ação não pode ser desfeita e todos os dados relacionados serão perdidos permanentemente.
|
||||||
<div className="flex justify-end gap-3">
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end gap-3 pt-4">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={() => setDeleteModalOpen(false)}
|
onClick={() => setDeleteModalOpen(false)}
|
||||||
@@ -392,12 +373,12 @@ export default function Dashboard() {
|
|||||||
Cancelar
|
Cancelar
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="danger"
|
||||||
onClick={confirmDelete}
|
onClick={confirmDelete}
|
||||||
isLoading={deleteMutation.isPending}
|
isLoading={deleteMutation.isPending}
|
||||||
className="bg-red-600 hover:bg-red-700"
|
className="px-8 shadow-lg shadow-red-500/20"
|
||||||
>
|
>
|
||||||
Deletar
|
Sim, Deletar
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -405,4 +386,3 @@ export default function Dashboard() {
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user