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:
parent
e871da4c5f
commit
586ed448c7
@ -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>
|
||||||
|
|||||||
@ -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>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user