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 { LucideArrowUpRight, LucideArrowDownRight, LucideEdit, LucideTrash2 } from 'lucide-svelte';
let transactions = [
{
id: 1,
date: '2023-05-15',
description: 'iPhone 12 screen replacement',
type: 'income',
category: 'Screen Repair',
amount: 1200000,
paymentMethod: 'cash'
},
{
id: 2,
date: '2023-05-14',
description: 'Bought battery for iPhone X',
type: 'expense',
category: 'Battery',
amount: 350000,
paymentMethod: 'bank'
},
{
id: 3,
date: '2023-05-12',
description: 'Samsung S21 screen repair',
type: 'income',
category: 'Screen Repair',
amount: 900000,
paymentMethod: 'ewallet'
}
];
let currentPage = 1;
const itemsPerPage = 10;
function handleEdit(transaction) {
// TODO: Implement edit
console.log('Edit:', transaction);
}
function handleDelete(id) {
// TODO: Implement delete
console.log('Delete:', id);
}
</script>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-slate-200">
<thead class="bg-slate-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Date</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Description</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Category</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-slate-500 uppercase tracking-wider">Payment</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium text-slate-500 uppercase tracking-wider">Amount</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium text-slate-500 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-slate-200">
{#each transactions as transaction (transaction.id)}
<tr class="hover:bg-slate-50">
<td class="px-6 py-4 whitespace-nowrap text-sm text-slate-500">{transaction.date}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-slate-900">{transaction.description}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-slate-500">{transaction.category}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-slate-500 capitalize">{transaction.paymentMethod}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-right {transaction.type === 'income' ? 'text-green-600' : 'text-red-600'}">
{transaction.type === 'income' ? '+' : '-'}Rp {transaction.amount.toLocaleString()}
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<div class="flex space-x-2 justify-end">
<button
on:click={() => handleEdit(transaction)}
class="text-blue-500 hover:text-blue-700"
title="Edit"
>
<LucideEdit size={16} />
</button>
<button
on:click={() => handleDelete(transaction.id)}
class="text-red-500 hover:text-red-700"
title="Delete"
>
<LucideTrash2 size={16} />
</button>
</div>
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{#if transactions.length === 0}
<div class="text-center py-8">
<p class="text-slate-500">No transactions yet. Add your first transaction!</p>
</div>
{/if}
<div class="flex items-center justify-between mt-4">
<div class="text-sm text-slate-500">
Showing {Math.min(currentPage * itemsPerPage, transactions.length)} of {transactions.length} transactions
</div>
<div class="flex space-x-2">
<button
disabled={currentPage === 1}
class="px-3 py-1 rounded border border-slate-200 text-slate-700 disabled:opacity-50"
>
Previous
</button>
<button
disabled={currentPage * itemsPerPage >= transactions.length}
class="px-3 py-1 rounded border border-slate-200 text-slate-700 disabled:opacity-50"
>
Next
</button>
</div>
</div>
</html>