feat: enhance UI consistency by adding consistent icons to action buttons and loaders to save operations across admin modules
This commit is contained in:
parent
2b43213ee4
commit
26eaaf6d66
@ -2,7 +2,7 @@ import { Head } from '@inertiajs/react';
|
|||||||
import type { Expense } from '@/types';
|
import type { Expense } from '@/types';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Trash2, X } from 'lucide-react';
|
import { Trash2, X, Plus } from 'lucide-react';
|
||||||
import { DataTable } from '@/components/data-table';
|
import { DataTable } from '@/components/data-table';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
@ -55,7 +55,8 @@ export default function ExpenseIndex({ expenses }: { expenses: Expense[] }) {
|
|||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold tracking-tight">Pengeluaran</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Pengeluaran</h1>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={onAdd}>
|
<Button onClick={onAdd} className="gap-2">
|
||||||
|
<Plus className="size-4" />
|
||||||
Tambah
|
Tambah
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -119,8 +120,14 @@ export default function ExpenseIndex({ expenses }: { expenses: Expense[] }) {
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
<AlertDialogAction onClick={confirmDelete} variant="destructive">Hapus</AlertDialogAction>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={confirmDelete} variant="destructive" className="gap-2">
|
||||||
|
<Trash2 className="size-4" />
|
||||||
|
Hapus
|
||||||
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
@ -138,11 +145,16 @@ export default function ExpenseIndex({ expenses }: { expenses: Expense[] }) {
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={confirmBulkDelete}
|
onClick={confirmBulkDelete}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
|
className="gap-2"
|
||||||
>
|
>
|
||||||
|
<Trash2 className="size-4" />
|
||||||
Hapus
|
Hapus
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import { useEffect, useState, useRef } from 'react';
|
|||||||
import expenseRoutes from '@/routes/expense';
|
import expenseRoutes from '@/routes/expense';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { NumericFormat } from 'react-number-format';
|
import { NumericFormat } from 'react-number-format';
|
||||||
import { ImagePlus, X } from 'lucide-react';
|
import { ImagePlus, X, Save, Loader } from 'lucide-react';
|
||||||
|
|
||||||
interface ExpenseFormModalProps {
|
interface ExpenseFormModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -183,8 +183,12 @@ export function ExpenseFormModal({ isOpen, onClose, expense }: ExpenseFormModalP
|
|||||||
</Field>
|
</Field>
|
||||||
</FieldGroup>
|
</FieldGroup>
|
||||||
<DialogFooter className="mt-6">
|
<DialogFooter className="mt-6">
|
||||||
<Button type="button" variant="outline" onClick={handleClose}>Batal</Button>
|
<Button type="button" variant="outline" className="gap-2" onClick={handleClose}>
|
||||||
<Button type="submit" disabled={processing}>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" className="gap-2" disabled={processing}>
|
||||||
|
{processing ? <Loader className="size-4 animate-spin" /> : <Save className="size-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Simpan'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Head } from '@inertiajs/react';
|
|||||||
import type { Payroll } from '@/types';
|
import type { Payroll } from '@/types';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Trash2 } from 'lucide-react';
|
import { Trash2, Sparkles, Plus, X } from 'lucide-react';
|
||||||
import { DataTable } from '@/components/data-table';
|
import { DataTable } from '@/components/data-table';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
@ -60,7 +60,8 @@ export default function PayrollIndex({
|
|||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold tracking-tight">Penggajian</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Penggajian</h1>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={onGenerate} disabled={isGenerating}>
|
<Button onClick={onGenerate} disabled={isGenerating} className="gap-2">
|
||||||
|
{isGenerating ? <Sparkles className="size-4 animate-spin" /> : <Sparkles className="size-4" />}
|
||||||
Generate
|
Generate
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -158,8 +159,14 @@ export default function PayrollIndex({
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
<AlertDialogAction onClick={confirmDelete} variant="destructive">Hapus</AlertDialogAction>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={confirmDelete} variant="destructive" className="gap-2">
|
||||||
|
<Trash2 className="size-4" />
|
||||||
|
Hapus
|
||||||
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
@ -177,11 +184,16 @@ export default function PayrollIndex({
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={confirmBulkDelete}
|
onClick={confirmBulkDelete}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
|
className="gap-2"
|
||||||
>
|
>
|
||||||
|
<Trash2 className="size-4" />
|
||||||
Hapus
|
Hapus
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
|
|||||||
@ -16,10 +16,11 @@ import { useForm } from '@inertiajs/react';
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import payrollRoutes from '@/routes/payroll';
|
import payrollRoutes from '@/routes/payroll';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Plus, Trash2 } from 'lucide-react';
|
import { Loader, Plus, Trash2 } from 'lucide-react';
|
||||||
import { NumericFormat } from 'react-number-format';
|
import { NumericFormat } from 'react-number-format';
|
||||||
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
||||||
import { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from '@/components/ui/empty';
|
import { Empty, EmptyDescription, EmptyHeader, EmptyTitle } from '@/components/ui/empty';
|
||||||
|
import { X, Save } from 'lucide-react';
|
||||||
|
|
||||||
interface PayrollFormModalProps {
|
interface PayrollFormModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -96,7 +97,8 @@ export function PayrollFormModal({ isOpen, onClose, payroll }: PayrollFormModalP
|
|||||||
<FieldGroup>
|
<FieldGroup>
|
||||||
<div className="flex items-center justify-between border-b pb-2 mb-4">
|
<div className="flex items-center justify-between border-b pb-2 mb-4">
|
||||||
<h3 className="text-sm font-medium">Bonus & Potongan</h3>
|
<h3 className="text-sm font-medium">Bonus & Potongan</h3>
|
||||||
<Button type="button" variant="outline" size="sm" onClick={addAdjustment}>
|
<Button type="button" variant="outline" size="sm" onClick={addAdjustment} className="gap-2">
|
||||||
|
<Plus className="size-4" />
|
||||||
Tambah
|
Tambah
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -180,8 +182,12 @@ export function PayrollFormModal({ isOpen, onClose, payroll }: PayrollFormModalP
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DialogFooter className="mt-6">
|
<DialogFooter className="mt-6">
|
||||||
<Button type="button" variant="outline" onClick={handleClose}>Batal</Button>
|
<Button type="button" variant="outline" className="gap-2" onClick={handleClose}>
|
||||||
<Button type="submit" disabled={processing}>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" className="gap-2" disabled={processing}>
|
||||||
|
{processing ? <Loader className="size-4 animate-spin" /> : <Save className="size-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Simpan'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import React, { useMemo, useState } from 'react';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Product, ProductPrice } from '@/types';
|
import { Product, ProductPrice } from '@/types';
|
||||||
import { OrderItem } from '@/types/order';
|
import { OrderItem } from '@/types/order';
|
||||||
import { Plus, Trash2, CalendarIcon, Minus, ShoppingCart, Search, ImagePlus, X, Tag } from 'lucide-react';
|
import { Plus, Trash2, CalendarIcon, Minus, ShoppingCart, Search, ImagePlus, X, Tag, ArrowLeft, Check, Loader, Save } from 'lucide-react';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
@ -66,8 +66,8 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
|
|||||||
const { data, setData, post, processing, errors, transform } = useForm({
|
const { data, setData, post, processing, errors, transform } = useForm({
|
||||||
invoice_number: '',
|
invoice_number: '',
|
||||||
customer_name: '',
|
customer_name: '',
|
||||||
discount: '',
|
discount: 0,
|
||||||
payment: '',
|
payment: 0,
|
||||||
payment_method: 'cash',
|
payment_method: 'cash',
|
||||||
order_status: 'delivered',
|
order_status: 'delivered',
|
||||||
order_channel: 'store',
|
order_channel: 'store',
|
||||||
@ -181,8 +181,8 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
|
|||||||
return cartItems.reduce((acc, item) => acc + item.total, 0);
|
return cartItems.reduce((acc, item) => acc + item.total, 0);
|
||||||
}, [cartItems]);
|
}, [cartItems]);
|
||||||
|
|
||||||
const total = subtotal - data.discount;
|
const total = subtotal - (Number(data.discount) || 0);
|
||||||
const change = data.payment - total;
|
const change = (Number(data.payment) || 0) - total;
|
||||||
const cartTotalItems = cartItems.reduce((a, i) => a + i.qty, 0);
|
const cartTotalItems = cartItems.reduce((a, i) => a + i.qty, 0);
|
||||||
|
|
||||||
const PriceTypeLabel = ({ type }: { type: string }) => {
|
const PriceTypeLabel = ({ type }: { type: string }) => {
|
||||||
@ -365,7 +365,7 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
|
|||||||
autoComplete='off'
|
autoComplete='off'
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
{change >= 0 && data.payment > 0 && (
|
{change >= 0 && (Number(data.payment) || 0) > 0 && (
|
||||||
<div className="flex justify-between items-center p-2 rounded bg-green-500/10 border border-green-500/20 text-green-600 dark:text-green-400">
|
<div className="flex justify-between items-center p-2 rounded bg-green-500/10 border border-green-500/20 text-green-600 dark:text-green-400">
|
||||||
<span className="text-xs font-bold uppercase">Kembalian</span>
|
<span className="text-xs font-bold uppercase">Kembalian</span>
|
||||||
<span className="text-lg font-bold">Rp {change.toLocaleString('id-ID')}</span>
|
<span className="text-lg font-bold">Rp {change.toLocaleString('id-ID')}</span>
|
||||||
@ -383,8 +383,9 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save
|
||||||
{processing ? 'Menyimpan...' : 'Checkout Pesanan'}
|
className="h-4 w-4" />}
|
||||||
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -397,7 +398,10 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
|
|||||||
<div className="flex items-center justify-between shrink-0">
|
<div className="flex items-center justify-between shrink-0">
|
||||||
<h1 className="text-3xl font-bold tracking-tight">Tambah Pesanan</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Tambah Pesanan</h1>
|
||||||
<Link href={orderRoutes.index().url}>
|
<Link href={orderRoutes.index().url}>
|
||||||
<Button variant='outline'>Kembali</Button>
|
<Button variant='outline' className="gap-2">
|
||||||
|
<ArrowLeft className="size-4" />
|
||||||
|
Kembali
|
||||||
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -616,8 +620,14 @@ export default function OrderCreate({ products, cartItems, orderStatus, orderCha
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button variant="outline" onClick={() => setQtyDialogIndex(null)}>Batal</Button>
|
<Button variant="outline" className="gap-2" onClick={() => setQtyDialogIndex(null)}>
|
||||||
<Button onClick={confirmQty}>Konfirmasi</Button>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</Button>
|
||||||
|
<Button className="gap-2" onClick={confirmQty}>
|
||||||
|
<Check className="size-4" />
|
||||||
|
Konfirmasi
|
||||||
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import React, { useMemo, useState } from 'react';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Product, ProductPrice } from '@/types';
|
import { Product, ProductPrice } from '@/types';
|
||||||
import { Order, OrderItem } from '@/types/order';
|
import { Order, OrderItem } from '@/types/order';
|
||||||
import { Plus, Trash2, CalendarIcon, Minus, ShoppingCart, Search, ImagePlus, X, Tag } from 'lucide-react';
|
import { Plus, Trash2, CalendarIcon, Minus, ShoppingCart, Search, ImagePlus, X, Tag, ArrowLeft, Check, Save, Loader } from 'lucide-react';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
@ -371,7 +371,7 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="w-full h-10 font-semibold shadow"
|
className="w-full h-10 font-semibold shadow gap-2"
|
||||||
disabled={processing || data.items.length === 0}
|
disabled={processing || data.items.length === 0}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (data.items.length > 0) {
|
if (data.items.length > 0) {
|
||||||
@ -379,8 +379,8 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Perbarui Pesanan'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -393,7 +393,10 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
|
|||||||
<div className="flex items-center justify-between shrink-0">
|
<div className="flex items-center justify-between shrink-0">
|
||||||
<h1 className="text-3xl font-bold tracking-tight">Ubah Pesanan</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Ubah Pesanan</h1>
|
||||||
<Link href={orderRoutes.index().url}>
|
<Link href={orderRoutes.index().url}>
|
||||||
<Button variant='outline'>Kembali</Button>
|
<Button variant='outline' className="gap-2">
|
||||||
|
<ArrowLeft className="size-4" />
|
||||||
|
Kembali
|
||||||
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -603,8 +606,14 @@ export default function OrderEdit({ order, products, orderStatus, orderChannels,
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button variant="outline" onClick={() => setQtyDialogIndex(null)}>Batal</Button>
|
<Button variant="outline" className="gap-2" onClick={() => setQtyDialogIndex(null)}>
|
||||||
<Button onClick={confirmQty}>Konfirmasi</Button>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</Button>
|
||||||
|
<Button className="gap-2" onClick={confirmQty}>
|
||||||
|
<Check className="size-4" />
|
||||||
|
Konfirmasi
|
||||||
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useCallback } from 'react';
|
|||||||
import type { Order } from '@/types/order';
|
import type { Order } from '@/types/order';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Trash2, ShoppingBag, Printer, Bluetooth, Usb, Unplug } from 'lucide-react';
|
import { Trash2, ShoppingBag, Printer, Bluetooth, Usb, Unplug, Plus, X, ArrowLeft } from 'lucide-react';
|
||||||
import { DataTable } from '@/components/data-table';
|
import { DataTable } from '@/components/data-table';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@ -184,7 +184,8 @@ export default function OrderIndex({ orders }: { orders: Order[] }) {
|
|||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
||||||
<Link href={orderRoutes.create().url}>
|
<Link href={orderRoutes.create().url}>
|
||||||
<Button>
|
<Button className="gap-2">
|
||||||
|
<Plus className="size-4" />
|
||||||
Tambah
|
Tambah
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@ -220,14 +221,20 @@ export default function OrderIndex({ orders }: { orders: Order[] }) {
|
|||||||
<AlertDialogMedia className="bg-destructive/10 text-destructive dark:bg-destructive/20 dark:text-destructive">
|
<AlertDialogMedia className="bg-destructive/10 text-destructive dark:bg-destructive/20 dark:text-destructive">
|
||||||
<Trash2 className="size-5" />
|
<Trash2 className="size-5" />
|
||||||
</AlertDialogMedia>
|
</AlertDialogMedia>
|
||||||
<AlertDialogTitle>Hapus data pesanan?</AlertDialogTitle>
|
<AlertDialogTitle>Hapus pesanan?</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
Tindakan ini tidak dapat dibatalkan. Data pesanan dengan nomor invoice <strong>{orderToDelete?.invoice_number}</strong> akan dihapus secara permanen dan stok akan dikembalikan.
|
Tindakan ini tidak dapat dibatalkan. Data pesanan dengan nomor invoice <strong>{orderToDelete?.invoice_number}</strong> akan dihapus secara permanen dan stok akan dikembalikan.
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
<AlertDialogAction onClick={confirmDelete} variant="destructive">Hapus</AlertDialogAction>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={confirmDelete} variant="destructive" className="gap-2">
|
||||||
|
<Trash2 className="size-4" />
|
||||||
|
Hapus
|
||||||
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
@ -245,11 +252,16 @@ export default function OrderIndex({ orders }: { orders: Order[] }) {
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={confirmBulkDelete}
|
onClick={confirmBulkDelete}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
|
className="gap-2"
|
||||||
>
|
>
|
||||||
|
<Trash2 className="size-4" />
|
||||||
Hapus
|
Hapus
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import purchaseRoutes from '@/routes/purchase';
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Product, ProductPrice } from '@/types';
|
import { Product, ProductPrice } from '@/types';
|
||||||
import { Plus, Trash2, CalendarIcon, Minus, ShoppingCart, Search, ImagePlus, X } from 'lucide-react';
|
import { Plus, Trash2, CalendarIcon, Minus, ShoppingCart, Search, ImagePlus, X, Loader, Save } from 'lucide-react';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||||
import { Calendar } from '@/components/ui/calendar';
|
import { Calendar } from '@/components/ui/calendar';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
@ -300,8 +300,8 @@ export default function PurchaseCreate({ products, cartItems }: { products: Prod
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Checkout Belanja'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -593,8 +593,8 @@ export default function PurchaseCreate({ products, cartItems }: { products: Prod
|
|||||||
className="w-full h-10 font-semibold shadow"
|
className="w-full h-10 font-semibold shadow"
|
||||||
disabled={processing || cartItems.length === 0}
|
disabled={processing || cartItems.length === 0}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Checkout Belanja'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -769,8 +769,8 @@ export default function PurchaseCreate({ products, cartItems }: { products: Prod
|
|||||||
disabled={processing || cartItems.length === 0}
|
disabled={processing || cartItems.length === 0}
|
||||||
onClick={() => onSubmit({ preventDefault: () => { } } as any)}
|
onClick={() => onSubmit({ preventDefault: () => { } } as any)}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Checkout Belanja'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import purchaseRoutes from '@/routes/purchase';
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Product, ProductPrice, Purchase } from '@/types';
|
import { Product, ProductPrice, Purchase } from '@/types';
|
||||||
import { Plus, Trash2, CalendarIcon, Minus, ShoppingCart, Search, ImagePlus, X } from 'lucide-react';
|
import { Plus, Trash2, CalendarIcon, Minus, ShoppingCart, Search, ImagePlus, X, Loader, Save } from 'lucide-react';
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||||
import { Calendar } from '@/components/ui/calendar';
|
import { Calendar } from '@/components/ui/calendar';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
@ -304,8 +304,8 @@ export default function PurchaseEdit({ purchase, products }: { purchase: Purchas
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Perbarui Belanja'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -597,8 +597,8 @@ export default function PurchaseEdit({ purchase, products }: { purchase: Purchas
|
|||||||
className="w-full h-10 font-semibold shadow"
|
className="w-full h-10 font-semibold shadow"
|
||||||
disabled={processing || data.items.length === 0}
|
disabled={processing || data.items.length === 0}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Perbarui Belanja'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -773,8 +773,8 @@ export default function PurchaseEdit({ purchase, products }: { purchase: Purchas
|
|||||||
disabled={processing || data.items.length === 0}
|
disabled={processing || data.items.length === 0}
|
||||||
onClick={() => onSubmit({ preventDefault: () => { } } as any)}
|
onClick={() => onSubmit({ preventDefault: () => { } } as any)}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Perbarui Belanja'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Head } from '@inertiajs/react';
|
|||||||
import type { Category } from '@/types';
|
import type { Category } from '@/types';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Trash2 } from 'lucide-react';
|
import { Trash2, Plus, X } from 'lucide-react';
|
||||||
import { DataTable } from '@/components/data-table';
|
import { DataTable } from '@/components/data-table';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
@ -52,7 +52,8 @@ export default function CategoryIndex({ categories }: { categories: Category[] }
|
|||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-bold tracking-tight">Kategori</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Kategori</h1>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={onAdd}>
|
<Button onClick={onAdd} className="gap-2">
|
||||||
|
<Plus className="size-4" />
|
||||||
Tambah
|
Tambah
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -108,8 +109,14 @@ export default function CategoryIndex({ categories }: { categories: Category[] }
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
<AlertDialogAction onClick={confirmDelete} variant="destructive">Hapus</AlertDialogAction>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={confirmDelete} variant="destructive" className="gap-2">
|
||||||
|
<Trash2 className="size-4" />
|
||||||
|
Hapus
|
||||||
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
@ -127,11 +134,16 @@ export default function CategoryIndex({ categories }: { categories: Category[] }
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={confirmBulkDelete}
|
onClick={confirmBulkDelete}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
|
className="gap-2"
|
||||||
>
|
>
|
||||||
|
<Trash2 className="size-4" />
|
||||||
Hapus
|
Hapus
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { useForm } from '@inertiajs/react';
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import categoryRoutes from '@/routes/category';
|
import categoryRoutes from '@/routes/category';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
|
import { X, Save, Loader } from 'lucide-react';
|
||||||
|
|
||||||
interface CategoryFormModalProps {
|
interface CategoryFormModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@ -88,8 +89,12 @@ export function CategoryFormModal({ isOpen, onClose, category }: CategoryFormMod
|
|||||||
</Field>
|
</Field>
|
||||||
</FieldGroup>
|
</FieldGroup>
|
||||||
<DialogFooter className="mt-6">
|
<DialogFooter className="mt-6">
|
||||||
<Button type="button" variant="outline" onClick={handleClose}>Batal</Button>
|
<Button type="button" variant="outline" className="gap-2" onClick={handleClose}>
|
||||||
<Button type="submit" disabled={processing}>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" className="gap-2" disabled={processing}>
|
||||||
|
{processing ? <Loader className="size-4 animate-spin" /> : <Save className="size-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Simpan'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import {
|
|||||||
useComboboxAnchor,
|
useComboboxAnchor,
|
||||||
} from "@/components/ui/combobox"
|
} from "@/components/ui/combobox"
|
||||||
import { NumericFormat } from 'react-number-format';
|
import { NumericFormat } from 'react-number-format';
|
||||||
import { ImagePlus, X, Upload } from 'lucide-react';
|
import { ImagePlus, X, Upload, ArrowLeft, Save, Loader } from 'lucide-react';
|
||||||
|
|
||||||
export default function ProductCreate({ categories }: { categories: Category[] }) {
|
export default function ProductCreate({ categories }: { categories: Category[] }) {
|
||||||
const { data, setData, post, processing, errors } = useForm<{
|
const { data, setData, post, processing, errors } = useForm<{
|
||||||
@ -117,7 +117,8 @@ export default function ProductCreate({ categories }: { categories: Category[] }
|
|||||||
<h1 className="text-3xl font-bold tracking-tight">Tambah Produk</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Tambah Produk</h1>
|
||||||
</div>
|
</div>
|
||||||
<Link href={productRoutes.index().url}>
|
<Link href={productRoutes.index().url}>
|
||||||
<Button variant='outline'>
|
<Button variant='outline' className="gap-2">
|
||||||
|
<ArrowLeft className="size-4" />
|
||||||
Kembali
|
Kembali
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@ -401,7 +402,8 @@ export default function ProductCreate({ categories }: { categories: Category[] }
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
||||||
<Button type="submit" className="w-full" disabled={processing}>
|
<Button type="submit" className="w-full gap-2" disabled={processing}>
|
||||||
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Simpan'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import {
|
|||||||
useComboboxAnchor,
|
useComboboxAnchor,
|
||||||
} from "@/components/ui/combobox"
|
} from "@/components/ui/combobox"
|
||||||
import { NumericFormat } from 'react-number-format';
|
import { NumericFormat } from 'react-number-format';
|
||||||
import { ImagePlus, X, Upload } from 'lucide-react';
|
import { ImagePlus, X, Upload, ArrowLeft, Save, Loader } from 'lucide-react';
|
||||||
|
|
||||||
interface ExistingImage {
|
interface ExistingImage {
|
||||||
kind: 'existing';
|
kind: 'existing';
|
||||||
@ -167,7 +167,8 @@ export default function ProductEdit({ product, categories }: { product: Product,
|
|||||||
<h1 className="text-3xl font-bold tracking-tight">Ubah Produk</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Ubah Produk</h1>
|
||||||
</div>
|
</div>
|
||||||
<Link href={productRoutes.index().url}>
|
<Link href={productRoutes.index().url}>
|
||||||
<Button variant='outline'>
|
<Button variant='outline' className="gap-2">
|
||||||
|
<ArrowLeft className="size-4" />
|
||||||
Kembali
|
Kembali
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@ -469,7 +470,8 @@ export default function ProductEdit({ product, categories }: { product: Product,
|
|||||||
|
|
||||||
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<Button type="submit" className="w-full" disabled={processing}>
|
<Button type="submit" className="w-full gap-2" disabled={processing}>
|
||||||
|
{processing ? <Loader className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Simpan'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Head, Link } from '@inertiajs/react';
|
|||||||
import type { Product, Category } from '@/types';
|
import type { Product, Category } from '@/types';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Trash2 } from 'lucide-react';
|
import { Trash2, Plus, X } from 'lucide-react';
|
||||||
import { DataTable } from '@/components/data-table';
|
import { DataTable } from '@/components/data-table';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
@ -52,7 +52,8 @@ export default function ProductIndex({ products, categories }: { products: Produ
|
|||||||
<h1 className="text-3xl font-bold tracking-tight">Produk</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Produk</h1>
|
||||||
</div>
|
</div>
|
||||||
<Link href={productRoutes.create().url}>
|
<Link href={productRoutes.create().url}>
|
||||||
<Button>
|
<Button className="gap-2">
|
||||||
|
<Plus className="size-4" />
|
||||||
Tambah
|
Tambah
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@ -111,8 +112,14 @@ export default function ProductIndex({ products, categories }: { products: Produ
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
<AlertDialogAction onClick={confirmDelete} variant="destructive">Hapus</AlertDialogAction>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={confirmDelete} variant="destructive" className="gap-2">
|
||||||
|
<Trash2 className="size-4" />
|
||||||
|
Hapus
|
||||||
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
@ -130,11 +137,16 @@ export default function ProductIndex({ products, categories }: { products: Produ
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={confirmBulkDelete}
|
onClick={confirmBulkDelete}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
|
className="gap-2"
|
||||||
>
|
>
|
||||||
|
<Trash2 className="size-4" />
|
||||||
Hapus
|
Hapus
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import {
|
|||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover"
|
} from "@/components/ui/popover"
|
||||||
import { NumericFormat } from 'react-number-format';
|
import { NumericFormat } from 'react-number-format';
|
||||||
|
import { ArrowLeft, Loader, Save } from 'lucide-react';
|
||||||
|
|
||||||
export default function UserCreate() {
|
export default function UserCreate() {
|
||||||
const [isCalendarOpen, setIsCalendarOpen] = React.useState(false);
|
const [isCalendarOpen, setIsCalendarOpen] = React.useState(false);
|
||||||
@ -50,7 +51,8 @@ export default function UserCreate() {
|
|||||||
<h1 className="text-3xl font-bold tracking-tight">Tambah Pegawai</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Tambah Pegawai</h1>
|
||||||
</div>
|
</div>
|
||||||
<Link href={userRoutes.index().url}>
|
<Link href={userRoutes.index().url}>
|
||||||
<Button variant='outline'>
|
<Button variant='outline' className="gap-2">
|
||||||
|
<ArrowLeft className="size-4" />
|
||||||
Kembali
|
Kembali
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@ -223,6 +225,7 @@ export default function UserCreate() {
|
|||||||
|
|
||||||
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
||||||
<Button type="submit" className="w-full" disabled={processing}>
|
<Button type="submit" className="w-full" disabled={processing}>
|
||||||
|
{processing ? <Loader className="size-4 animate-spin" /> : <Save className="size-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Simpan'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import {
|
|||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover"
|
} from "@/components/ui/popover"
|
||||||
import { NumericFormat } from 'react-number-format';
|
import { NumericFormat } from 'react-number-format';
|
||||||
|
import { ArrowLeft, Loader, Save } from 'lucide-react';
|
||||||
|
|
||||||
export default function UserEdit({ user }: { user: any }) {
|
export default function UserEdit({ user }: { user: any }) {
|
||||||
const [isCalendarOpen, setIsCalendarOpen] = React.useState(false);
|
const [isCalendarOpen, setIsCalendarOpen] = React.useState(false);
|
||||||
@ -52,6 +53,7 @@ export default function UserEdit({ user }: { user: any }) {
|
|||||||
</div>
|
</div>
|
||||||
<Link href={userRoutes.index().url}>
|
<Link href={userRoutes.index().url}>
|
||||||
<Button variant='outline'>
|
<Button variant='outline'>
|
||||||
|
<ArrowLeft className="size-4" />
|
||||||
Kembali
|
Kembali
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@ -224,6 +226,7 @@ export default function UserEdit({ user }: { user: any }) {
|
|||||||
|
|
||||||
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
||||||
<Button type="submit" className="w-full" disabled={processing}>
|
<Button type="submit" className="w-full" disabled={processing}>
|
||||||
|
{processing ? <Loader className="size-4 animate-spin" /> : <Save className="size-4" />}
|
||||||
{processing ? 'Menyimpan...' : 'Simpan'}
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { Head, Link } from '@inertiajs/react';
|
|||||||
import type { User } from '@/types';
|
import type { User } from '@/types';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Trash2, KeyRound } from 'lucide-react';
|
import { Trash2, KeyRound, Plus, X } from 'lucide-react';
|
||||||
import { DataTable } from '@/components/data-table';
|
import { DataTable } from '@/components/data-table';
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
@ -52,7 +52,8 @@ export default function UserIndex({ users, defaultPassword }: { users: User[], d
|
|||||||
<h1 className="text-3xl font-bold tracking-tight">Pegawai</h1>
|
<h1 className="text-3xl font-bold tracking-tight">Pegawai</h1>
|
||||||
</div>
|
</div>
|
||||||
<Link href={userRoutes.create().url}>
|
<Link href={userRoutes.create().url}>
|
||||||
<Button>
|
<Button className="gap-2">
|
||||||
|
<Plus className="size-4" />
|
||||||
Tambah
|
Tambah
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
@ -93,8 +94,14 @@ export default function UserIndex({ users, defaultPassword }: { users: User[], d
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
<AlertDialogAction onClick={confirmDelete} variant="destructive">Hapus</AlertDialogAction>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={confirmDelete} variant="destructive" className="gap-2">
|
||||||
|
<Trash2 className="size-4" />
|
||||||
|
Hapus
|
||||||
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
@ -106,14 +113,20 @@ export default function UserIndex({ users, defaultPassword }: { users: User[], d
|
|||||||
<AlertDialogMedia className="bg-blue-100 text-blue-600 dark:bg-blue-900/20 dark:text-blue-500">
|
<AlertDialogMedia className="bg-blue-100 text-blue-600 dark:bg-blue-900/20 dark:text-blue-500">
|
||||||
<KeyRound className="size-5" />
|
<KeyRound className="size-5" />
|
||||||
</AlertDialogMedia>
|
</AlertDialogMedia>
|
||||||
<AlertDialogTitle>Reset password?</AlertDialogTitle>
|
<AlertDialogTitle>Reset kata sandi?</AlertDialogTitle>
|
||||||
<AlertDialogDescription>
|
<AlertDialogDescription>
|
||||||
Tindakan ini akan mereset password <strong>{userToReset?.name}</strong> menjadi <strong>{defaultPassword}</strong>. Pengguna dapat mengubahnya kembali nanti.
|
Tindakan ini akan mereset kata sandi <strong>{userToReset?.name}</strong> menjadi <strong>{defaultPassword}</strong>. Pengguna dapat mengubahnya kembali nanti.
|
||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
<AlertDialogAction onClick={confirmResetPassword} className="bg-blue-600 hover:bg-blue-700 text-white focus:ring-blue-600">Reset</AlertDialogAction>
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={confirmResetPassword} className="bg-blue-600 hover:bg-blue-700 text-white focus:ring-blue-600 gap-2">
|
||||||
|
<KeyRound className="size-4" />
|
||||||
|
Reset
|
||||||
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
</AlertDialogContent>
|
</AlertDialogContent>
|
||||||
</AlertDialog>
|
</AlertDialog>
|
||||||
@ -131,11 +144,16 @@ export default function UserIndex({ users, defaultPassword }: { users: User[], d
|
|||||||
</AlertDialogDescription>
|
</AlertDialogDescription>
|
||||||
</AlertDialogHeader>
|
</AlertDialogHeader>
|
||||||
<AlertDialogFooter>
|
<AlertDialogFooter>
|
||||||
<AlertDialogCancel variant="outline">Batal</AlertDialogCancel>
|
<AlertDialogCancel variant="outline" className="gap-2">
|
||||||
|
<X className="size-4" />
|
||||||
|
Batal
|
||||||
|
</AlertDialogCancel>
|
||||||
<AlertDialogAction
|
<AlertDialogAction
|
||||||
onClick={confirmBulkDelete}
|
onClick={confirmBulkDelete}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
|
className="gap-2"
|
||||||
>
|
>
|
||||||
|
<Trash2 className="size-4" />
|
||||||
Hapus
|
Hapus
|
||||||
</AlertDialogAction>
|
</AlertDialogAction>
|
||||||
</AlertDialogFooter>
|
</AlertDialogFooter>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import type { GeneralSetting } from '@/types';
|
|||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import systemRoutes from '@/routes/system';
|
import systemRoutes from '@/routes/system';
|
||||||
import { ImagePlus, X } from 'lucide-react';
|
import { ImagePlus, X, Save, Loader } from 'lucide-react';
|
||||||
|
|
||||||
export default function SettingIndex({ setting }: { setting: GeneralSetting | null }) {
|
export default function SettingIndex({ setting }: { setting: GeneralSetting | null }) {
|
||||||
const { data, setData, post, processing, errors } = useForm({
|
const { data, setData, post, processing, errors } = useForm({
|
||||||
@ -227,8 +227,9 @@ export default function SettingIndex({ setting }: { setting: GeneralSetting | nu
|
|||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
<div className="flex flex-col gap-4 p-4 rounded-xl bg-primary/5 border border-primary/10 shadow-sm">
|
||||||
<Button type="submit" className="w-full" disabled={processing}>
|
<Button type="submit" className="w-full gap-2" disabled={processing}>
|
||||||
{processing ? 'Menyimpan...' : 'Simpan Perubahan'}
|
{processing ? <Loader className="size-4 animate-spin" /> : <Save className="size-4" />}
|
||||||
|
{processing ? 'Menyimpan...' : 'Simpan'}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user