Refactor AttendanceWebcamModal and LeaveRequestFormModal to streamline code and improve form handling. Update video and image display elements for consistency, and implement useFormDialog for better form management in LeaveRequestFormModal.

This commit is contained in:
Yoga Pangestu 2026-06-12 16:41:22 +07:00
parent e871da4c5f
commit 586ed448c7
2 changed files with 20 additions and 46 deletions

View File

@ -130,6 +130,7 @@ watch(open, async (isOpen) => {
resetState(); resetState();
await nextTick(); await nextTick();
await initializeCamera(); await initializeCamera();
return; return;
} }
@ -157,19 +158,11 @@ onBeforeUnmount(() => {
<p class="text-sm font-medium"> <p class="text-sm font-medium">
Kamera Kamera
</p> </p>
<div class="relative aspect-[4/3] overflow-hidden rounded-lg border bg-muted"> <div class="relative aspect-4/3 overflow-hidden rounded-lg border bg-muted">
<video <video ref="videoRef" class="size-full scale-x-[-1] object-cover" autoplay muted playsinline />
ref="videoRef"
class="size-full scale-x-[-1] object-cover"
autoplay
muted
playsinline
/>
<div <div v-if="cameraLoading"
v-if="cameraLoading" class="absolute inset-0 flex items-center justify-center bg-background/80">
class="absolute inset-0 flex items-center justify-center bg-background/80"
>
<Loader2 class="text-muted-foreground size-8 animate-spin" /> <Loader2 class="text-muted-foreground size-8 animate-spin" />
</div> </div>
</div> </div>
@ -179,12 +172,8 @@ onBeforeUnmount(() => {
<p class="text-sm font-medium"> <p class="text-sm font-medium">
Hasil Foto Hasil Foto
</p> </p>
<div class="relative aspect-[4/3] overflow-hidden rounded-lg border bg-muted"> <div class="relative aspect-4/3 overflow-hidden rounded-lg border bg-muted">
<img <img :src="previewPhoto" alt="Hasil foto presensi" class="size-full object-cover" />
:src="previewPhoto"
alt="Hasil foto presensi"
class="size-full object-cover"
/>
</div> </div>
<p class="text-muted-foreground text-xs whitespace-pre-line"> <p class="text-muted-foreground text-xs whitespace-pre-line">
@ -198,23 +187,13 @@ onBeforeUnmount(() => {
Ambil Ulang Ambil Ulang
</Button> </Button>
<Button <Button v-if="!previewPhoto" type="button" :disabled="!cameraReady || capturing" @click="capturePhoto">
v-if="!previewPhoto"
type="button"
:disabled="!cameraReady || capturing"
@click="capturePhoto"
>
<Loader2 v-if="capturing" class="size-4 animate-spin" /> <Loader2 v-if="capturing" class="size-4 animate-spin" />
<Camera v-else class="size-4" /> <Camera v-else class="size-4" />
Ambil Foto Ambil Foto
</Button> </Button>
<Button <Button v-else type="button" :disabled="form.processing" @click="submitAttendance">
v-else
type="button"
:disabled="form.processing"
@click="submitAttendance"
>
<Loader2 v-if="form.processing" class="size-4 animate-spin" /> <Loader2 v-if="form.processing" class="size-4 animate-spin" />
{{ submitLabel }} {{ submitLabel }}
</Button> </Button>

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useForm } from '@inertiajs/vue3'; import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { computed, watch } from 'vue'; import { computed } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { DatePicker } from '@/components/ui/date-picker'; import { DatePicker } from '@/components/ui/date-picker';
@ -19,6 +19,7 @@ import {
FieldLabel, FieldLabel,
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { useFormDialog } from '@/composables/useFormDialog';
import { formErrors } from '@/lib/form'; import { formErrors } from '@/lib/form';
import type { LeaveRequestFormData, LeaveRequestListItem } from '@/types/leave-request'; import type { LeaveRequestFormData, LeaveRequestListItem } from '@/types/leave-request';
@ -51,19 +52,11 @@ function populateForm(leaveRequest: LeaveRequestListItem | null | undefined) {
form.end_date = leaveRequest.end_date_input; form.end_date = leaveRequest.end_date_input;
} }
watch( useFormDialog({
() => props.leaveRequest, open,
(leaveRequest) => { source: () => props.leaveRequest,
populateForm(leaveRequest); populate: populateForm,
}, reset: resetForm,
);
watch(open, (isOpen) => {
if (isOpen) {
populateForm(props.leaveRequest);
} else {
resetForm();
}
}); });
function submit() { function submit() {
@ -79,9 +72,11 @@ function submit() {
if (isEditing.value && props.leaveRequest) { if (isEditing.value && props.leaveRequest) {
form.put(`/admin/hr/leave-requests/${props.leaveRequest.id}`, options); form.put(`/admin/hr/leave-requests/${props.leaveRequest.id}`, options);
} else {
form.post('/admin/hr/leave-requests', options); return;
} }
form.post('/admin/hr/leave-requests', options);
} }
</script> </script>