114 lines
4.9 KiB
TypeScript
114 lines
4.9 KiB
TypeScript
import SecurityController from '@/actions/App/Http/Controllers/Settings/SecurityController';
|
|
import PasswordInput from '@/components/password-input';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Field, FieldError } from "@/components/ui/field";
|
|
import { Label } from '@/components/ui/label';
|
|
import { edit } from '@/routes/security';
|
|
import { Head, useForm } from '@inertiajs/react';
|
|
import { Loader, Save } from 'lucide-react';
|
|
import { useRef } from 'react';
|
|
import { toast } from 'sonner';
|
|
|
|
export default function Security() {
|
|
const passwordInput = useRef<HTMLInputElement>(null);
|
|
const currentPasswordInput = useRef<HTMLInputElement>(null);
|
|
|
|
const { data, setData, put, processing, errors, reset } = useForm({
|
|
current_password: '',
|
|
password: '',
|
|
password_confirmation: '',
|
|
});
|
|
|
|
const onSubmit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
put(SecurityController.update().url, {
|
|
preserveScroll: true,
|
|
onSuccess: () => {
|
|
toast.success('Kata sandi berhasil diperbarui.');
|
|
reset();
|
|
},
|
|
onError: (errors) => {
|
|
if (errors.password) {
|
|
passwordInput.current?.focus();
|
|
}
|
|
if (errors.current_password) {
|
|
currentPasswordInput.current?.focus();
|
|
}
|
|
},
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col gap-6">
|
|
<Head title="Keamanan Akun" />
|
|
|
|
<h1 className="sr-only">Keamanan Akun</h1>
|
|
|
|
<form onSubmit={onSubmit} className="space-y-6">
|
|
<Card className="overflow-hidden border-none shadow-lg bg-card/50 backdrop-blur-sm">
|
|
<CardHeader className="border-b">
|
|
<CardTitle>Perbarui Kata Sandi</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-6 pt-6">
|
|
<Field>
|
|
<Label htmlFor="current_password" required>Kata Sandi Saat Ini</Label>
|
|
<PasswordInput
|
|
id="current_password"
|
|
ref={currentPasswordInput}
|
|
value={data.current_password}
|
|
onChange={(e) => setData('current_password', e.target.value)}
|
|
className="w-full"
|
|
autoComplete="current-password"
|
|
placeholder="Masukkan kata sandi saat ini"
|
|
/>
|
|
<FieldError error={errors.current_password} label="Kata sandi saat ini" className="text-xs" />
|
|
</Field>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<Field>
|
|
<Label htmlFor="password" required>Kata Sandi Baru</Label>
|
|
<PasswordInput
|
|
id="password"
|
|
ref={passwordInput}
|
|
value={data.password}
|
|
onChange={(e) => setData('password', e.target.value)}
|
|
placeholder="Masukkan kata sandi baru"
|
|
autoComplete="new-password"
|
|
/>
|
|
<FieldError error={errors.password} label="Kata sandi baru" className="text-xs" />
|
|
</Field>
|
|
|
|
<Field>
|
|
<Label htmlFor="password_confirmation" required>Konfirmasi Kata Sandi Baru</Label>
|
|
<PasswordInput
|
|
id="password_confirmation"
|
|
value={data.password_confirmation}
|
|
onChange={(e) => setData('password_confirmation', e.target.value)}
|
|
placeholder="Ulangi kata sandi baru"
|
|
autoComplete="new-password"
|
|
/>
|
|
<FieldError error={errors.password_confirmation} label="Konfirmasi kata sandi baru" className="text-xs" />
|
|
</Field>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Button type="submit" disabled={processing}>
|
|
{processing ? <Loader className="size-4 animate-spin" /> : <Save className="size-4" />}
|
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
|
</Button>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
Security.layout = {
|
|
breadcrumbs: [
|
|
{
|
|
title: 'Keamanan Akun',
|
|
href: edit(),
|
|
},
|
|
],
|
|
};
|