Merge branch 'dev' into feat/laporan-operasi-182
This commit is contained in:
No files matched your search
@@ -1,226 +0,0 @@
|
||||
export type SubjectCode = 'detail' | 'pri-complain' | 'sec-complain' | 'cur-disea-hist' | 'pas-disea-hist' | 'fam-disea-hist' | 'alg-hist' | 'alg-react' | 'med-hist' | 'blood-type'
|
||||
export type ObjectCode = 'detail' | 'consc-level' | 'consc-level-det' | 'syst-bp' | 'diast-bp' | 'pulse' | 'resp-rate' | 'hear-rt' | 'neuro-cranialis' | 'sensoris' | 'reflect-fisio' | 'reflect-pato' | 'autonom-neuron' | 'neck-rom' | 'body-rom' | 'aga-rom' | 'agb-rom' | 'neck-mmt' | 'body-mmt' | 'aga-mmt' | 'agb-mmt' | 'localis' | 'medical-trouble' | 'rehab-medic-trouble' | 'temp' | 'spo2' | 'weight' | 'height' | 'head-to-toe'
|
||||
export type AssessmentCode = 'detail' | 'early-med-diag' | 'late-med-diag' | 'sec-med-diag' | 'early-func-diag' | 'late-func-diag' | 'sec-func-diag' | 'patient-dev'
|
||||
export type PlanCode = 'detail' | 'plan'
|
||||
export type InstructionCode = 'detail' | 'medical-act' | 'supporting-exam' | 'therapy' | 'medication' | 'material' | 'rehab-program' | 'physic-modal' | 'exercise' | 'ortes-protesa' | 'education' | 'other'
|
||||
export type HeadToToeCode = 'head' | 'eye' | 'ear' | 'nose' | 'mouth-throat' | 'head-others' | 'thorax' | 'heart' | 'lung' | 'abdomen' | 'liver' | 'back' | 'ekstremitas' | 'gender' | 'rectum' | 'neuron' | 'body-others'
|
||||
export type McuUrgencyLevelCode = 'cito' | 'cito-igd' | 'ponek' | 'blood-gas' | 'priority-form' | 'routine'
|
||||
export type McuScopeCode = 'cp-lab' | 'mic-lab' | 'ap-lab' | 'rad'
|
||||
export type SoapiTypeCode = 'early-medic' | 'early-rehab' | 'function' | 'progress' | 'dev-record' | 'kfr-adm' | 'kfr-series'
|
||||
export type MedicalActionTypeCode = 'chemo' | 'hemo' | 'thalasemia' | 'echocardio' | 'spirometry'
|
||||
export type VehicleTypeCode = 'ambulance' | 'transport' | 'hearse'
|
||||
export type GeneralEduCode = 'right-obg' | 'general-consent' | 'service' | 'alt-care-src' | 'home-plan' | 'home-care' | 'orientation' | 'fall-risk-prevention' | 'alt-care' | 'act-delay' | 'others'
|
||||
export type SpecialEduCode = 'disease-diag-dev' | 'safe-med-usage' | 'side-effect' | 'diet' | 'pain-mgmt' | 'medical-eq-usage' | 'rehab-technique' | 'prevention-act'
|
||||
export type EduAssessmentCode = 'learn-ability' | 'learn-will' | 'obstacle' | 'learn-method' | 'lang' | 'lang-obstacle' | 'belief'
|
||||
export type AbilityCode = 'able' | 'not-able'
|
||||
export type WillCode = 'ready' | 'interested' | 'not-interested'
|
||||
export type MedObstacleCode = 'hearing' | 'sight' | 'physical' | 'emotional' | 'cognitif'
|
||||
export type LearnMethodCode = 'demo' | 'discuss-leaflet'
|
||||
export type LangClassCode = 'ind' | 'region' | 'foreign'
|
||||
export type TranslatorSrcCode = 'team' | 'family'
|
||||
|
||||
export const subjectCodes: Record<SubjectCode, string> = {
|
||||
detail: 'Detail',
|
||||
'pri-complain': 'Keluhan Utama',
|
||||
'sec-complain': 'Secondary Complaint',
|
||||
'cur-disea-hist': 'Current Disease History',
|
||||
'pas-disea-hist': 'Past Disease History',
|
||||
'fam-disea-hist': 'Family Disease History',
|
||||
'alg-hist': 'Allergic Hist',
|
||||
'alg-react': 'Allergic Reaction',
|
||||
'med-hist': 'Medication Hist',
|
||||
'blood-type': 'Golongan Darah',
|
||||
}
|
||||
|
||||
export const objectCodes: Record<ObjectCode, string> = {
|
||||
detail: 'Detail',
|
||||
'consc-level': 'Tingkat Kesadaran',
|
||||
'consc-level-det': 'Detail Tingkat Kesadaran',
|
||||
'syst-bp': 'Tekanan Darah Systolic',
|
||||
'diast-bp': 'Tekanan Darah Diastolic',
|
||||
'pulse': 'Nadi',
|
||||
'resp-rate': 'Pernafasan',
|
||||
'hear-rt': 'Detak Jantung',
|
||||
'neuro-cranialis': 'Neurologist Cranialist',
|
||||
'sensoris': 'Sensoris',
|
||||
'reflect-fisio': 'Refleks Fisiologi',
|
||||
'reflect-pato': 'Refleks Patologi',
|
||||
'autonom-neuron': 'Saraf Otonom',
|
||||
'neck-rom': 'ROM - Leher',
|
||||
'body-rom': 'ROM - Batang Tubuh',
|
||||
'aga-rom': 'ROM - AGA',
|
||||
'agb-rom': 'ROM - AGB',
|
||||
'neck-mmt': 'MMT - Leher',
|
||||
'body-mmt': 'MMT - Batang Tubuh',
|
||||
'aga-mmt': 'MMT - AGA',
|
||||
'agb-mmt': 'MMT - AGB',
|
||||
'localis': 'Status Lokalis',
|
||||
'medical-trouble': 'Masalah Medis',
|
||||
'rehab-medic-trouble': 'Masalah Rehab Medik',
|
||||
'temp': 'Suhu',
|
||||
'spo2': 'SpO2',
|
||||
'weight': 'Berat Badan',
|
||||
'height': 'Tinggi Badan',
|
||||
'head-to-toe': 'Kepala Sampai Kaki',
|
||||
}
|
||||
|
||||
export const assessmentCodes: Record<AssessmentCode, string> = {
|
||||
detail: 'Detail',
|
||||
'early-med-diag': 'Diagnosis Medis Awal',
|
||||
'late-med-diag': 'Diagnosis Medis Akhir',
|
||||
'sec-med-diag': 'Diagnosis Medis Sekunder',
|
||||
'early-func-diag': 'Diagnosis Fungsi Awal',
|
||||
'late-func-diag': 'Diagnosis Fungsi Akhir',
|
||||
'sec-func-diag': 'Diagnosis Fungsi Sekunder',
|
||||
'patient-dev': 'Catatan Perkembangan Patient',
|
||||
}
|
||||
|
||||
export const planCodes: Record<PlanCode, string> = {
|
||||
detail: 'Detail',
|
||||
'plan': 'Rencana',
|
||||
}
|
||||
|
||||
export const instructionCodes: Record<InstructionCode, string> = {
|
||||
detail: 'Detail Instruksi',
|
||||
'medical-act': 'Tindakan medis',
|
||||
'supporting-exam': 'Pemeriksaan Penunjang',
|
||||
'therapy': 'Terapi',
|
||||
'medication': 'Obat',
|
||||
'material': 'BMHP',
|
||||
'rehab-program': 'Program Rehab',
|
||||
'physic-modal': 'Modalitas Fisik',
|
||||
'exercise': 'Latihan',
|
||||
'ortes-protesa': 'Ortesa Protesa',
|
||||
'education': 'Edukasi',
|
||||
'other': 'Lain-lain',
|
||||
}
|
||||
|
||||
export const headToToeCodes: Record<HeadToToeCode, string> = {
|
||||
head: 'Kepala',
|
||||
eye: 'Mata',
|
||||
ear: 'Telinga',
|
||||
nose: 'Hidung',
|
||||
'mouth-throat': 'Mulut - Tenggorokan',
|
||||
'head-others': 'Kepala - Lainnya',
|
||||
thorax: 'Toraks',
|
||||
heart: 'Jantung',
|
||||
lung: 'Paru',
|
||||
abdomen: 'Perut',
|
||||
liver: 'Hati',
|
||||
back: 'Punggung',
|
||||
ekstremitas: 'Ekstermitas',
|
||||
gender: 'Kelamin',
|
||||
rectum: 'Dubur',
|
||||
neuron: 'Syaraf',
|
||||
'body-others': 'Badan - Lainnya',
|
||||
}
|
||||
|
||||
export const mcuUrgencyLevelCodes: Record<McuUrgencyLevelCode, string> = {
|
||||
cito: 'CITO',
|
||||
'cito-igd': 'CITO IGD',
|
||||
ponek: 'PONEK',
|
||||
'blood-gas': 'Analisa Gas Darah',
|
||||
'priority-form': 'Form Prioritas',
|
||||
routine: 'Pemeriksaan Rutin',
|
||||
}
|
||||
|
||||
export const mcuScopeCodes: Record<McuScopeCode, string> = {
|
||||
'cp-lab': 'Laboratorium',
|
||||
'mic-lab': 'Microbacterial Laboratorium',
|
||||
'ap-lab': 'Patology Anatomy Laboratorium',
|
||||
rad: 'Radiology',
|
||||
}
|
||||
|
||||
export const soapiTypeCodes: Record<SoapiTypeCode, string> = {
|
||||
'early-medic': 'Kajian Awal Medis',
|
||||
'early-rehab': 'Kajian Awal Rehab Medik',
|
||||
'function': 'Assessmen Fungsi',
|
||||
'progress': 'CPPT',
|
||||
'dev-record': 'Catatan Perkembangan',
|
||||
'kfr-adm': 'Soapi Untuk KFR',
|
||||
'kfr-series': 'Soapi Untuk KFR',
|
||||
}
|
||||
|
||||
export const medicalActionTypeCodes: Record<MedicalActionTypeCode, string> = {
|
||||
chemo: 'Kemoterapi',
|
||||
hemo: 'Hemofilia',
|
||||
thalasemia: 'Talasemi',
|
||||
echocardio: 'Echokardio',
|
||||
spirometry: 'Spirometri',
|
||||
}
|
||||
|
||||
export const vehicleTypeCodes: Record<VehicleTypeCode, string> = {
|
||||
ambulance: 'Ambulans',
|
||||
transport: 'Transport',
|
||||
hearse: 'Jenazah',
|
||||
}
|
||||
|
||||
export const generalEduCodes: Record<GeneralEduCode, string> = {
|
||||
'right-obg': 'Hak dan kewajiban pasien dan keluarga',
|
||||
'general-consent': 'General Consent',
|
||||
'service': 'Pelayanan yang disediakan (jam pelayanan, akses pelayanan dan proses pelayanan)',
|
||||
'alt-care-src': 'Sumber alternatif asuhan di tempat lain/faskes lain',
|
||||
'home-plan': 'Rencana tindakan di rumah',
|
||||
'home-care': 'Kebutuhan perawatan di rumah',
|
||||
'orientation': 'Orientasi ruangan',
|
||||
'fall-risk-prevention': 'Pencegahan risiko jatuh',
|
||||
'alt-care': 'Alternatif pelayanan',
|
||||
'act-delay': 'Penundaan Tindakan',
|
||||
'others': 'Lain - lain',
|
||||
}
|
||||
|
||||
export const specialEduCodes: Record<SpecialEduCode, string> = {
|
||||
'disease-diag-dev': 'Diagnosa penyakit dan perkembangannya',
|
||||
'safe-med-usage': 'Penggunaan obat yang aman,',
|
||||
'side-effect': 'efek samping dan reaksi obat',
|
||||
'diet': 'Diet/Nutrisi',
|
||||
'pain-mgmt': 'Managemen nyeri',
|
||||
'medical-eq-usage': 'Penggunaan Peralatan Medis',
|
||||
'rehab-technique': 'Tehnik Rehabilitasi',
|
||||
'prevention-act': 'Tindakan pencegahan (cuci tangan, pemasangan gelang)',
|
||||
}
|
||||
|
||||
export const eduAssessmentCodes: Record<EduAssessmentCode, string> = {
|
||||
'learn-ability': 'Kemampuan Belajar',
|
||||
'learn-will': 'Kemauan Belajar',
|
||||
'obstacle': 'Hambatan',
|
||||
'learn-method': 'Metode Pembelajaran',
|
||||
'lang': 'Bahasa',
|
||||
'lang-obstacle': 'Hambatan Bahasa',
|
||||
'belief': 'Keyakinan',
|
||||
}
|
||||
|
||||
export const abilityCodes: Record<AbilityCode, string> = {
|
||||
able: 'Mampu',
|
||||
'not-able': 'Tidak Mampu',
|
||||
}
|
||||
|
||||
export const willCodes: Record<WillCode, string> = {
|
||||
ready: 'Siap',
|
||||
interested: 'Tertarik',
|
||||
'not-interested': 'Tidak Tertarik',
|
||||
}
|
||||
|
||||
export const medObstacleCodes: Record<MedObstacleCode, string> = {
|
||||
hearing: 'Pendengaran',
|
||||
sight: 'Penglihatan',
|
||||
physical: 'Fisik',
|
||||
emotional: 'Emosional',
|
||||
cognitif: 'Kognitif',
|
||||
}
|
||||
|
||||
export const learnMethodCodes: Record<LearnMethodCode, string> = {
|
||||
demo: 'Demonstrasi',
|
||||
'discuss-leaflet': 'Diskusi Leaflet',
|
||||
}
|
||||
|
||||
export const langClassCodes: Record<LangClassCode, string> = {
|
||||
ind: 'Indonesia',
|
||||
region: 'Daerah',
|
||||
foreign: 'Asing',
|
||||
}
|
||||
|
||||
export const translatorSrcCodes: Record<TranslatorSrcCode, string> = {
|
||||
team: 'Tim Penerjemah',
|
||||
family: 'Keluarga',
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
export type ActiveStatusCode = 'active' | 'inactive'
|
||||
export type DataStatusCode = 'new' | 'review' | 'process' | 'done' | 'canceled' | 'rejected' | 'skipped'
|
||||
export type DataApprovalCode = 'new' | 'approved' | 'rejected'
|
||||
export type DataAvailabilityCode = 'review' | 'available' | 'unavailble'
|
||||
export type DataVerifiedCode = 'new' | 'verified' | 'rejected'
|
||||
export type UserStatusCode = 'new' | 'active' | 'inactive' | 'blocked' | 'suspended'
|
||||
export type ProcessStatusCode = 'success' | 'failed'
|
||||
export type TimeUnitCode = 'sec' | 'min' | 'hour' | 'day' | 'week' | 'month' | 'year'
|
||||
export type DayCode = '0' | '1' | '2' | '3' | '4' | '5' | '6'
|
||||
export type PaymentMethodCode = 'cash' | 'debit' | 'credit' | 'insurance' | 'membership'
|
||||
|
||||
export const activeStatusCodes: Record<ActiveStatusCode, string> = {
|
||||
active: 'Aktif',
|
||||
inactive: 'Tidak Aktif',
|
||||
}
|
||||
|
||||
export const dataStatusCodes: Record<DataStatusCode, string> = {
|
||||
new: 'Baru',
|
||||
review: 'Review',
|
||||
process: 'Proses',
|
||||
done: 'Selesai',
|
||||
canceled: 'Dibatalkan',
|
||||
rejected: 'Ditolak',
|
||||
skipped: 'Dilewati',
|
||||
}
|
||||
|
||||
export const dataApprovalCodes: Record<DataApprovalCode, string> = {
|
||||
new: 'Baru',
|
||||
approved: 'Diterima',
|
||||
rejected: 'Ditolak',
|
||||
}
|
||||
|
||||
export const dataAvailabilityCodes: Record<DataAvailabilityCode, string> = {
|
||||
review: 'Konfirmasi',
|
||||
available: 'Tersedia',
|
||||
unavailble: 'Tidak Tersedia',
|
||||
}
|
||||
|
||||
export const dataVerifiedCodes: Record<DataVerifiedCode, string> = {
|
||||
new: 'Baru',
|
||||
verified: 'Terverifikasi',
|
||||
rejected: 'Ditolak',
|
||||
}
|
||||
|
||||
export const userStatusCodes: Record<UserStatusCode, string> = {
|
||||
new: 'Baru',
|
||||
active: 'Aktif',
|
||||
inactive: 'Tidak Aktif',
|
||||
blocked: 'Diblokir',
|
||||
suspended: 'Dibekukan',
|
||||
}
|
||||
|
||||
export const processStatusCodes: Record<ProcessStatusCode, string> = {
|
||||
success: 'Sukses',
|
||||
failed: 'Gagal',
|
||||
}
|
||||
|
||||
export const timeUnitCodes: Record<TimeUnitCode, string> = {
|
||||
sec: 'Detik',
|
||||
min: 'Menit',
|
||||
hour: 'Jam',
|
||||
day: 'Hari',
|
||||
week: 'Minggu',
|
||||
month: 'Bulan',
|
||||
year: 'Tahun',
|
||||
}
|
||||
|
||||
export const dayCodes: Record<DayCode, string> = {
|
||||
'0': 'Minggu',
|
||||
'1': '',
|
||||
'2': '',
|
||||
'3': '',
|
||||
'4': '',
|
||||
'5': '',
|
||||
'6': 'Sabtu',
|
||||
}
|
||||
|
||||
export const paymentMethodCodes: Record<PaymentMethodCode, string> = {
|
||||
cash: 'Cash',
|
||||
debit: 'Debit',
|
||||
credit: 'Kredit',
|
||||
insurance: 'Asuransi',
|
||||
membership: 'Membership',
|
||||
}
|
||||
@@ -8,7 +8,7 @@ export const dataStatusCodes: Record<string, string> = {
|
||||
review: 'Review',
|
||||
process: 'Proses',
|
||||
done: 'Selesai',
|
||||
canceled: 'Dibatalkan',
|
||||
cancel: 'Dibatalkan',
|
||||
rejected: 'Ditolak',
|
||||
skiped: 'Dilewati',
|
||||
}
|
||||
|
||||
+72
-36
@@ -1,46 +1,69 @@
|
||||
const monthsInId = [
|
||||
'Januari',
|
||||
'Februari',
|
||||
'Maret',
|
||||
'April',
|
||||
'Mei',
|
||||
'Juni',
|
||||
'Juli',
|
||||
'Agustus',
|
||||
'September',
|
||||
'Oktober',
|
||||
'November',
|
||||
'Desember',
|
||||
]
|
||||
|
||||
export function getAge(dateString: string, comparedDate?: string): { idFormat: string; extFormat: string } {
|
||||
const birthDate = new Date(dateString);
|
||||
const today = new Date();
|
||||
const birthDate = new Date(dateString)
|
||||
const today = new Date()
|
||||
|
||||
if (comparedDate) {
|
||||
const comparedDateObj = new Date(comparedDate);
|
||||
today.setFullYear(comparedDateObj.getFullYear());
|
||||
today.setMonth(comparedDateObj.getMonth());
|
||||
today.setDate(comparedDateObj.getDate());
|
||||
}
|
||||
if (comparedDate) {
|
||||
const comparedDateObj = new Date(comparedDate)
|
||||
today.setFullYear(comparedDateObj.getFullYear())
|
||||
today.setMonth(comparedDateObj.getMonth())
|
||||
today.setDate(comparedDateObj.getDate())
|
||||
}
|
||||
|
||||
// Format the date part
|
||||
const options: Intl.DateTimeFormatOptions = { day: 'numeric', month: 'long', year: 'numeric' };
|
||||
const idFormat = birthDate.toLocaleDateString('id-ID', options);
|
||||
// Format the date part
|
||||
const options: Intl.DateTimeFormatOptions = { day: 'numeric', month: 'long', year: 'numeric' }
|
||||
const idFormat = birthDate.toLocaleDateString('id-ID', options)
|
||||
|
||||
// Calculate age
|
||||
let years = today.getFullYear() - birthDate.getFullYear();
|
||||
let months = today.getMonth() - birthDate.getMonth();
|
||||
let days = today.getDate() - birthDate.getDate();
|
||||
// Calculate age
|
||||
let years = today.getFullYear() - birthDate.getFullYear()
|
||||
let months = today.getMonth() - birthDate.getMonth()
|
||||
let days = today.getDate() - birthDate.getDate()
|
||||
|
||||
if (months < 0 || (months === 0 && days < 0)) {
|
||||
years--;
|
||||
months += 12;
|
||||
}
|
||||
if (months < 0 || (months === 0 && days < 0)) {
|
||||
years--
|
||||
months += 12
|
||||
}
|
||||
|
||||
if (days < 0) {
|
||||
const prevMonth = new Date(today.getFullYear(), today.getMonth() - 1, 0);
|
||||
days += prevMonth.getDate();
|
||||
months--;
|
||||
}
|
||||
if (days < 0) {
|
||||
const prevMonth = new Date(today.getFullYear(), today.getMonth() - 1, 0)
|
||||
days += prevMonth.getDate()
|
||||
months--
|
||||
}
|
||||
|
||||
// Format the age part
|
||||
let extFormat = '';
|
||||
if ([years, months, days].filter(Boolean).join(' ')) {
|
||||
extFormat = `${years} Tahun ${months} Bulan ${days} Hari`;
|
||||
} else {
|
||||
extFormat = '0';
|
||||
}
|
||||
// Format the age part
|
||||
let extFormat = ''
|
||||
if ([years, months, days].filter(Boolean).join(' ')) {
|
||||
extFormat = `${years} Tahun ${months} Bulan ${days} Hari`
|
||||
} else {
|
||||
extFormat = '0'
|
||||
}
|
||||
|
||||
return {
|
||||
idFormat,
|
||||
extFormat
|
||||
};
|
||||
return {
|
||||
idFormat,
|
||||
extFormat,
|
||||
}
|
||||
}
|
||||
|
||||
// Date selection: default to today - today
|
||||
export function getFormatDateId(date: Date) {
|
||||
const dd = String(date.getDate()).padStart(2, '0')
|
||||
const mm = monthsInId[date.getMonth()]
|
||||
const yyyy = date.getFullYear()
|
||||
return `${dd} ${mm} ${yyyy}`
|
||||
}
|
||||
|
||||
export function formatDateYyyyMmDd(isoDateString: string): string {
|
||||
@@ -49,4 +72,17 @@ export function formatDateYyyyMmDd(isoDateString: string): string {
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if date is invalid (like "0001-01-01T00:00:00Z")
|
||||
export function isValidDate(dateString: string | null | undefined): boolean {
|
||||
if (!dateString) return false
|
||||
// Check for invalid date patterns
|
||||
if (dateString.startsWith('0001-01-01')) return false
|
||||
try {
|
||||
const date = new Date(dateString)
|
||||
return !isNaN(date.getTime())
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* Download data as CSV file.
|
||||
*
|
||||
* @param headers - Array of header names. If omitted and data is array of objects, keys will be taken from first object.
|
||||
* @param data - Array of rows. Each row can be either an object (key -> value) or an array of values.
|
||||
* @param filename - optional file name to use for downloaded file
|
||||
* @param delimiter - csv delimiter (default is comma)
|
||||
* @param addBOM - add UTF-8 BOM to the file to make Excel detect UTF-8 correctly
|
||||
* Usage examples:
|
||||
* 1) With headers and array of objects
|
||||
* downloadCsv(['name', 'age'], [{name: 'Alice', age: 25}, {name: 'Bob', age: 30}], 'people.csv');
|
||||
* 2) Without headers (automatically uses object keys)
|
||||
* downloadCsv(null, [{name: 'Alice', age: 25}, {name: 'Bob', age: 30}], 'people.csv');
|
||||
* 3) With array-of-arrays
|
||||
* downloadCsv(['col1', 'col2'], [['a', 'b'], ['c', 'd']], 'matrix.csv');
|
||||
*/
|
||||
export function downloadCsv(
|
||||
headers: string[] | null,
|
||||
headerLabels: string[],
|
||||
data: Array<Record<string, any> | any[]>,
|
||||
filename = 'data.csv',
|
||||
delimiter = ',',
|
||||
addBOM = true,
|
||||
) {
|
||||
if (!Array.isArray(data) || data.length === 0) {
|
||||
// still create an empty CSV containing only headers
|
||||
const csvHeader = headers ? headers.join(delimiter) : ''
|
||||
const csvString = addBOM ? '\uFEFF' + csvHeader : csvHeader
|
||||
const blob = new Blob([csvString], { type: 'text/csv;charset=utf-8;' })
|
||||
const link = document.createElement('a')
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.setAttribute('download', filename)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
return
|
||||
}
|
||||
|
||||
// if headers not provided and rows are objects, take keys from first object
|
||||
let _headers: string[] | null = headers
|
||||
if (!_headers) {
|
||||
const firstRow = data[0]
|
||||
if (typeof firstRow === 'object' && !Array.isArray(firstRow)) {
|
||||
_headers = Object.keys(firstRow)
|
||||
} else if (Array.isArray(firstRow)) {
|
||||
// if rows are arrays and no headers provided, we won't add header row
|
||||
_headers = null
|
||||
}
|
||||
}
|
||||
|
||||
const escape = (val: unknown) => {
|
||||
if (val === null || typeof val === 'undefined') return ''
|
||||
const str = String(val)
|
||||
const needsQuoting = str.includes(delimiter) || str.includes('\n') || str.includes('\r') || str.includes('"')
|
||||
if (!needsQuoting) return str
|
||||
return '"' + str.replace(/"/g, '""') + '"'
|
||||
}
|
||||
|
||||
const rows: string[] = data.map((row) => {
|
||||
if (Array.isArray(row)) {
|
||||
return row.map(escape).join(delimiter)
|
||||
}
|
||||
// object row - map using headers if available, otherwise use object values
|
||||
if (_headers && Array.isArray(_headers)) {
|
||||
return _headers.map((h) => escape((row as Record<string, any>)[h])).join(delimiter)
|
||||
}
|
||||
return Object.values(row).map(escape).join(delimiter)
|
||||
})
|
||||
|
||||
const headerRow = headerLabels ? headerLabels.join(delimiter) : _headers ? _headers.join(delimiter) : null
|
||||
const csvString = (addBOM ? '\uFEFF' : '') + [headerRow, ...rows].filter(Boolean).join('\r\n')
|
||||
|
||||
const blob = new Blob([csvString], { type: 'text/csv;charset=utf-8;' })
|
||||
const link = document.createElement('a')
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.setAttribute('download', filename)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
/**
|
||||
* Download data as XLS (Excel) file using xlsx library.
|
||||
*
|
||||
* @param headers - Array of header names. If omitted and data is array of objects, keys will be taken from first object.
|
||||
* @param data - Array of rows. Each row can be either an object (key -> value) or an array of values.
|
||||
* @param filename - optional file name to use for downloaded file (default: 'data.xlsx')
|
||||
* @param sheetName - optional sheet name in workbook (default: 'Sheet1')
|
||||
* Usage examples:
|
||||
* 1) With headers and array of objects
|
||||
* await downloadXls(['name', 'age'], [{name: 'Alice', age: 25}, {name: 'Bob', age: 30}], 'people.xlsx');
|
||||
* 2) Without headers (automatically uses object keys)
|
||||
* await downloadXls(null, [{name: 'Alice', age: 25}, {name: 'Bob', age: 30}], 'people.xlsx');
|
||||
* 3) With custom sheet name
|
||||
* await downloadXls(['col1', 'col2'], [['a', 'b'], ['c', 'd']], 'matrix.xlsx', 'MyData');
|
||||
*/
|
||||
export async function downloadXls(
|
||||
headers: string[] | null,
|
||||
headerLabels: string[],
|
||||
data: Array<Record<string, any> | any[]>,
|
||||
filename = 'data.xlsx',
|
||||
sheetName = 'Sheet1',
|
||||
) {
|
||||
// Dynamically import xlsx to avoid server-side issues
|
||||
const { utils, write } = await import('xlsx')
|
||||
const { saveAs } = await import('file-saver')
|
||||
|
||||
if (!Array.isArray(data) || data.length === 0) {
|
||||
// Create empty sheet with headers only
|
||||
const ws = utils.aoa_to_sheet(headers ? [headers] : [[]])
|
||||
const wb = utils.book_new()
|
||||
utils.book_append_sheet(wb, ws, sheetName)
|
||||
const wbout = write(wb, { bookType: 'xlsx', type: 'array' })
|
||||
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), filename)
|
||||
return
|
||||
}
|
||||
|
||||
// if headers not provided and rows are objects, take keys from first object
|
||||
let _headers: string[] | null = headers
|
||||
if (!_headers) {
|
||||
const firstRow = data[0]
|
||||
if (typeof firstRow === 'object' && !Array.isArray(firstRow)) {
|
||||
_headers = Object.keys(firstRow)
|
||||
} else if (Array.isArray(firstRow)) {
|
||||
_headers = null
|
||||
}
|
||||
}
|
||||
|
||||
// Convert data rows to 2D array
|
||||
const rows: any[][] = data.map((row) => {
|
||||
if (Array.isArray(row)) {
|
||||
return row
|
||||
}
|
||||
// object row - map using headers if available, otherwise use object values
|
||||
if (_headers && Array.isArray(_headers)) {
|
||||
return _headers.map((h) => (row as Record<string, any>)[h] ?? '')
|
||||
}
|
||||
return Object.values(row)
|
||||
})
|
||||
|
||||
// Combine headers/labels and rows for sheet
|
||||
// If caller provided headerLabels (as display labels), prefer them.
|
||||
const sheetHeader = headerLabels ? headerLabels : _headers ? _headers : null
|
||||
const sheetData = sheetHeader ? [sheetHeader, ...rows] : rows
|
||||
|
||||
// Create worksheet and workbook
|
||||
const ws = utils.aoa_to_sheet(sheetData)
|
||||
const wb = utils.book_new()
|
||||
utils.book_append_sheet(wb, ws, sheetName)
|
||||
|
||||
// Write and save file
|
||||
const wbout = write(wb, { bookType: 'xlsx', type: 'array' })
|
||||
saveAs(new Blob([wbout], { type: 'application/octet-stream' }), filename)
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
export type QueueStatusCode = 'wait' | 'proc' | 'done' | 'cancel' | 'skip'
|
||||
export type EncounterClassCode = 'ambulatory' | 'emergency' | 'inpatient'
|
||||
export type DischargeMethodCode = 'home' | 'home-request' | 'consul-back' | 'consul-poly' | 'consul-executive' | 'consul-ch-day' | 'emergency' | 'emergency-covid' | 'inpatient' | 'external' | 'death' | 'death-on-arrival' | 'run-away'
|
||||
export type PolySwitchCode = 'consul-poly' | 'consul-executive'
|
||||
export type RefTypeCode = 'none' | 'gov' | 'private' | 'bpjs'
|
||||
export type TransportationCode = 'ambulance' | 'car' | 'motor-cycle' | 'other'
|
||||
export type PersonConditionCode = 'res' | 'emg' | 'urg' | 'lurg' | 'nurg' | 'doa'
|
||||
export type AmbulatoryClassCode = 'reg' | 'rehab' | 'chemo'
|
||||
export type EmergencyClassCode = 'emg' | 'eon'
|
||||
export type InpatientClassCode = 'op' | 'icu' | 'hcu' | 'vk'
|
||||
export type ChemoClassCode = 'adm' | 'act'
|
||||
export type AmbulanceFacilityCode = 'std' | 'icu'
|
||||
export type AmbulanceNeedsCode = 'assist' | 'non-assist'
|
||||
export type DocTypeCode = 'person-resident-number' | 'person-driving-license' | 'person-passport' | 'person-family-card' | 'encounter-patient' | 'encounter-suport' | 'encounter-other' | 'mcu-item-result' | 'vclaim-sep' | 'vclaim-sipp' | 'general-consent'
|
||||
export type AltPaymentMethodCode = 'jkn' | 'jkmm' | 'spm' | 'pks' | 'umum'
|
||||
export type SEPRefTypCode = 'internal' | 'external'
|
||||
export type VisitModeCode = 'adm' | 'readm' | 'series'
|
||||
|
||||
export const queueStatusCodes: Record<QueueStatusCode, string> = {
|
||||
wait: 'Tunggu',
|
||||
proc: 'Proses',
|
||||
done: 'Selesai',
|
||||
cancel: 'Batal',
|
||||
skip: 'Dilewati',
|
||||
}
|
||||
|
||||
export const encounterClassCodes: Record<EncounterClassCode, string> = {
|
||||
ambulatory: 'Rawat Jalan',
|
||||
emergency: 'Gawat Darurat',
|
||||
inpatient: 'Rawat Inap',
|
||||
}
|
||||
|
||||
export const dischageMethodCodes: Record<DischargeMethodCode, string> = {
|
||||
home: 'Pulang',
|
||||
'home-request': 'Pulang Atas Permintaan Sendiri',
|
||||
'consul-back': 'Konsultasi Balik / Lanjutan',
|
||||
'consul-poly': 'Konsultasi Poliklinik Lain',
|
||||
'consul-executive': 'Konsultasi Antar Dokter Eksekutif',
|
||||
'consul-ch-day': 'Konsultasi Hari Lain',
|
||||
emergency: 'Rujuk IGD',
|
||||
'emergency-covid': 'Rujuk IGD Covid',
|
||||
inpatient: 'Rujuk Rawat Inap',
|
||||
external: 'Rujuk Faskes Lain',
|
||||
death: 'Meninggal',
|
||||
'death-on-arrival': 'Meninggal Saat Tiba',
|
||||
'run-away': 'Kabur / Lari',
|
||||
}
|
||||
|
||||
export const polySwitchCode: Record<PolySwitchCode, string> = {
|
||||
'consul-poly': 'Konsultasi Poliklinik Lain',
|
||||
'consul-executive': 'Konsultasi Antar Dokter Eksekutif',
|
||||
}
|
||||
|
||||
export const refTypeCode: Record<RefTypeCode, string> = {
|
||||
none: 'Tidak Ada',
|
||||
gov: 'Pemerintah',
|
||||
private: 'Swasta',
|
||||
bpjs: 'BPJS',
|
||||
}
|
||||
|
||||
export const transportationCode: Record<TransportationCode, string> = {
|
||||
ambulance: 'Ambulans',
|
||||
car: 'Mobil',
|
||||
'motor-cycle': 'Motor',
|
||||
other: 'Lainnya',
|
||||
}
|
||||
|
||||
export const personConditionCode: Record<PersonConditionCode, string> = {
|
||||
res: 'Resutiasi',
|
||||
emg: 'Darurat',
|
||||
urg: 'Mendesak',
|
||||
lurg: 'Kurang Mendesak',
|
||||
nurg: 'Mendesak',
|
||||
doa: 'Meninggal Saat Tiba',
|
||||
}
|
||||
|
||||
export const ambulatoryClassCode: Record<AmbulatoryClassCode, string> = {
|
||||
reg: 'Reguler',
|
||||
rehab: 'Rehab Medik',
|
||||
chemo: 'Kemoterapi',
|
||||
}
|
||||
|
||||
export const emergencyClassCode: Record<EmergencyClassCode, string> = {
|
||||
emg: 'Darurat',
|
||||
eon: 'Ponek',
|
||||
}
|
||||
|
||||
export const inpatientClassCode: Record<InpatientClassCode, string> = {
|
||||
op: 'Rawat Inap',
|
||||
icu: 'ICU',
|
||||
hcu: 'HCU',
|
||||
vk: 'Kamar Bersalin',
|
||||
}
|
||||
|
||||
export const chemoClassCode: Record<ChemoClassCode, string> = {
|
||||
adm: 'Administrasi',
|
||||
act: 'Tindakan',
|
||||
}
|
||||
|
||||
export const ambulanceFacilityCode: Record<AmbulanceFacilityCode, string> = {
|
||||
std: 'Standar',
|
||||
icu: 'ICU',
|
||||
}
|
||||
|
||||
export const ambulanceNeedsCode: Record<AmbulanceNeedsCode, string> = {
|
||||
assist: 'Dengan Pendampingan',
|
||||
'non-assist': 'Tanpa Pendampingan',
|
||||
}
|
||||
|
||||
export const docTypeCode: Record<DocTypeCode, string> = {
|
||||
'person-resident-number': '',
|
||||
'person-driving-license': '',
|
||||
'person-passport': '',
|
||||
'person-family-card': '',
|
||||
'encounter-patient': '',
|
||||
'encounter-suport': '',
|
||||
'encounter-other': '',
|
||||
'mcu-item-result': '',
|
||||
'vclaim-sep': '',
|
||||
'vclaim-sipp': '',
|
||||
'general-consent': '',
|
||||
}
|
||||
|
||||
export const altPaymentMethodCode: Record<AltPaymentMethodCode, string> = {
|
||||
jkn: 'JKN',
|
||||
jkmm: 'JKMM',
|
||||
spm: 'SPM',
|
||||
pks: 'PKS',
|
||||
umum: 'Umum',
|
||||
}
|
||||
|
||||
export const sepRefTypCode: Record<SEPRefTypCode, string> = {
|
||||
internal: 'Rujukan Internal',
|
||||
external: 'Faskes Lain',
|
||||
}
|
||||
|
||||
export const visitModeCode: Record<VisitModeCode, string> = {
|
||||
adm: 'Administrasi',
|
||||
readm: 'Administrasi',
|
||||
series: 'Tindakan',
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
export type InfragroupCode = 'building' | 'floor' | 'warehouse' | 'room' | 'chamber' | 'bed' | 'counter' | 'public-screen'
|
||||
export type ItemGroupCode = 'infra' | 'medicine' | 'device' | 'material' | 'employee-fee' | 'doctor-fee'
|
||||
export type UnitTypeCode = 'reg' | 'exa' | 'pay' | 'pha' | 'lab' | 'rad'
|
||||
export type ContractStatusCode = 'system' | 'employee' | 'intern' | 'other'
|
||||
export type EmployeePositionCode = 'reg' | 'nur' | 'doc' | 'miw' | 'thr' | 'nut' | 'lab' | 'pha' | 'nom'
|
||||
export type InternPositionCode = 'specialist' | 'nurse' | 'non-medic'
|
||||
export type DoctorFeeTypeCodes = 'outpatient' | 'emergency' | 'inpatient' | 'medic-rehab'
|
||||
|
||||
export const infragroupCodes: Record<InfragroupCode, string> = {
|
||||
building: 'Bangunan',
|
||||
floor: 'Lantai',
|
||||
warehouse: 'Gudang / Depo',
|
||||
room: 'Ruang',
|
||||
chamber: 'Kamar',
|
||||
bed: 'Ranjang',
|
||||
counter: 'Counter',
|
||||
'public-screen': 'Public Screen',
|
||||
}
|
||||
|
||||
export const itemGroupCodes: Record<ItemGroupCode, string> = {
|
||||
infra: 'Infrastruktur',
|
||||
medicine: 'Obat',
|
||||
device: 'Peralatan',
|
||||
material: 'Perlengkapan',
|
||||
'employee-fee': 'Gaji Karyawan',
|
||||
'doctor-fee': 'Gaji Dokter',
|
||||
}
|
||||
|
||||
export const unitTypeCodes: Record<UnitTypeCode, string> = {
|
||||
reg: 'Registrasi',
|
||||
exa: 'Pemeriksaan',
|
||||
pay: 'Pembayaran',
|
||||
pha: 'Farmasai',
|
||||
lab: 'Laboratorium',
|
||||
rad: 'Radiologi',
|
||||
}
|
||||
|
||||
export const contractStatusCodes: Record<ContractStatusCode, string> = {
|
||||
system: 'Sistem',
|
||||
employee: 'Pegawai',
|
||||
intern: 'Magang',
|
||||
other: 'Lainnya',
|
||||
}
|
||||
|
||||
export const employeePositionCodes: Record<EmployeePositionCode, string> = {
|
||||
reg: 'Admisi / Pendaftaran',
|
||||
nur: 'Perawat',
|
||||
doc: 'Dokter',
|
||||
miw: 'Bidan',
|
||||
thr: 'Terapis',
|
||||
nut: 'Ahli Gisi',
|
||||
lab: 'Laboran',
|
||||
pha: 'Farmasi',
|
||||
nom: 'Non Medis',
|
||||
}
|
||||
|
||||
export const internPositionCodes: Record<InternPositionCode, string> = {
|
||||
specialist: 'PPDS',
|
||||
nurse: 'Perawat',
|
||||
'non-medic': 'Non Medis',
|
||||
}
|
||||
|
||||
export const doctorFeeTypeCodes: Record<DoctorFeeTypeCodes, string> = {
|
||||
outpatient: 'Rawat Jalan',
|
||||
emergency: 'Darurat',
|
||||
inpatient: 'Rawat Inap',
|
||||
'medic-rehab': 'Rehab Medik',
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { RoleAccess } from '~/models/role'
|
||||
|
||||
export const PAGE_PERMISSIONS = {
|
||||
'/patient': {
|
||||
'/client/patient': {
|
||||
'emp|doc': ['R'],
|
||||
'emp|nur': ['R'],
|
||||
'emp|reg': ['C', 'R', 'U', 'D'],
|
||||
@@ -9,13 +9,11 @@ export const PAGE_PERMISSIONS = {
|
||||
'emp|pay': ['R'],
|
||||
'emp|mng': ['R'],
|
||||
},
|
||||
'/doctor': {
|
||||
'emp|doc': ['C', 'R', 'U', 'D'],
|
||||
'emp|nur': ['R'],
|
||||
'emp|reg': ['R'],
|
||||
'emp|pha': ['R'],
|
||||
'emp|pay': ['R'],
|
||||
'emp|mng': ['R'],
|
||||
'/human-src/employee': {
|
||||
'div|hrd': ['C', 'R', 'U', 'D'],
|
||||
},
|
||||
'/human-src/intern': {
|
||||
'div|hrd': ['C', 'R', 'U', 'D'],
|
||||
},
|
||||
'/satusehat': {
|
||||
'emp|doc': ['R'],
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
export type GenderCode = 'male' | 'female' | 'not-stated' | 'unknown'
|
||||
export type ReligionCode = 'islam' | 'protestan' | 'katolik' | 'hindu' | 'buda' | 'konghucu'
|
||||
export type EducationCode = 'TS' | 'TK' | 'SD' | 'SMP' | 'SMA' | 'D1' | 'D2' | 'D3' | 'S1' | 'S2' | 'S3'
|
||||
export type OccupationCode = 'tidak-bekerja' | 'pns' | 'polisi' | 'tni' | 'guru' | 'wiraswasta' | 'kary-swasta' | 'lainnya'
|
||||
export type AddressLocationTypeCode = 'identity' | 'domicile'
|
||||
export type PersonContactType = 'phone' | 'm-phone' | 'email' | 'fax'
|
||||
export type RelationshipCode = 'mother' | 'father' | 'uncle' | 'aunt' | 'sibling' | 'gd-mother' | 'gd-father' | 'child' | 'nephew' | 'gd-child' | 'friend' | 'spouse' | 'self' | 'other'
|
||||
export type MaritalStatus_Code = 'S' | 'M' | 'D' | 'W'
|
||||
|
||||
export const genderCodes: Record<GenderCode, string> = {
|
||||
male: 'Laki',
|
||||
female: 'Perempuan',
|
||||
'not-stated': 'Tidak Disebutkan',
|
||||
unknown: 'Tidak Diketahui',
|
||||
}
|
||||
|
||||
export const religionCodes: Record<ReligionCode, string> = {
|
||||
islam: 'Islam',
|
||||
protestan: 'Protestan',
|
||||
katolik: 'Katolik',
|
||||
hindu: 'Hindu',
|
||||
buda: 'Buda',
|
||||
konghucu: 'Konghucu',
|
||||
}
|
||||
|
||||
export const educationCodes: Record<EducationCode, string> = {
|
||||
TS: 'TS',
|
||||
TK: 'TK',
|
||||
SD: 'SD',
|
||||
SMP: 'SMP',
|
||||
SMA: 'SMA',
|
||||
D1: 'D1',
|
||||
D2: 'D2',
|
||||
D3: 'D3',
|
||||
S1: 'S1',
|
||||
S2: 'S2',
|
||||
S3: 'S3',
|
||||
}
|
||||
|
||||
export const occupationCodes: Record<OccupationCode, string> = {
|
||||
'tidak-bekerja': 'Tidak Bekerja',
|
||||
pns: 'Pegawai Negeri Sipil',
|
||||
polisi: 'Polisi',
|
||||
tni: 'TNI',
|
||||
guru: 'Guru',
|
||||
wiraswasta: 'Wiraswasta',
|
||||
'kary-swasta': 'Karyawan Swasta',
|
||||
lainnya: 'Lainnya',
|
||||
}
|
||||
|
||||
export const personContactTypes: Record<PersonContactType, string> = {
|
||||
phone: 'Telepon',
|
||||
'm-phone': 'HP / Ponsel',
|
||||
email: 'Email',
|
||||
fax: 'Fax',
|
||||
}
|
||||
|
||||
export const relationshipCodes: Record<RelationshipCode, string> = {
|
||||
mother: 'Ibu',
|
||||
father: 'Ayah',
|
||||
uncle: 'Paman',
|
||||
aunt: 'Bibi',
|
||||
sibling: 'Saudara',
|
||||
'gd-mother': 'Nenek',
|
||||
'gd-father': 'Kakek',
|
||||
child: 'Anak',
|
||||
nephew: 'Keponakan',
|
||||
'gd-child': 'Cucu',
|
||||
friend: 'Teman',
|
||||
spouse: 'Pasangan (Suami / Istri)',
|
||||
self: 'Diri sendiri',
|
||||
other: 'Lainnya',
|
||||
}
|
||||
|
||||
export const maritalStatusCodes: Record<MaritalStatus_Code, string> = {
|
||||
S: 'Single (Belum Kawin)',
|
||||
M: 'Married (Kawin)',
|
||||
D: 'Divorced (Cerai Hidup)',
|
||||
W: 'Widowed (Cerai Mati)',
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { medicalRoles, respPosCode } from '~/const/common/role'
|
||||
|
||||
export function getServicePosition(role?: string): string {
|
||||
if(!role) {
|
||||
return 'none'
|
||||
}
|
||||
if (medicalRoles.includes(role)) {
|
||||
return 'medical'
|
||||
} else if (role === 'emp|reg') {
|
||||
return 'registration'
|
||||
} else if (role.includes('|resp')) {
|
||||
return 'verificator'
|
||||
} else {
|
||||
return 'none'
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user