refactor: migrate password fields to use InputGroup component for password visibility toggling

This commit is contained in:
Yoga Pangestu 2026-06-14 02:00:05 +07:00
parent 9365797f89
commit f0cc242c7e
2 changed files with 78 additions and 23 deletions

View File

@ -13,6 +13,7 @@ import {
FieldLabel,
} from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { InputGroup, InputGroupInput, InputGroupAddon, InputGroupButton } from '@/components/ui/input-group';
import { formErrors } from '@/lib/form';
import { cn } from '@/lib/utils';
import FieldSeparator from './ui/field/FieldSeparator.vue';
@ -75,27 +76,25 @@ function submit() {
Kata Sandi
</FieldLabel>
<div class="relative">
<Input
<InputGroup>
<InputGroupInput
id="password"
v-model="form.password"
:type="showPassword ? 'text' : 'password'"
placeholder="********"
required
class="pr-10"
/>
<Button
variant="ghost"
size="icon"
type="button"
@click="showPassword = !showPassword"
class="absolute inset-y-0 right-0"
>
<Eye v-if="!showPassword" class="h-5 w-5" />
<EyeOff v-else class="h-5 w-5" />
</Button>
</div>
<InputGroupAddon align="inline-end">
<InputGroupButton
type="button"
size="icon-xs"
@click="showPassword = !showPassword"
>
<Eye v-if="!showPassword" class="h-4 w-4" />
<EyeOff v-else class="h-4 w-4" />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<FieldError
:errors="formErrors(form, 'password')"

View File

@ -1,6 +1,7 @@
<script setup lang="ts">
import { Head, useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue';
import { Save, Eye, EyeOff } from '@lucide/vue';
import { ref } from 'vue';
import { toast } from 'vue-sonner';
import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
@ -11,7 +12,7 @@ import {
FieldLabel,
FieldSet,
} from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { InputGroup, InputGroupInput, InputGroupAddon, InputGroupButton } from '@/components/ui/input-group';
import AccountLayout from '@/layouts/AccountLayout.vue';
import { formErrors } from '@/lib/form';
import type { PasswordFormData } from '@/types/account';
@ -22,6 +23,10 @@ const form = useForm<PasswordFormData>({
password_confirmation: '',
});
const showCurrentPassword = ref(false);
const showPassword = ref(false);
const showPasswordConfirmation = ref(false);
function submit() {
form.put('/admin/account/password', {
onSuccess: () => {
@ -49,8 +54,25 @@ function submit() {
<FieldLabel for="current_password" required>
Kata Sandi Saat Ini
</FieldLabel>
<Input id="current_password" v-model="form.current_password" type="password"
placeholder="********" autocomplete="current-password" />
<InputGroup>
<InputGroupInput
id="current_password"
v-model="form.current_password"
:type="showCurrentPassword ? 'text' : 'password'"
placeholder="********"
autocomplete="current-password"
/>
<InputGroupAddon align="inline-end">
<InputGroupButton
type="button"
size="icon-xs"
@click="showCurrentPassword = !showCurrentPassword"
>
<Eye v-if="!showCurrentPassword" class="h-4 w-4" />
<EyeOff v-else class="h-4 w-4" />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<FieldError :errors="formErrors(form, 'current_password')" />
</Field>
@ -58,8 +80,25 @@ function submit() {
<FieldLabel for="password" required>
Kata Sandi Baru
</FieldLabel>
<Input id="password" v-model="form.password" type="password" placeholder="********"
autocomplete="new-password" />
<InputGroup>
<InputGroupInput
id="password"
v-model="form.password"
:type="showPassword ? 'text' : 'password'"
placeholder="********"
autocomplete="new-password"
/>
<InputGroupAddon align="inline-end">
<InputGroupButton
type="button"
size="icon-xs"
@click="showPassword = !showPassword"
>
<Eye v-if="!showPassword" class="h-4 w-4" />
<EyeOff v-else class="h-4 w-4" />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<FieldError :errors="formErrors(form, 'password')" />
</Field>
@ -67,8 +106,25 @@ function submit() {
<FieldLabel for="password_confirmation" required>
Konfirmasi Kata Sandi Baru
</FieldLabel>
<Input id="password_confirmation" v-model="form.password_confirmation"
type="password" placeholder="********" autocomplete="new-password" />
<InputGroup>
<InputGroupInput
id="password_confirmation"
v-model="form.password_confirmation"
:type="showPasswordConfirmation ? 'text' : 'password'"
placeholder="********"
autocomplete="new-password"
/>
<InputGroupAddon align="inline-end">
<InputGroupButton
type="button"
size="icon-xs"
@click="showPasswordConfirmation = !showPasswordConfirmation"
>
<Eye v-if="!showPasswordConfirmation" class="h-4 w-4" />
<EyeOff v-else class="h-4 w-4" />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<FieldError :errors="formErrors(form, 'password_confirmation')" />
</Field>
</FieldGroup>