fix: exibir a nova senha SIP ao redefinir senha de ramal
O endpoint POST /extensions/:id/reset-password já retornava a senha em texto puro (mesmo padrão da criação), mas o frontend descartava o resultado e só mostrava um toast genérico — o usuário nunca via a senha nova, precisando adivinhar ou reconfigurar de novo. Reaproveita o mesmo padrão de diálogo 'copie agora' já usado na criação do ramal.
This commit is contained in:
@@ -152,6 +152,42 @@ function ExtensionFormDialog({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ResetPasswordDialog({
|
||||||
|
result,
|
||||||
|
onOpenChange,
|
||||||
|
}: {
|
||||||
|
result: { number: string; password: string } | null;
|
||||||
|
onOpenChange: (v: boolean) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Dialog open={result !== null} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Senha SIP redefinida — ramal {result?.number}</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Exibida apenas uma vez, copie agora:
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-2 rounded-md border border-border bg-muted p-2 font-mono text-sm">
|
||||||
|
<span className="flex-1 break-all">{result?.password}</span>
|
||||||
|
<Button
|
||||||
|
size="icon"
|
||||||
|
variant="ghost"
|
||||||
|
onClick={() => result && navigator.clipboard.writeText(result.password)}
|
||||||
|
>
|
||||||
|
<Copy className="size-4" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button onClick={() => onOpenChange(false)}>Fechar</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function ExtensionsContent() {
|
function ExtensionsContent() {
|
||||||
const { can } = useAuth();
|
const { can } = useAuth();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
@@ -160,6 +196,9 @@ function ExtensionsContent() {
|
|||||||
const debouncedSearch = useDebounce(search);
|
const debouncedSearch = useDebounce(search);
|
||||||
const [dialogOpen, setDialogOpen] = React.useState(false);
|
const [dialogOpen, setDialogOpen] = React.useState(false);
|
||||||
const [editing, setEditing] = React.useState<Extension | null>(null);
|
const [editing, setEditing] = React.useState<Extension | null>(null);
|
||||||
|
const [resetResult, setResetResult] = React.useState<{ number: string; password: string } | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
const { data, isLoading, isError, refetch } = useQuery({
|
const { data, isLoading, isError, refetch } = useQuery({
|
||||||
queryKey: ['extensions'],
|
queryKey: ['extensions'],
|
||||||
@@ -168,9 +207,9 @@ function ExtensionsContent() {
|
|||||||
|
|
||||||
const resetPassword = useMutation({
|
const resetPassword = useMutation({
|
||||||
mutationFn: (id: string) => extensionsService.resetPassword(id),
|
mutationFn: (id: string) => extensionsService.resetPassword(id),
|
||||||
onSuccess: () => {
|
onSuccess: (result) => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['extensions'] });
|
queryClient.invalidateQueries({ queryKey: ['extensions'] });
|
||||||
toast({ title: 'Senha SIP redefinida', variant: 'success' });
|
setResetResult({ number: result.number, password: result.sipPassword });
|
||||||
},
|
},
|
||||||
onError: (err) => toast({ title: 'Erro', description: errorMessage(err), variant: 'destructive' }),
|
onError: (err) => toast({ title: 'Erro', description: errorMessage(err), variant: 'destructive' }),
|
||||||
});
|
});
|
||||||
@@ -283,6 +322,10 @@ function ExtensionsContent() {
|
|||||||
emptyMessage="Nenhum ramal cadastrado."
|
emptyMessage="Nenhum ramal cadastrado."
|
||||||
/>
|
/>
|
||||||
<ExtensionFormDialog open={dialogOpen} onOpenChange={setDialogOpen} extension={editing} />
|
<ExtensionFormDialog open={dialogOpen} onOpenChange={setDialogOpen} extension={editing} />
|
||||||
|
<ResetPasswordDialog
|
||||||
|
result={resetResult}
|
||||||
|
onOpenChange={(v) => !v && setResetResult(null)}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,6 @@ export const extensionsService = {
|
|||||||
update: (id: string, input: Partial<ExtensionInput>) =>
|
update: (id: string, input: Partial<ExtensionInput>) =>
|
||||||
api.patch<Extension>(`/extensions/${id}`, input),
|
api.patch<Extension>(`/extensions/${id}`, input),
|
||||||
resetPassword: (id: string) =>
|
resetPassword: (id: string) =>
|
||||||
api.post<Extension>(`/extensions/${id}/reset-password`),
|
api.post<Extension & { sipPassword: string }>(`/extensions/${id}/reset-password`),
|
||||||
remove: (id: string) => api.delete<void>(`/extensions/${id}`),
|
remove: (id: string) => api.delete<void>(`/extensions/${id}`),
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user