feat: add loading animation to tenant creation button
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m10s
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m10s
- Implemented isSaving state in SuperAdmin to provide visual feedback during organization creation and updates.
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
import React, { useState, useMemo } from 'react';
|
import React, { useState, useMemo } from 'react';
|
||||||
import {
|
import {
|
||||||
Building2, Users, MessageSquare, Plus, Search,
|
Building2, Users, MessageSquare, Plus, Search,
|
||||||
Edit, Trash2, ChevronDown, ChevronUp, ChevronsUpDown, X, CheckCircle2
|
Edit, Trash2, ChevronDown, ChevronUp, ChevronsUpDown, X, CheckCircle2, Loader2
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';import { getTenants, createTenant, deleteTenant, updateTenant } from '../services/dataService';
|
||||||
import { getTenants, createTenant, deleteTenant, updateTenant } from '../services/dataService';
|
|
||||||
import { Tenant } from '../types';
|
import { Tenant } from '../types';
|
||||||
import { DateRangePicker } from '../components/DateRangePicker';
|
import { DateRangePicker } from '../components/DateRangePicker';
|
||||||
import { KPICard } from '../components/KPICard';
|
import { KPICard } from '../components/KPICard';
|
||||||
@@ -93,17 +92,20 @@ export const SuperAdmin: React.FC = () => {
|
|||||||
|
|
||||||
const [successMessage, setSuccessMessage] = useState('');
|
const [successMessage, setSuccessMessage] = useState('');
|
||||||
const [errorMessage, setErrorMessage] = useState('');
|
const [errorMessage, setErrorMessage] = useState('');
|
||||||
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
|
||||||
const handleSaveTenant = async (e: React.FormEvent) => {
|
const handleSaveTenant = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setErrorMessage('');
|
setErrorMessage('');
|
||||||
setSuccessMessage('');
|
setSuccessMessage('');
|
||||||
|
setIsSaving(true);
|
||||||
const form = e.target as HTMLFormElement;
|
const form = e.target as HTMLFormElement;
|
||||||
const name = (form.elements.namedItem('name') as HTMLInputElement).value;
|
const name = (form.elements.namedItem('name') as HTMLInputElement).value;
|
||||||
const slug = (form.elements.namedItem('slug') as HTMLInputElement).value;
|
const slug = (form.elements.namedItem('slug') as HTMLInputElement).value;
|
||||||
const admin_email = (form.elements.namedItem('admin_email') as HTMLInputElement).value;
|
const admin_email = (form.elements.namedItem('admin_email') as HTMLInputElement).value;
|
||||||
const status = (form.elements.namedItem('status') as HTMLSelectElement).value;
|
const status = (form.elements.namedItem('status') as HTMLSelectElement).value;
|
||||||
|
|
||||||
|
try {
|
||||||
if (editingTenant) {
|
if (editingTenant) {
|
||||||
const success = await updateTenant(editingTenant.id, { name, slug, admin_email, status });
|
const success = await updateTenant(editingTenant.id, { name, slug, admin_email, status });
|
||||||
if (success) {
|
if (success) {
|
||||||
@@ -113,9 +115,11 @@ export const SuperAdmin: React.FC = () => {
|
|||||||
setIsModalOpen(false);
|
setIsModalOpen(false);
|
||||||
setSuccessMessage('');
|
setSuccessMessage('');
|
||||||
setEditingTenant(null);
|
setEditingTenant(null);
|
||||||
|
setIsSaving(false);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
} else {
|
} else {
|
||||||
setErrorMessage('Erro ao atualizar organização.');
|
setErrorMessage('Erro ao atualizar organização.');
|
||||||
|
setIsSaving(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const result = await createTenant({ name, slug, admin_email, status });
|
const result = await createTenant({ name, slug, admin_email, status });
|
||||||
@@ -125,11 +129,17 @@ export const SuperAdmin: React.FC = () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsModalOpen(false);
|
setIsModalOpen(false);
|
||||||
setSuccessMessage('');
|
setSuccessMessage('');
|
||||||
|
setIsSaving(false);
|
||||||
}, 3000);
|
}, 3000);
|
||||||
} else {
|
} else {
|
||||||
setErrorMessage(result.message || 'Erro ao salvar organização.');
|
setErrorMessage(result.message || 'Erro ao salvar organização.');
|
||||||
|
setIsSaving(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setErrorMessage('Ocorreu um erro inesperado.');
|
||||||
|
setIsSaving(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const SortIcon = ({ column }: { column: keyof Tenant }) => {
|
const SortIcon = ({ column }: { column: keyof Tenant }) => {
|
||||||
@@ -282,7 +292,9 @@ export const SuperAdmin: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="pt-4 flex justify-end gap-3 border-t dark:border-dark-border mt-6">
|
<div className="pt-4 flex justify-end gap-3 border-t dark:border-dark-border mt-6">
|
||||||
<button type="button" onClick={() => setIsModalOpen(false)} className="px-4 py-2 text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-dark-border rounded-lg text-sm font-medium transition-colors">Cancelar</button>
|
<button type="button" onClick={() => setIsModalOpen(false)} className="px-4 py-2 text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-dark-border rounded-lg text-sm font-medium transition-colors">Cancelar</button>
|
||||||
<button type="submit" className="px-4 py-2 bg-zinc-900 dark:bg-brand-yellow text-white dark:text-zinc-950 rounded-lg text-sm font-bold hover:opacity-90 transition-all shadow-sm">{editingTenant ? 'Salvar Alterações' : 'Criar Organização'}</button>
|
<button type="submit" disabled={isSaving} className="px-4 py-2 bg-zinc-900 dark:bg-brand-yellow text-white dark:text-zinc-950 rounded-lg text-sm font-bold flex items-center gap-2 hover:opacity-90 transition-all shadow-sm disabled:opacity-70">
|
||||||
|
{isSaving ? <Loader2 className="animate-spin" size={16} /> : (editingTenant ? 'Salvar Alterações' : 'Criar Organização')}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user