202 lines
9.0 KiB
Vue
202 lines
9.0 KiB
Vue
<script setup>
|
|
import { ref } from 'vue'
|
|
import axios from 'axios'
|
|
import { useNavigate } from '../composables/Core/useNavigate'
|
|
import { useModal } from '../composables/Core/useModal'
|
|
import { usePageTitle } from '../composables/Core/usePageTitle'
|
|
import BackButton from '../Components/Core/BackButton.vue'
|
|
import LoadingSpinner from '../Components/LoadingSpinner.vue'
|
|
|
|
const { navigate } = useNavigate()
|
|
const modal = useModal()
|
|
usePageTitle('Batch Add Cooperatives')
|
|
|
|
const COOPERATIVE_TYPES = ['AGRICULTURAL', 'CREDIT', 'CONSUMERS', 'MARKETING', 'SERVICE', 'MULTIPURPOSE']
|
|
const COOPERATIVE_CATEGORIES = ['MICRO', 'SMALL', 'MEDIUM', 'LARGE']
|
|
|
|
const blankRow = () => ({
|
|
name: '',
|
|
address: '',
|
|
registration_number: '',
|
|
cin: '',
|
|
tin: '',
|
|
cooperative_type: '',
|
|
cooperative_category: '',
|
|
registration_date: '',
|
|
contact_person: '',
|
|
contact_number: '',
|
|
contact_email: '',
|
|
})
|
|
|
|
const cooperatives = ref([blankRow()])
|
|
const saving = ref(false)
|
|
|
|
const addRow = () => {
|
|
cooperatives.value.push(blankRow())
|
|
}
|
|
|
|
const removeRow = (index) => {
|
|
if (cooperatives.value.length > 1) cooperatives.value.splice(index, 1)
|
|
}
|
|
|
|
const saveCooperatives = async () => {
|
|
const invalid = cooperatives.value.some(c => !c.name || !c.name.trim())
|
|
if (invalid) {
|
|
modal.open({
|
|
title: 'Validation Error',
|
|
body: 'Cooperative Name is required for all rows.'
|
|
})
|
|
return
|
|
}
|
|
|
|
saving.value = true
|
|
try {
|
|
const response = await axios.post('/admin/batch/cooperatives', { cooperatives: cooperatives.value })
|
|
if (response.data && response.data.success) {
|
|
modal.open({
|
|
title: 'Success',
|
|
body: `Successfully added ${response.data.count} cooperatives.`,
|
|
onClose: () => navigate({ page: 'CooperativeList' })
|
|
})
|
|
}
|
|
} catch (err) {
|
|
console.error('Error saving batch cooperatives:', err)
|
|
const errorMessage = err.response?.data?.errors
|
|
? err.response.data.errors.join('<br>')
|
|
: (err.response?.data?.message || 'Failed to save cooperatives.')
|
|
|
|
modal.open({
|
|
title: 'Error',
|
|
body: errorMessage
|
|
})
|
|
} finally {
|
|
saving.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="batch-add-page pb-5">
|
|
<div class="tf-container mt-4">
|
|
<div class="mb-3">
|
|
<BackButton to="CooperativeList" />
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<h3 class="fw_6 mb-1">Batch Add Cooperatives</h3>
|
|
<p class="text-muted small mb-0">Register multiple cooperatives at once. Ideal for large-scale onboarding.</p>
|
|
</div>
|
|
|
|
<div class="d-grid mb-3">
|
|
<button @click="addRow" class="btn btn-outline-primary rounded-pill">
|
|
<i class="fas fa-plus-circle me-2"></i> Add Cooperative
|
|
</button>
|
|
</div>
|
|
|
|
<div class="row g-4">
|
|
<div v-for="(coop, index) in cooperatives" :key="index" class="col-md-6 col-lg-4">
|
|
<div class="leaf-card p-3 bg-white rounded-3 border position-relative h-100">
|
|
<div class="d-flex justify-content-between align-items-center mb-3 pb-2 border-bottom">
|
|
<span class="badge bg-primary rounded-pill">#{{ index + 1 }}</span>
|
|
<button @click="removeRow(index)" class="btn btn-link text-danger p-0 border-0"
|
|
:disabled="cooperatives.length <= 1"><i class="fas fa-times-circle"></i></button>
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<label class="form-label small fw-bold text-muted mb-1">Name *</label>
|
|
<input v-model="coop.name" type="text" class="form-control form-control-sm" placeholder="Cooperative name">
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<label class="form-label small fw-bold text-muted mb-1">Address</label>
|
|
<input v-model="coop.address" type="text" class="form-control form-control-sm" placeholder="Address">
|
|
</div>
|
|
|
|
<div class="row g-2 mb-2">
|
|
<div class="col-6">
|
|
<label class="form-label small fw-bold text-muted mb-1">Registration #</label>
|
|
<input v-model="coop.registration_number" type="text" class="form-control form-control-sm" placeholder="REG-12345">
|
|
</div>
|
|
<div class="col-6">
|
|
<label class="form-label small fw-bold text-muted mb-1">CIN</label>
|
|
<input v-model="coop.cin" type="text" class="form-control form-control-sm" placeholder="CIN">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<label class="form-label small fw-bold text-muted mb-1">TIN</label>
|
|
<input v-model="coop.tin" type="text" class="form-control form-control-sm" placeholder="TIN">
|
|
</div>
|
|
|
|
<div class="row g-2 mb-2">
|
|
<div class="col-6">
|
|
<label class="form-label small fw-bold text-muted mb-1">Type</label>
|
|
<select v-model="coop.cooperative_type" class="form-select form-select-sm">
|
|
<option value="">Select Type</option>
|
|
<option v-for="t in COOPERATIVE_TYPES" :key="t" :value="t">{{ t }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-6">
|
|
<label class="form-label small fw-bold text-muted mb-1">Category</label>
|
|
<select v-model="coop.cooperative_category" class="form-select form-select-sm">
|
|
<option value="">Select Category</option>
|
|
<option v-for="c in COOPERATIVE_CATEGORIES" :key="c" :value="c">{{ c }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<label class="form-label small fw-bold text-muted mb-1">Registration Date</label>
|
|
<input v-model="coop.registration_date" type="date" class="form-control form-control-sm">
|
|
</div>
|
|
|
|
<div class="row g-2 mb-2">
|
|
<div class="col-6">
|
|
<label class="form-label small fw-bold text-muted mb-1">Contact Person</label>
|
|
<input v-model="coop.contact_person" type="text" class="form-control form-control-sm" placeholder="Full name">
|
|
</div>
|
|
<div class="col-6">
|
|
<label class="form-label small fw-bold text-muted mb-1">Contact Number</label>
|
|
<input v-model="coop.contact_number" type="text" class="form-control form-control-sm" placeholder="09123456789">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-2">
|
|
<label class="form-label small fw-bold text-muted mb-1">Contact Email</label>
|
|
<input v-model="coop.contact_email" type="email" class="form-control form-control-sm" placeholder="email@example.com">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-grid mt-4">
|
|
<button @click="addRow" class="btn btn-outline-primary rounded-pill px-4 fw-semibold">
|
|
<i class="fas fa-plus-circle me-2"></i> Add Another Cooperative
|
|
</button>
|
|
</div>
|
|
|
|
<div class="d-grid mt-3 pt-3 border-top">
|
|
<button @click="saveCooperatives" :disabled="saving" class="btn btn-primary rounded-pill px-4 fw-semibold">
|
|
<i class="fas fa-save me-2"></i>
|
|
{{ saving ? 'Saving...' : 'Save All Cooperatives' }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.batch-add-page {
|
|
background: var(--bg-primary);
|
|
min-height: 100vh;
|
|
}
|
|
.leaf-card { transition: box-shadow 0.15s ease, transform 0.15s ease; }
|
|
.leaf-card:hover { box-shadow: 0 4px 12px rgba(13,110,253,0.08); transform: translateY(-2px); }
|
|
:global(.dark-mode) .leaf-card { background-color: var(--bg-secondary) !important; border-color: var(--border-color) !important; }
|
|
:global(.dark-mode) .form-control, :global(.dark-mode) .form-select {
|
|
background-color: var(--bg-secondary) !important;
|
|
color: var(--text-primary);
|
|
border-color: var(--border-color);
|
|
}
|
|
</style>
|