155 lines
11 KiB
PHP
155 lines
11 KiB
PHP
<x-app-layout>
|
||
<x-slot name="header">
|
||
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||
{{ __('Edit Budget') }} - {{ $budget->fiscal_year }}
|
||
</h2>
|
||
</x-slot>
|
||
|
||
<div class="py-12" x-data="budgetEditor()">
|
||
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
|
||
<form method="POST" action="{{ route('admin.budgets.update', $budget) }}" class="space-y-6">
|
||
@csrf
|
||
@method('PATCH')
|
||
|
||
<!-- Basic Info -->
|
||
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
|
||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100 mb-4">{{ __('Basic Information') }}</h3>
|
||
|
||
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
|
||
<div>
|
||
<label for="name" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Budget Name') }} *</label>
|
||
<input type="text" name="name" id="name" value="{{ old('name', $budget->name) }}" required
|
||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
|
||
@error('name')<p class="mt-1 text-sm text-red-600 dark:text-red-400">{{ $message }}</p>@enderror
|
||
</div>
|
||
|
||
<div>
|
||
<label for="period_start" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Period Start') }} *</label>
|
||
<input type="date" name="period_start" id="period_start" value="{{ old('period_start', $budget->period_start->format('Y-m-d')) }}" required
|
||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
|
||
</div>
|
||
|
||
<div>
|
||
<label for="period_end" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Period End') }} *</label>
|
||
<input type="date" name="period_end" id="period_end" value="{{ old('period_end', $budget->period_end->format('Y-m-d')) }}" required
|
||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
|
||
</div>
|
||
|
||
<div class="sm:col-span-2">
|
||
<label for="notes" class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Notes') }}</label>
|
||
<textarea name="notes" id="notes" rows="3" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">{{ old('notes', $budget->notes) }}</textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Income Items -->
|
||
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
|
||
<div class="flex items-center justify-between mb-4">
|
||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('Income') }} (6e)</h3>
|
||
<button type="button" @click="addItem('income')" class="btn-secondary text-sm">+ {{ __('Add Income Item') }}</button>
|
||
</div>
|
||
|
||
<div class="space-y-4">
|
||
<template x-for="(item, index) in incomeItems" :key="index">
|
||
<div class="flex gap-4 items-start bg-gray-50 dark:bg-gray-900 p-4 rounded-md">
|
||
<div class="flex-1">
|
||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Account') }}</label>
|
||
<select :name="'budget_items[income_' + index + '][chart_of_account_id]'" x-model="item.account_id" required
|
||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
|
||
<option value="">{{ __('Select account...') }}</option>
|
||
@foreach($incomeAccounts as $account)
|
||
<option value="{{ $account->id }}">{{ $account->account_code }} - {{ $account->account_name_zh }}</option>
|
||
@endforeach
|
||
</select>
|
||
</div>
|
||
<div class="w-48">
|
||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Amount') }}</label>
|
||
<input type="number" :name="'budget_items[income_' + index + '][budgeted_amount]'" x-model="item.amount" step="0.01" min="0" required
|
||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
|
||
</div>
|
||
<div class="pt-6">
|
||
<button type="button" @click="removeItem('income', index)" class="text-red-600 hover:text-red-800 dark:text-red-400">
|
||
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd"/></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<div x-show="incomeItems.length === 0" class="text-center py-8 text-gray-500 dark:text-gray-400">
|
||
{{ __('No income items. Click "Add Income Item" to get started.') }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Expense Items -->
|
||
<div class="bg-white shadow sm:rounded-lg dark:bg-gray-800 px-4 py-5 sm:p-6">
|
||
<div class="flex items-center justify-between mb-4">
|
||
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">{{ __('Expenses') }} (/<EFBFBD>)</h3>
|
||
<button type="button" @click="addItem('expense')" class="btn-secondary text-sm">+ {{ __('Add Expense Item') }}</button>
|
||
</div>
|
||
|
||
<div class="space-y-4">
|
||
<template x-for="(item, index) in expenseItems" :key="index">
|
||
<div class="flex gap-4 items-start bg-gray-50 dark:bg-gray-900 p-4 rounded-md">
|
||
<div class="flex-1">
|
||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Account') }}</label>
|
||
<select :name="'budget_items[expense_' + index + '][chart_of_account_id]'" x-model="item.account_id" required
|
||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
|
||
<option value="">{{ __('Select account...') }}</option>
|
||
@foreach($expenseAccounts as $account)
|
||
<option value="{{ $account->id }}">{{ $account->account_code }} - {{ $account->account_name_zh }}</option>
|
||
@endforeach
|
||
</select>
|
||
</div>
|
||
<div class="w-48">
|
||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">{{ __('Amount') }}</label>
|
||
<input type="number" :name="'budget_items[expense_' + index + '][budgeted_amount]'" x-model="item.amount" step="0.01" min="0" required
|
||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600 dark:text-gray-100">
|
||
</div>
|
||
<div class="pt-6">
|
||
<button type="button" @click="removeItem('expense', index)" class="text-red-600 hover:text-red-800 dark:text-red-400">
|
||
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd"/></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<div x-show="expenseItems.length === 0" class="text-center py-8 text-gray-500 dark:text-gray-400">
|
||
{{ __('No expense items. Click "Add Expense Item" to get started.') }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Actions -->
|
||
<div class="flex items-center justify-end gap-x-4">
|
||
<a href="{{ route('admin.budgets.show', $budget) }}" class="btn-secondary">{{ __('Cancel') }}</a>
|
||
<button type="submit" class="btn-primary">{{ __('Save Budget') }}</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function budgetEditor() {
|
||
return {
|
||
incomeItems: @json($budget->budgetItems->filter(fn($item) => $item->chartOfAccount->isIncome())->map(fn($item) => ['account_id' => $item->chart_of_account_id, 'amount' => $item->budgeted_amount])->values()),
|
||
expenseItems: @json($budget->budgetItems->filter(fn($item) => $item->chartOfAccount->isExpense())->map(fn($item) => ['account_id' => $item->chart_of_account_id, 'amount' => $item->budgeted_amount])->values()),
|
||
|
||
addItem(type) {
|
||
if (type === 'income') {
|
||
this.incomeItems.push({ account_id: '', amount: 0 });
|
||
} else {
|
||
this.expenseItems.push({ account_id: '', amount: 0 });
|
||
}
|
||
},
|
||
|
||
removeItem(type, index) {
|
||
if (type === 'income') {
|
||
this.incomeItems.splice(index, 1);
|
||
} else {
|
||
this.expenseItems.splice(index, 1);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
</x-app-layout>
|