mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-23 14:55:44 +00:00
105 lines
3.5 KiB
TypeScript
105 lines
3.5 KiB
TypeScript
import { formatNumber, formatDate } from '@/lib/helper';
|
|
import { toast } from 'react-hot-toast';
|
|
import * as XLSX from 'xlsx';
|
|
import { ProjectFlockKandangLookup } from '@/types/api/production/project-flock';
|
|
|
|
export const generateUniformityTemplate = (
|
|
population: number,
|
|
projectFlockKandangLookup: ProjectFlockKandangLookup
|
|
) => {
|
|
try {
|
|
const sampleSize = Math.round(population * 0.02);
|
|
const kandangName = projectFlockKandangLookup.kandang?.name || 'Kandang';
|
|
const flockName = projectFlockKandangLookup.project_flock?.flock_name || '';
|
|
const flockPeriod = projectFlockKandangLookup.project_flock?.period || 1;
|
|
const locationName =
|
|
projectFlockKandangLookup.project_flock?.location?.name || '';
|
|
|
|
const instructions = [
|
|
['PETUNJUK PENGISIAN DATA UNIFORMITY'],
|
|
[''],
|
|
['INFORMASI FLOCK'],
|
|
['Lokasi', locationName],
|
|
['Nama Flock', flockName],
|
|
['Periode', flockPeriod],
|
|
['Kandang', kandangName],
|
|
['Total Populasi', formatNumber(population)],
|
|
['Jumlah Sampel (2%)', formatNumber(sampleSize)],
|
|
[''],
|
|
['CARA PENGISIAN:'],
|
|
['1. Pindah ke sheet ke-2 untuk mengisi data BW (Body Weight).'],
|
|
[
|
|
'2. Kolom NO sudah terisi otomatis dari 1 sampai ' +
|
|
formatNumber(sampleSize),
|
|
],
|
|
['3. Isi kolom BW dengan berat badan ayam dalam gram.'],
|
|
['4. Pastikan baris terisi dengan data yang valid.'],
|
|
['5. Simpan file dan upload kembali ke sistem.'],
|
|
[''],
|
|
['FORMAT DATA:'],
|
|
['• NO: Nomor urut ayam (1, 2, 3, ...).'],
|
|
['• BW: Berat badan dalam gram (contoh: 1500, 1650, 1800).'],
|
|
[''],
|
|
['CATATAN:'],
|
|
[
|
|
'1. File ini dibuat secara otomatis berdasarkan ukuran sampling (2% dari total populasi).',
|
|
],
|
|
[
|
|
'2. Jumlah baris sudah ditentukan dan boleh ditambah asal angkanya berurutan.',
|
|
],
|
|
['3. Silakan isi berat badan (gram) untuk setiap ayam yang disampling.'],
|
|
[
|
|
'4. Biarkan sel kosong jika data tidak tersedia, jangan dihapus nomornya.',
|
|
],
|
|
];
|
|
|
|
const instructionSheet = XLSX.utils.aoa_to_sheet(instructions);
|
|
instructionSheet['!cols'] = [
|
|
{ wch: 30 }, // Column A width
|
|
{ wch: 40 }, // Column B width
|
|
];
|
|
|
|
const data = Array.from({ length: sampleSize }, (_, index) => ({
|
|
NO: index + 1,
|
|
BW: '',
|
|
}));
|
|
|
|
const dataWorksheet = XLSX.utils.json_to_sheet(data, {
|
|
header: ['NO', 'BW'],
|
|
});
|
|
|
|
dataWorksheet['!cols'] = [{ wch: 10 }, { wch: 15 }];
|
|
|
|
const workbook = XLSX.utils.book_new();
|
|
XLSX.utils.book_append_sheet(workbook, instructionSheet, 'Instruksi');
|
|
|
|
const dataSheetName =
|
|
kandangName.length > 31 ? kandangName.substring(0, 31) : kandangName;
|
|
XLSX.utils.book_append_sheet(workbook, dataWorksheet, dataSheetName);
|
|
|
|
const sanitizedFlockName = flockName
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '');
|
|
|
|
const sanitizedKandangName = kandangName
|
|
.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '');
|
|
|
|
const filename = `${formatDate(
|
|
new Date(),
|
|
'YYYY-MM-DD'
|
|
)}-${sanitizedFlockName}-${sanitizedKandangName}-periode-${flockPeriod}-data-${sampleSize}.xlsx`;
|
|
|
|
XLSX.writeFile(workbook, filename);
|
|
|
|
toast.success(
|
|
`Template berhasil dibuat dengan ${formatNumber(sampleSize)} baris data (2% dari ${formatNumber(population)} populasi).`
|
|
);
|
|
} catch (error) {
|
|
console.error('Error generating uniformity template:', error);
|
|
toast.error('Gagal membuat template Excel. Silakan coba lagi.');
|
|
}
|
|
};
|