refactor: reorder component imports and optimize code structure across UI forms and composables

This commit is contained in:
Yoga Pangestu 2026-06-14 01:26:00 +07:00
parent c22252f44c
commit 8609c68a6d
39 changed files with 193 additions and 111 deletions

View File

@ -1,38 +1,43 @@
<script setup lang="ts"> <script setup lang="ts">
import { useForm } from '@inertiajs/vue3' import { Button } from '@/components/ui/button';
import type { HTMLAttributes } from "vue" import { Card, CardContent } from '@/components/ui/card';
import { toast } from 'vue-sonner'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import { import {
Field, FieldError, Field,
FieldError,
FieldGroup, FieldGroup,
FieldLabel FieldLabel,
} from '@/components/ui/field' } from '@/components/ui/field';
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input';
import { formErrors } from '@/lib/form' import { formErrors } from '@/lib/form';
import { cn } from "@/lib/utils" import { cn } from '@/lib/utils';
import FieldSeparator from './ui/field/FieldSeparator.vue' import { useForm } from '@inertiajs/vue3';
import { Eye, EyeOff } from '@lucide/vue';
import { ref, type HTMLAttributes } from 'vue';
import { toast } from 'vue-sonner';
import FieldSeparator from './ui/field/FieldSeparator.vue';
const props = defineProps<{ const props = defineProps<{
class?: HTMLAttributes["class"] class?: HTMLAttributes['class'];
}>() }>();
const showPassword = ref(false);
const form = useForm({ const form = useForm({
login: '', login: '',
password: '', password: '',
}) });
function submit() { function submit() {
form.post('/auth/login', { form.post('/auth/login', {
onError: (errors) => { onError: (errors) => {
const message = errors.login const message =
?? errors.password errors.login ??
?? 'Gagal masuk. Periksa kembali data Anda.'; errors.password ??
'Gagal masuk. Periksa kembali data Anda.';
toast.error(message); toast.error(message);
}, },
}) });
} }
</script> </script>
@ -42,33 +47,58 @@ function submit() {
<CardContent class="grid p-0 md:grid-cols-2"> <CardContent class="grid p-0 md:grid-cols-2">
<form class="p-6 md:p-8" @submit.prevent="submit"> <form class="p-6 md:p-8" @submit.prevent="submit">
<FieldGroup> <FieldGroup>
<div class="flex flex-col items-center gap-2 text-center"> <div
<h1 class="text-2xl font-bold"> class="flex flex-col items-center gap-2 text-center"
Selamat Datang >
</h1> <h1 class="text-2xl font-bold">Selamat Datang</h1>
<p class="text-muted-foreground text-balance"> <p class="text-balance text-muted-foreground">
Silakan masukkan email dan username untuk akses dasbor. Silakan masukkan email dan username untuk akses
dasbor.
</p> </p>
</div> </div>
<Field> <Field>
<FieldLabel for="login" required> <FieldLabel for="login" required>
Email/Username Email/Username
</FieldLabel> </FieldLabel>
<Input id="login" v-model="form.login" type="text" placeholder="m@example.com" required /> <Input
id="login"
v-model="form.login"
type="text"
placeholder="m@example.com"
required
/>
<FieldError :errors="formErrors(form, 'login')" /> <FieldError :errors="formErrors(form, 'login')" />
</Field> </Field>
<Field> <Field>
<div class="flex items-center"> <FieldLabel for="password" required>
<FieldLabel for="password" required> Kata Sandi
Kata Sandi </FieldLabel>
</FieldLabel>
<a href="#" class="ml-auto text-sm underline-offset-2 hover:underline"> <div class="relative">
Lupa kata sandi? <Input
</a> 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> </div>
<Input id="password" v-model="form.password" type="password" placeholder="********"
required /> <FieldError
<FieldError :errors="formErrors(form, 'password')" /> :errors="formErrors(form, 'password')"
/>
</Field> </Field>
<Field> <Field>
<Button type="submit" :disabled="form.processing"> <Button type="submit" :disabled="form.processing">
@ -76,24 +106,33 @@ function submit() {
</Button> </Button>
</Field> </Field>
<FieldSeparator class="*:data-[slot=field-separator-content]:bg-card"> <FieldSeparator
class="*:data-[slot=field-separator-content]:bg-card"
>
Atau lanjutkan dengan Atau lanjutkan dengan
</FieldSeparator> </FieldSeparator>
<Field class="grid gap-4"> <Field class="grid gap-4">
<Button variant="outline" type="button"> <Button variant="outline" type="button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<path <path
d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z"
fill="currentColor" /> fill="currentColor"
/>
</svg> </svg>
<span>Google</span> <span>Google</span>
</Button> </Button>
</Field> </Field>
</FieldGroup> </FieldGroup>
</form> </form>
<div class="bg-muted relative hidden md:block"> <div class="relative hidden bg-muted md:block">
<img src="https://images.pexels.com/photos/37080685/pexels-photo-37080685.jpeg" alt="Image" <img
class="absolute inset-0 h-full w-full object-cover"> src="https://images.pexels.com/photos/37080685/pexels-photo-37080685.jpeg"
alt="Image"
class="absolute inset-0 h-full w-full object-cover"
/>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>

View File

@ -3,6 +3,8 @@ import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import ImageUploadField from '@/components/form/image-upload-field/ImageUploadField.vue';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {
Dialog, Dialog,
@ -18,8 +20,6 @@ import {
FieldLabel, FieldLabel,
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import ImageUploadField from '@/components/form/image-upload-field/ImageUploadField.vue';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { useFormDialog } from '@/composables/useFormDialog'; import { useFormDialog } from '@/composables/useFormDialog';
import { FIELD_LIMITS } from '@/lib/field-limits'; import { FIELD_LIMITS } from '@/lib/field-limits';

View File

@ -1,8 +1,8 @@
import type { ColumnDef } from '@tanstack/vue-table'; import type { ColumnDef } from '@tanstack/vue-table';
import { h } from 'vue'; import { h } from 'vue';
import DataTableActions from '@/components/admin/finance/cash/data-table-actions.vue'; import DataTableActions from '@/components/admin/finance/cash/data-table-actions.vue';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { DataTableColumnHeader } from '@/components/data-table'; import { DataTableColumnHeader } from '@/components/data-table';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import type { CashTransactionListItem } from '@/types/cash'; import type { CashTransactionListItem } from '@/types/cash';

View File

@ -3,6 +3,8 @@ import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import ImageUploadField from '@/components/form/image-upload-field/ImageUploadField.vue';
import { RupiahInput } from '@/components/form/rupiah-input';
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';
import { import {
@ -19,8 +21,6 @@ import {
FieldLabel, FieldLabel,
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import ImageUploadField from '@/components/form/image-upload-field/ImageUploadField.vue';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { useFormDialog } from '@/composables/useFormDialog'; import { useFormDialog } from '@/composables/useFormDialog';
import { FIELD_LIMITS } from '@/lib/field-limits'; import { FIELD_LIMITS } from '@/lib/field-limits';

View File

@ -1,8 +1,8 @@
import type { ColumnDef } from '@tanstack/vue-table'; import type { ColumnDef } from '@tanstack/vue-table';
import { h } from 'vue'; import { h } from 'vue';
import DataTableActions from '@/components/admin/finance/employee-advances/data-table-actions.vue'; import DataTableActions from '@/components/admin/finance/employee-advances/data-table-actions.vue';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { DataTableColumnHeader } from '@/components/data-table'; import { DataTableColumnHeader } from '@/components/data-table';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import type { EmployeeAdvanceListItem } from '@/types/employee-advance'; import type { EmployeeAdvanceListItem } from '@/types/employee-advance';

View File

@ -3,6 +3,8 @@ import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { ImageUploadField } from '@/components/form/image-upload-field';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {
Dialog, Dialog,
@ -18,8 +20,6 @@ import {
FieldLabel, FieldLabel,
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { ImageUploadField } from '@/components/form/image-upload-field';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { useFormDialog } from '@/composables/useFormDialog'; import { useFormDialog } from '@/composables/useFormDialog';
import { FIELD_LIMITS } from '@/lib/field-limits'; import { FIELD_LIMITS } from '@/lib/field-limits';

View File

@ -1,8 +1,8 @@
import type { ColumnDef } from '@tanstack/vue-table'; import type { ColumnDef } from '@tanstack/vue-table';
import { h } from 'vue'; import { h } from 'vue';
import DataTableActions from '@/components/admin/finance/expenses/data-table-actions.vue'; import DataTableActions from '@/components/admin/finance/expenses/data-table-actions.vue';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { DataTableColumnHeader } from '@/components/data-table'; import { DataTableColumnHeader } from '@/components/data-table';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import type { ExpenseListItem } from '@/types/expense'; import type { ExpenseListItem } from '@/types/expense';
export function createColumns(onEdit: (expense: ExpenseListItem) => void): ColumnDef<ExpenseListItem>[] { export function createColumns(onEdit: (expense: ExpenseListItem) => void): ColumnDef<ExpenseListItem>[] {

View File

@ -3,6 +3,7 @@ import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { watch } from 'vue'; import { watch } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {
Dialog, Dialog,
@ -20,7 +21,6 @@ import {
} from '@/components/ui/field'; } from '@/components/ui/field';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { FIELD_LIMITS } from '@/lib/field-limits'; import { FIELD_LIMITS } from '@/lib/field-limits';
import { parseRupiah } from '@/lib/rupiah'; import { parseRupiah } from '@/lib/rupiah';

View File

@ -2,6 +2,8 @@
import { useForm } from '@inertiajs/vue3'; import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { DatePicker } from '@/components/ui/date-picker'; import { DatePicker } from '@/components/ui/date-picker';
@ -14,9 +16,7 @@ import {
} from '@/components/ui/field'; } from '@/components/ui/field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { RupiahInput } from '@/components/form/rupiah-input';
import { import {
Select, Select,
SelectContent, SelectContent,

View File

@ -7,7 +7,7 @@ import {
DialogTitle, DialogTitle,
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
const props = defineProps<{ defineProps<{
checkInPhotoUrl: string | null; checkInPhotoUrl: string | null;
checkOutPhotoUrl: string | null; checkOutPhotoUrl: string | null;
checkInLocationTag?: string | null; checkInLocationTag?: string | null;

View File

@ -1,8 +1,8 @@
import type { ColumnDef } from '@tanstack/vue-table'; import type { ColumnDef } from '@tanstack/vue-table';
import { h } from 'vue'; import { h } from 'vue';
import { DataTableColumnHeader } from '@/components/data-table';
import DataTableActions from '@/components/admin/hr/employees/data-table-actions.vue'; import DataTableActions from '@/components/admin/hr/employees/data-table-actions.vue';
import EmployeeStatusToggle from '@/components/admin/hr/employees/employee-status-toggle.vue'; import EmployeeStatusToggle from '@/components/admin/hr/employees/employee-status-toggle.vue';
import { DataTableColumnHeader } from '@/components/data-table';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import type { EmployeeListItem } from '@/types/employee'; import type { EmployeeListItem } from '@/types/employee';

View File

@ -19,11 +19,11 @@ import {
TableHeader, TableHeader,
TableRow, TableRow,
} from '@/components/ui/table'; } from '@/components/ui/table';
import type { CuttingListItem } from '@/types/cutting';
import type { import type {
DataTablePagination, DataTablePagination,
DataTablePaginationLink, DataTablePaginationLink,
} from '@/types/data-table'; } from '@/types/data-table';
import type { CuttingListItem } from '@/types/cutting';
const props = defineProps<{ const props = defineProps<{
cuttings: CuttingListItem[]; cuttings: CuttingListItem[];
@ -104,6 +104,7 @@ function getGroupedMaterials(materials: any[]): GroupedCuttingMaterials[] {
items: [], items: [],
}; };
} }
groups[rawMaterialId].items.push(item); groups[rawMaterialId].items.push(item);
}); });
@ -125,6 +126,7 @@ function getGroupedResults(results: any[]): GroupedCuttingResults[] {
items: [], items: [],
}; };
} }
groups[productId].items.push(item); groups[productId].items.push(item);
}); });

View File

@ -1,6 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { useForm } from '@inertiajs/vue3';
import { Minus, Plus, Save, Scissors, Search, Trash2 } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner';
import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue'; import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue';
import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue'; import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue';
import { DecimalInput } from '@/components/form/decimal-input';
import { NumberInput } from '@/components/form/number-input';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
@ -18,8 +24,6 @@ import {
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { DecimalInput } from '@/components/form/decimal-input';
import { NumberInput } from '@/components/form/number-input';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { getFirstCoverImage } from '@/lib/catalog-cover'; import { getFirstCoverImage } from '@/lib/catalog-cover';
@ -31,10 +35,6 @@ import type {
CuttingRawMaterialCatalogItem, CuttingRawMaterialCatalogItem,
CuttingResultCartItem, CuttingResultCartItem,
} from '@/types/cutting'; } from '@/types/cutting';
import { useForm } from '@inertiajs/vue3';
import { Minus, Plus, Save, Scissors, Search, Trash2 } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner';
const props = defineProps<{ const props = defineProps<{
rawMaterialCatalog: CuttingRawMaterialCatalogItem[]; rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
@ -124,9 +124,11 @@ function decreaseMaterialQty(priceId: number) {
const index = materialCart.value.findIndex( const index = materialCart.value.findIndex(
(item) => item.raw_material_price_id === priceId, (item) => item.raw_material_price_id === priceId,
); );
if (index !== -1) { if (index !== -1) {
const item = materialCart.value[index]; const item = materialCart.value[index];
const nextQty = (Number(item.material_usage) || 0) - 1; const nextQty = (Number(item.material_usage) || 0) - 1;
if (nextQty <= 0) { if (nextQty <= 0) {
removeMaterial(index); removeMaterial(index);
} else { } else {
@ -147,6 +149,7 @@ function addMaterial(
existing.material_usage = String( existing.material_usage = String(
(Number(existing.material_usage) || 0) + 1, (Number(existing.material_usage) || 0) + 1,
); );
return; return;
} }
@ -178,9 +181,11 @@ function decreaseResultQty(variantId: number) {
const index = resultCart.value.findIndex( const index = resultCart.value.findIndex(
(item) => item.product_variant_id === variantId, (item) => item.product_variant_id === variantId,
); );
if (index !== -1) { if (index !== -1) {
const item = resultCart.value[index]; const item = resultCart.value[index];
const nextQty = (Number(item.cutting_result) || 0) - 1; const nextQty = (Number(item.cutting_result) || 0) - 1;
if (nextQty <= 0) { if (nextQty <= 0) {
removeResult(index); removeResult(index);
} else { } else {
@ -210,6 +215,7 @@ function addResult(
(Number(existing.warehouse_stock) || 0) + 1, (Number(existing.warehouse_stock) || 0) + 1,
); );
syncResultTotals(existing); syncResultTotals(existing);
return; return;
} }

View File

@ -1,4 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { Link, router, useForm } from '@inertiajs/vue3';
import { Check, Pencil, RotateCcw, Scissors, Trash2, X } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner';
import ConfirmDialog from '@/components/ConfirmDialog.vue'; import ConfirmDialog from '@/components/ConfirmDialog.vue';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@ -26,10 +30,6 @@ import {
import { useCan } from '@/composables/useCan'; import { useCan } from '@/composables/useCan';
import { FIELD_LIMITS } from '@/lib/field-limits'; import { FIELD_LIMITS } from '@/lib/field-limits';
import type { CuttingListItem, CuttingStatusAction } from '@/types/cutting'; import type { CuttingListItem, CuttingStatusAction } from '@/types/cutting';
import { Link, router, useForm } from '@inertiajs/vue3';
import { Check, Pencil, RotateCcw, Scissors, Trash2, X } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner';
const props = defineProps<{ const props = defineProps<{
cutting: CuttingListItem; cutting: CuttingListItem;
@ -108,6 +108,7 @@ function statusConfirmDescription(action: CuttingStatusAction): string {
function openStatusConfirm(action: CuttingStatusAction) { function openStatusConfirm(action: CuttingStatusAction) {
if (action.status === 'verified') { if (action.status === 'verified') {
verifyDialogOpen.value = true; verifyDialogOpen.value = true;
return; return;
} }

View File

@ -5,6 +5,8 @@ import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue'; import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue';
import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue'; import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue';
import { NumberInput } from '@/components/form/number-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { import {
@ -21,8 +23,6 @@ import {
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { NumberInput } from '@/components/form/number-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import { import {
Select, Select,
SelectContent, SelectContent,
@ -185,6 +185,7 @@ function getCartItem(variantId: number): OrderCartItem | undefined {
async function decreaseVariantQty(variantId: number) { async function decreaseVariantQty(variantId: number) {
const index = cart.value.findIndex((item) => item.product_variant_id === variantId); const index = cart.value.findIndex((item) => item.product_variant_id === variantId);
if (index !== -1) { if (index !== -1) {
await adjustQuantity(index, -1); await adjustQuantity(index, -1);
} }

View File

@ -83,6 +83,7 @@ function getGroupedItems(items: any[]): GroupedPurchaseItems[] {
items: [], items: [],
}; };
} }
groups[rawMaterialId].items.push(item); groups[rawMaterialId].items.push(item);
}); });

View File

@ -5,6 +5,9 @@ import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue'; import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue';
import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue'; import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue';
import { DecimalInput } from '@/components/form/decimal-input';
import { ImageUploadField } from '@/components/form/image-upload-field';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
@ -21,10 +24,7 @@ import {
FieldLabel, FieldLabel,
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { ImageUploadField } from '@/components/form/image-upload-field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { DecimalInput } from '@/components/form/decimal-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import { import {
Select, Select,
SelectContent, SelectContent,
@ -162,6 +162,7 @@ function getCartItem(priceId: number): PurchaseCartItem | undefined {
async function decreasePriceQty(priceId: number) { async function decreasePriceQty(priceId: number) {
const index = cart.value.findIndex((item) => item.raw_material_price_id === priceId); const index = cart.value.findIndex((item) => item.raw_material_price_id === priceId);
if (index !== -1) { if (index !== -1) {
await adjustQuantity(index, -1); await adjustQuantity(index, -1);
} }

View File

@ -3,6 +3,7 @@ import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { computed } from 'vue'; import { computed } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {
Dialog, Dialog,
@ -19,7 +20,6 @@ import {
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { useFormDialog } from '@/composables/useFormDialog'; import { useFormDialog } from '@/composables/useFormDialog';
import { FIELD_LIMITS } from '@/lib/field-limits'; import { FIELD_LIMITS } from '@/lib/field-limits';

View File

@ -3,6 +3,9 @@ import { useForm } from '@inertiajs/vue3';
import { Copy, Plus, Save, Trash2 } from '@lucide/vue'; import { Copy, Plus, Save, Trash2 } from '@lucide/vue';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { MultipleImageUploadField } from '@/components/form/image-upload-field';
import { NumberInput } from '@/components/form/number-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { import {
@ -12,10 +15,7 @@ import {
FieldLabel, FieldLabel,
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { MultipleImageUploadField } from '@/components/form/image-upload-field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { NumberInput } from '@/components/form/number-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { FIELD_LIMITS } from '@/lib/field-limits'; import { FIELD_LIMITS } from '@/lib/field-limits';
import { formErrors } from '@/lib/form'; import { formErrors } from '@/lib/form';

View File

@ -3,8 +3,8 @@ import { Link } from '@inertiajs/vue3';
import { computed } from 'vue'; import { computed } from 'vue';
import DataTableActions from '@/components/admin/master/products/data-table-actions.vue'; import DataTableActions from '@/components/admin/master/products/data-table-actions.vue';
import ProductStatusToggle from '@/components/admin/master/products/product-status-toggle.vue'; import ProductStatusToggle from '@/components/admin/master/products/product-status-toggle.vue';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue'; import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {
@ -28,9 +28,10 @@ import type {
} from '@/types/data-table'; } from '@/types/data-table';
import { import {
PRICE_TYPES, PRICE_TYPES,
PRICE_TYPE_LABELS, PRICE_TYPE_LABELS
type ProductListItem,
} from '@/types/product'; } from '@/types/product';
import type {ProductListItem} from '@/types/product';
const props = defineProps<{ const props = defineProps<{
products: ProductListItem[]; products: ProductListItem[];

View File

@ -3,6 +3,9 @@ import { useForm } from '@inertiajs/vue3';
import { Copy, Plus, Save, Trash2 } from '@lucide/vue'; import { Copy, Plus, Save, Trash2 } from '@lucide/vue';
import { ref } from 'vue'; import { ref } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { DecimalInput } from '@/components/form/decimal-input';
import { MultipleImageUploadField } from '@/components/form/image-upload-field';
import { RupiahInput } from '@/components/form/rupiah-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { import {
@ -12,10 +15,7 @@ import {
FieldLabel, FieldLabel,
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { MultipleImageUploadField } from '@/components/form/image-upload-field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { DecimalInput } from '@/components/form/decimal-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import { import {
Select, Select,
SelectContent, SelectContent,

View File

@ -3,8 +3,8 @@ import { Link } from '@inertiajs/vue3';
import { computed } from 'vue'; import { computed } from 'vue';
import DataTableActions from '@/components/admin/master/raw-materials/data-table-actions.vue'; import DataTableActions from '@/components/admin/master/raw-materials/data-table-actions.vue';
import RawMaterialStatusToggle from '@/components/admin/master/raw-materials/raw-material-status-toggle.vue'; import RawMaterialStatusToggle from '@/components/admin/master/raw-materials/raw-material-status-toggle.vue';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue'; import DataTableToolbar from '@/components/data-table/DataTableToolbar.vue';
import MediaThumbnailCell from '@/components/media/MediaThumbnailCell.vue';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {

View File

@ -3,6 +3,7 @@ import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { computed } from 'vue'; import { computed } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {
Dialog, Dialog,
@ -19,7 +20,6 @@ import {
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { useFormDialog } from '@/composables/useFormDialog'; import { useFormDialog } from '@/composables/useFormDialog';
import { FIELD_LIMITS } from '@/lib/field-limits'; import { FIELD_LIMITS } from '@/lib/field-limits';

View File

@ -1,12 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue'; import { computed } from 'vue';
import { RupiahInput } from '@/components/form/rupiah-input';
import { import {
Field, Field,
FieldError, FieldError,
FieldLabel, FieldLabel,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { RupiahInput } from '@/components/form/rupiah-input';
import { import {
Select, Select,
SelectContent, SelectContent,

View File

@ -2,12 +2,12 @@
import { router, useForm } from '@inertiajs/vue3'; import { router, useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { ImageUploadField } from '@/components/form/image-upload-field';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { Field, FieldError, FieldGroup, FieldLabel, FieldSet } from '@/components/ui/field'; import { Field, FieldError, FieldGroup, FieldLabel, FieldSet } from '@/components/ui/field';
import { ImageUploadField } from '@/components/form/image-upload-field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { formErrors } from '@/lib/form'; import { formErrors } from '@/lib/form';
import type { SystemSettingsData } from '@/types/setting'; import type { SystemSettingsData } from '@/types/setting';

View File

@ -18,11 +18,17 @@ const emit = defineEmits<{
// Formats JS float string/number (e.g. 1250.75) to ID decimal string (e.g. 1250,75) // Formats JS float string/number (e.g. 1250.75) to ID decimal string (e.g. 1250,75)
function formatDecimal(value: string | number): string { function formatDecimal(value: string | number): string {
const str = String(value ?? '').trim(); const str = String(value ?? '').trim();
if (!str) return '';
if (!str) {
return '';
}
// Normalize to dot for processing // Normalize to dot for processing
const normalized = str.replace(',', '.'); const normalized = str.replace(',', '.');
if (isNaN(parseFloat(normalized))) return '';
if (isNaN(parseFloat(normalized))) {
return '';
}
// Split into integer and decimal parts // Split into integer and decimal parts
const parts = normalized.split('.'); const parts = normalized.split('.');
@ -31,8 +37,10 @@ function formatDecimal(value: string | number): string {
if (decimalPart !== undefined) { if (decimalPart !== undefined) {
decimalPart = decimalPart.slice(0, 2); decimalPart = decimalPart.slice(0, 2);
return `${integerPart},${decimalPart}`; return `${integerPart},${decimalPart}`;
} }
return integerPart; return integerPart;
} }
@ -50,6 +58,7 @@ function parseDecimal(value: string): string {
let clean = normalized.replace(/\./g, '').replace(',', '.'); let clean = normalized.replace(/\./g, '').replace(',', '.');
const parts = clean.split('.'); const parts = clean.split('.');
if (parts.length > 2) { if (parts.length > 2) {
clean = parts[0] + '.' + parts.slice(1).join(''); clean = parts[0] + '.' + parts.slice(1).join('');
} }
@ -57,6 +66,7 @@ function parseDecimal(value: string): string {
clean = clean.replace(/[^0-9.]/g, ''); clean = clean.replace(/[^0-9.]/g, '');
const cleanParts = clean.split('.'); const cleanParts = clean.split('.');
if (cleanParts[1] !== undefined) { if (cleanParts[1] !== undefined) {
clean = `${cleanParts[0]}.${cleanParts[1].slice(0, 2)}`; clean = `${cleanParts[0]}.${cleanParts[1].slice(0, 2)}`;
} }

View File

@ -18,7 +18,11 @@ const emit = defineEmits<{
function formatNumber(value: string | number): string { function formatNumber(value: string | number): string {
const str = String(value ?? '').trim(); const str = String(value ?? '').trim();
const clean = str.replace(/\D/g, ''); const clean = str.replace(/\D/g, '');
if (!clean) return '';
if (!clean) {
return '';
}
return Number(clean).toLocaleString('id-ID'); return Number(clean).toLocaleString('id-ID');
} }

View File

@ -1,6 +1,7 @@
import { router } from '@inertiajs/vue3'; import { router } from '@inertiajs/vue3';
import { useDebounceFn } from '@vueuse/core'; import { useDebounceFn } from '@vueuse/core';
import { ref, watch, type WatchSource } from 'vue'; import { ref, watch } from 'vue';
import type {WatchSource} from 'vue';
import type { DataTableQuery, DataTableSort } from '@/types/data-table'; import type { DataTableQuery, DataTableSort } from '@/types/data-table';
type UseDataTableQueryOptions = { type UseDataTableQueryOptions = {

View File

@ -8,6 +8,7 @@ export function useGeolocation() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!navigator.geolocation) { if (!navigator.geolocation) {
reject(new Error('Perangkat tidak mendukung geolokasi.')); reject(new Error('Perangkat tidak mendukung geolokasi.'));
return; return;
} }

View File

@ -7,6 +7,7 @@ function urlBase64ToUint8Array(base64String: string): Uint8Array {
.replace(/-/g, '+') .replace(/-/g, '+')
.replace(/_/g, '/'); .replace(/_/g, '/');
const rawData = atob(base64); const rawData = atob(base64);
return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0))); return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));
} }
@ -26,7 +27,9 @@ export function usePushNotification() {
.vapidPublicKey as string | undefined; .vapidPublicKey as string | undefined;
async function checkSubscriptionStatus(): Promise<void> { async function checkSubscriptionStatus(): Promise<void> {
if (!isSupported.value) return; if (!isSupported.value) {
return;
}
try { try {
const registration = await navigator.serviceWorker.ready; const registration = await navigator.serviceWorker.ready;
@ -39,10 +42,15 @@ export function usePushNotification() {
} }
async function subscribe(): Promise<void> { async function subscribe(): Promise<void> {
if (!isSupported.value || isLoading.value) return; if (!isSupported.value || isLoading.value) {
return;
}
const permission = await Notification.requestPermission(); const permission = await Notification.requestPermission();
if (permission !== 'granted') return;
if (permission !== 'granted') {
return;
}
isLoading.value = true; isLoading.value = true;
@ -85,7 +93,9 @@ export function usePushNotification() {
} }
async function unsubscribe(): Promise<void> { async function unsubscribe(): Promise<void> {
if (!isSupported.value || isLoading.value) return; if (!isSupported.value || isLoading.value) {
return;
}
isLoading.value = true; isLoading.value = true;
@ -96,6 +106,7 @@ export function usePushNotification() {
if (!subscription) { if (!subscription) {
isSubscribed.value = false; isSubscribed.value = false;
return; return;
} }

View File

@ -1,13 +1,13 @@
<script setup lang="ts"> <script setup lang="ts">
import { usePage } from '@inertiajs/vue3'; import { usePage } from '@inertiajs/vue3';
import AppSidebar from '@/components/AppSidebar.vue'; import AppSidebar from '@/components/AppSidebar.vue';
import UserNav from '@/components/UserNav.vue';
import { Separator } from '@/components/ui/separator'; import { Separator } from '@/components/ui/separator';
import { import {
SidebarInset, SidebarInset,
SidebarProvider, SidebarProvider,
SidebarTrigger, SidebarTrigger,
} from '@/components/ui/sidebar'; } from '@/components/ui/sidebar';
import UserNav from '@/components/UserNav.vue';
defineProps<{ defineProps<{
title?: string; title?: string;

View File

@ -2,6 +2,7 @@
import { Head, useForm } from '@inertiajs/vue3'; import { Head, useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue'; import { Save } from '@lucide/vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { DatePicker } from '@/components/ui/date-picker'; import { DatePicker } from '@/components/ui/date-picker';
@ -13,7 +14,6 @@ import {
FieldSet, FieldSet,
} from '@/components/ui/field'; } from '@/components/ui/field';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { PhoneNumberInput } from '@/components/form/phone-number-input';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import AccountLayout from '@/layouts/AccountLayout.vue'; import AccountLayout from '@/layouts/AccountLayout.vue';

View File

@ -2,16 +2,16 @@
import { Head } from '@inertiajs/vue3'; import { Head } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue'; import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import ExpenseFormModal from '@/components/admin/finance/expenses/ExpenseFormModal.vue';
import { createColumns } from '@/components/admin/finance/expenses/columns'; import { createColumns } from '@/components/admin/finance/expenses/columns';
import ExpenseFormModal from '@/components/admin/finance/expenses/ExpenseFormModal.vue';
import { DataTable } from '@/components/data-table'; import { DataTable } from '@/components/data-table';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { useCan } from '@/composables/useCan'; import { useCan } from '@/composables/useCan';
import { useDataTableQuery, useDataTableQuerySync } from '@/composables/useDataTableQuery'; import { useDataTableQuery, useDataTableQuerySync } from '@/composables/useDataTableQuery';
import AdminLayout from '@/layouts/AdminLayout.vue'; import AdminLayout from '@/layouts/AdminLayout.vue';
import type { ExpenseListItem, PaginatedExpenses } from '@/types/expense';
import type { DataTableSort } from '@/types/data-table'; import type { DataTableSort } from '@/types/data-table';
import type { ExpenseListItem, PaginatedExpenses } from '@/types/expense';
const props = defineProps<{ const props = defineProps<{
expenses: PaginatedExpenses; expenses: PaginatedExpenses;

View File

@ -2,8 +2,8 @@
import { Head, Link } from '@inertiajs/vue3'; import { Head, Link } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue'; import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import CuttingInProgressSection from '@/components/admin/manage/cuttings/CuttingInProgressSection.vue';
import CuttingGroupedTable from '@/components/admin/manage/cuttings/CuttingGroupedTable.vue'; import CuttingGroupedTable from '@/components/admin/manage/cuttings/CuttingGroupedTable.vue';
import CuttingInProgressSection from '@/components/admin/manage/cuttings/CuttingInProgressSection.vue';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { useCan } from '@/composables/useCan'; import { useCan } from '@/composables/useCan';

View File

@ -3,6 +3,7 @@ import { Head } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue'; import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { createColumns } from '@/components/admin/master/customers/columns'; import { createColumns } from '@/components/admin/master/customers/columns';
import CustomerFormModal from '@/components/admin/master/customers/CustomerFormModal.vue';
import { DataTable } from '@/components/data-table'; import { DataTable } from '@/components/data-table';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
@ -10,7 +11,6 @@ import { useCan } from '@/composables/useCan';
import { useDataTableQuery, useDataTableQuerySync } from '@/composables/useDataTableQuery'; import { useDataTableQuery, useDataTableQuerySync } from '@/composables/useDataTableQuery';
import AdminLayout from '@/layouts/AdminLayout.vue'; import AdminLayout from '@/layouts/AdminLayout.vue';
import type { DataTableSort } from '@/types/data-table'; import type { DataTableSort } from '@/types/data-table';
import CustomerFormModal from '@/components/admin/master/customers/CustomerFormModal.vue';
import type { CustomerListItem, PaginatedCustomers } from '@/types/customer'; import type { CustomerListItem, PaginatedCustomers } from '@/types/customer';
const props = defineProps<{ const props = defineProps<{

View File

@ -1,4 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Head, Link } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import MasterOutOfStockCatalogSection from '@/components/admin/master/MasterOutOfStockCatalogSection.vue'; import MasterOutOfStockCatalogSection from '@/components/admin/master/MasterOutOfStockCatalogSection.vue';
import ProductGroupedTable from '@/components/admin/master/products/ProductGroupedTable.vue'; import ProductGroupedTable from '@/components/admin/master/products/ProductGroupedTable.vue';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@ -15,9 +18,6 @@ import type {
ProductOutOfStockGroup, ProductOutOfStockGroup,
ProductStockWarningGroup, ProductStockWarningGroup,
} from '@/types/product'; } from '@/types/product';
import { Head, Link } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
const props = defineProps<{ const props = defineProps<{
products: PaginatedProducts; products: PaginatedProducts;

View File

@ -1,4 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Head, Link } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import MasterOutOfStockCatalogSection from '@/components/admin/master/MasterOutOfStockCatalogSection.vue'; import MasterOutOfStockCatalogSection from '@/components/admin/master/MasterOutOfStockCatalogSection.vue';
import RawMaterialGroupedTable from '@/components/admin/master/raw-materials/RawMaterialGroupedTable.vue'; import RawMaterialGroupedTable from '@/components/admin/master/raw-materials/RawMaterialGroupedTable.vue';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@ -12,9 +15,6 @@ import AdminLayout from '@/layouts/AdminLayout.vue';
import type { DataTableFilterDef } from '@/types/data-table'; import type { DataTableFilterDef } from '@/types/data-table';
import type { MasterOutOfStockGroup } from '@/types/master-inventory'; import type { MasterOutOfStockGroup } from '@/types/master-inventory';
import type { PaginatedRawMaterials } from '@/types/raw-material'; import type { PaginatedRawMaterials } from '@/types/raw-material';
import { Head, Link } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
const props = defineProps<{ const props = defineProps<{
rawMaterials: PaginatedRawMaterials; rawMaterials: PaginatedRawMaterials;

View File

@ -2,6 +2,8 @@
import { Head } from '@inertiajs/vue3'; import { Head } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue'; import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { createColumns } from '@/components/admin/master/suppliers/columns';
import SupplierFormModal from '@/components/admin/master/suppliers/SupplierFormModal.vue';
import { DataTable } from '@/components/data-table'; import { DataTable } from '@/components/data-table';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
@ -9,8 +11,6 @@ import { useCan } from '@/composables/useCan';
import { useDataTableQuery, useDataTableQuerySync } from '@/composables/useDataTableQuery'; import { useDataTableQuery, useDataTableQuerySync } from '@/composables/useDataTableQuery';
import AdminLayout from '@/layouts/AdminLayout.vue'; import AdminLayout from '@/layouts/AdminLayout.vue';
import type { DataTableSort } from '@/types/data-table'; import type { DataTableSort } from '@/types/data-table';
import { createColumns } from '@/components/admin/master/suppliers/columns';
import SupplierFormModal from '@/components/admin/master/suppliers/SupplierFormModal.vue';
import type { SupplierListItem, PaginatedSuppliers } from '@/types/supplier'; import type { SupplierListItem, PaginatedSuppliers } from '@/types/supplier';
const props = defineProps<{ const props = defineProps<{

View File

@ -1,4 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
const sw = self as unknown as ServiceWorkerGlobalScope; const sw = self as unknown as ServiceWorkerGlobalScope;
@ -35,7 +35,9 @@ sw.addEventListener('activate', (event: Event) => {
sw.addEventListener('push', (event: Event) => { sw.addEventListener('push', (event: Event) => {
const pushEvent = event as PushEvent; const pushEvent = event as PushEvent;
if (!pushEvent.data) return; if (!pushEvent.data) {
return;
}
let data: { title?: string; body?: string; icon?: string; url?: string } = let data: { title?: string; body?: string; icon?: string; url?: string } =
{}; {};
@ -81,6 +83,7 @@ sw.addEventListener('notificationclick', (event: Event) => {
.then((c) => c?.focus()); .then((c) => c?.focus());
} }
} }
return sw.clients.openWindow(targetUrl); return sw.clients.openWindow(targetUrl);
}), }),
); );