Arifzyn's picture
Buatkan project web fullstack bernama "ServiceBook" menggunakan **SvelteKit** dengan UI memakai **Tailwind CSS**, ikon **Lucide** dan palet warna berupa **soft color blocks + white** (bersih, minimal, modern). Aplikasi ini untuk pencatatan keuangan usaha servis HP.
8f096b5 verified
svelte
<script>
import { createEventDispatcher } from 'svelte';
import { LucideSave, LucideX } from 'lucide-svelte';
const dispatch = createEventDispatcher();
export let transaction = {
date: new Date().toISOString().split('T')[0],
type: 'income',
description: '',
category: '',
amount: 0,
paymentMethod: 'cash'
};
export let categories = [];
const paymentMethods = [
{ value: 'cash', label: 'Cash' },
{ value: 'bank', label: 'Bank Transfer' },
{ value: 'card', label: 'Credit Card' },
{ value: 'ewallet', label: 'E-Wallet' }
];
function handleSubmit() {
if (!transaction.amount || transaction.amount <= 0) return;
if (!transaction.category) return;
dispatch('submit', transaction);
}
</script>
<form on:submit|preventDefault={handleSubmit} class="space-y-4">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="date" class="block text-sm font-medium text-slate-700 mb-1">Date</label>
<input
id="date"
type="date"
bind:value={transaction.date}
class="input-field"
required
/>
</div>
<div>
<label for="type" class="block text-sm font-medium text-slate-700 mb-1">Type</label>
<select
id="type"
bind:value={transaction.type}
class="input-field"
>
<option value="income">Income</option>
<option value="expense">Expense</option>
</select>
</div>
</div>
<div>
<label for="description" class="block text-sm font-medium text-slate-700 mb-1">Description</label>
<input
id="description"
type="text"
bind:value={transaction.description}
class="input-field"
placeholder="Repair iPhone screen, Buy spare parts..."
/>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="category" class="block text-sm font-medium text-slate-700 mb-1">Category</label>
<select
id="category"
bind:value={transaction.category}
class="input-field"
required
>
<option value="">Select a category</option>
{#each categories as category}
<option value={category}>{category}</option>
{/each}
</select>
</div>
<div>
<label for="amount" class="block text-sm font-medium text-slate-700 mb-1">Amount</label>
<div class="relative">
<span class="absolute left-3 top-1/2 -translate-y-1/2 text-slate-500">Rp</span>
<input
id="amount"
type="number"
bind:value={transaction.amount}
class="input-field pl-10"
min="0"
step="1000"
required
/>
</div>
</div>
</div>
<div>
<label for="paymentMethod" class="block text-sm font-medium text-slate-700 mb-1">Payment Method</label>
<select
id="paymentMethod"
bind:value={transaction.paymentMethod}
class="input-field"
>
{#each paymentMethods as method}
<option value={method.value}>{method.label}</option>
{/each}
</select>
</div>
<div class="flex justify-end space-x-3 pt-4">
<button
type="button"
on:click={() => dispatch('cancel')}
class="btn-secondary flex items-center space-x-1"
>
<LucideX size={18} />
<span>Cancel</span>
</button>
<button
type="submit"
class="btn-primary flex items-center space-x-1"
>
<LucideSave size={18} />
<span>Save</span>
</button>
</div>
</form>
</html>