- CodeIgniter 4 framework setup with SQL Server database config - Models: Control, Test, Dept, Result, Daily/ Monthly entry models - Controllers: Dashboard, Control, Test, Dept, Entry, Report, API endpoints - Views: CRUD pages with modal dialogs, dashboard, reports - Database: Migrations for control test and daily/monthly result tables - Legacy v1 PHP application preserved in /v1 directory - Documentation: AGENTS.md, VIEWS_RULES.md for development guidelines
96 lines
6.4 KiB
PHP
96 lines
6.4 KiB
PHP
<!-- Backdrop -->
|
|
<div x-show="showModal"
|
|
x-transition:enter="transition ease-out duration-200"
|
|
x-transition:enter-start="opacity-0"
|
|
x-transition:enter-end="opacity-100"
|
|
x-transition:leave="transition ease-in duration-150"
|
|
x-transition:leave-start="opacity-100"
|
|
x-transition:leave-end="opacity-0"
|
|
class="fixed inset-0 bg-slate-900/50 backdrop-blur-sm z-40"
|
|
@click="closeModal()">
|
|
</div>
|
|
|
|
<!-- Modal Panel -->
|
|
<div x-show="showModal"
|
|
x-cloak
|
|
x-transition:enter="transition ease-out duration-200"
|
|
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
|
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
|
x-transition:leave="transition ease-in duration-150"
|
|
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
|
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
|
class="fixed inset-0 z-50 flex items-center justify-center p-4">
|
|
<div class="bg-white rounded-2xl shadow-2xl w-full max-w-2xl" @click.stop>
|
|
<!-- Header -->
|
|
<div class="px-6 py-4 border-b border-slate-100 flex items-center justify-between">
|
|
<h3 class="text-lg font-semibold text-slate-800" x-text="form.control_id ? 'Edit Control' : 'Add Control'"></h3>
|
|
<button @click="closeModal()" class="text-slate-400 hover:text-slate-600">
|
|
<i class="fa-solid fa-xmark text-xl"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Form -->
|
|
<form @submit.prevent="save()">
|
|
<div class="p-6">
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700 mb-1">Department <span class="text-red-500">*</span></label>
|
|
<select x-model="form.dept_ref_id" class="w-full px-4 py-2.5 text-sm bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500" :class="{'border-red-300 bg-red-50': errors.dept_ref_id}" required>
|
|
<option value="">Select Department</option>
|
|
<template x-for="dept in depts" :key="dept.dept_id">
|
|
<option :value="dept.dept_id" x-text="dept.name"></option>
|
|
</template>
|
|
</select>
|
|
<p x-show="errors.dept_ref_id" x-text="errors.dept_ref_id" class="text-red-500 text-xs mt-1"></p>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700 mb-1">Control Name <span class="text-red-500">*</span></label>
|
|
<input type="text" x-model="form.name" class="w-full px-4 py-2.5 text-sm bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500" :class="{'border-red-300 bg-red-50': errors.name}" placeholder="Enter control name" required>
|
|
<p x-show="errors.name" x-text="errors.name" class="text-red-500 text-xs mt-1"></p>
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700 mb-1">Lot Number</label>
|
|
<input type="text" x-model="form.lot" class="w-full px-4 py-2.5 text-sm bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500" placeholder="Enter lot number">
|
|
</div>
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700 mb-1">Producer</label>
|
|
<input type="text" x-model="form.producer" class="w-full px-4 py-2.5 text-sm bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500" placeholder="Enter producer">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-sm font-medium text-slate-700 mb-1">Expiry Date</label>
|
|
<input type="date" x-model="form.expdate" class="w-full px-4 py-2.5 text-sm bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500">
|
|
</div>
|
|
<div class="col-span-2">
|
|
<label class="block text-sm font-medium text-slate-700 mb-1">Assigned Tests</label>
|
|
<div class="border border-slate-200 rounded-lg p-3 bg-slate-50 max-h-48 overflow-y-auto">
|
|
<div class="grid grid-cols-2 gap-2">
|
|
<template x-for="test in tests" :key="test.test_id">
|
|
<label class="flex items-center gap-2 cursor-pointer">
|
|
<input type="checkbox" :value="test.test_id" x-model="form.test_ids" class="w-4 h-4 text-blue-600 rounded border-slate-300 focus:ring-blue-500">
|
|
<span class="text-sm text-slate-700" x-text="test.name + ' (' + (test.dept_name || '') + ')'"></span>
|
|
</label>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<p class="text-xs text-slate-500 mt-1">Select tests to associate with this control</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Footer -->
|
|
<div class="flex items-center justify-end gap-3 px-6 py-4 border-t border-slate-100 bg-slate-50/50 rounded-b-2xl">
|
|
<button type="button" @click="closeModal()" class="px-4 py-2 text-sm font-medium text-slate-600 hover:text-slate-800 transition-colors">Cancel</button>
|
|
<button type="submit" :disabled="loading" class="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors">
|
|
<template x-if="!loading">
|
|
<span><i class="fa-solid fa-check mr-1"></i> <span x-text="form.control_id ? 'Update' : 'Save'"></span></span>
|
|
</template>
|
|
<template x-if="loading">
|
|
<span><i class="fa-solid fa-spinner fa-spin mr-1"></i> Saving...</span>
|
|
</template>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|