first commit

This commit is contained in:
2025-04-22 10:56:56 +07:00
commit af123c091b
147 changed files with 778063 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
import { type Period, isPeriodActive } from './periodUtils'
interface ContactPoint {
system?: String
use?: String
rank?: Number
period?: Period
value?: String
}
export function getContactPoints(
contact: ContactPoint[],
system: 'phone' | 'email' | 'url' | 'fax' | 'pager' | 'sms' | 'other',
): String[] {
if (!contact || contact.length === 0) {
return []
}
// Filter contact points by the specified system
const filteredBySystem = contact.filter((cp) => cp.system === system)
if (filteredBySystem.length === 0) {
return []
}
// Filter active contact points using the exported function
const activeContactPoints = filteredBySystem.filter((cp) =>
isPeriodActive(cp.period),
)
let sortedContactPoints: ContactPoint[]
if (activeContactPoints.length > 0) {
// Sort active contact points by rank (lower rank is preferred)
activeContactPoints.sort(
(a, b) => (a.rank || Infinity) - (b.rank || Infinity),
)
sortedContactPoints = activeContactPoints
} else {
// If no active contact points, return all contact points for the system sorted by rank
filteredBySystem.sort((a, b) => (a.rank || Infinity) - (b.rank || Infinity))
sortedContactPoints = filteredBySystem
}
// Map the sorted ContactPoint array to an array of their 'value' properties
return sortedContactPoints.map((cp) => cp.value || '')
}

49
utils/formatDate.ts Normal file
View File

@@ -0,0 +1,49 @@
export function formatDate(
date: Date | string | number | null | undefined,
option:
| 'full'
| 'long'
| 'medium'
| 'short'
| 'numeric'
| 'yearMonth'
| 'dayMonth'
| 'time'
| Intl.DateTimeFormatOptions,
): string {
if (!date) {
return 'Tidak ada data tanggal'
}
const listOptions: { [key: string]: Intl.DateTimeFormatOptions } = {
full: { day: 'numeric', month: 'long', year: 'numeric' },
long: { day: 'numeric', month: 'long', year: 'numeric' }, // Mirip 'full' tapi bisa disesuaikan
medium: { day: 'numeric', month: 'short', year: 'numeric' },
short: { day: '2-digit', month: '2-digit', year: '2-digit' },
numeric: { day: 'numeric', month: 'numeric', year: 'numeric' },
yearMonth: { month: 'long', year: 'numeric' },
dayMonth: { day: 'numeric', month: 'long' },
time: { hour: 'numeric', minute: 'numeric', second: 'numeric' },
}
let options: Intl.DateTimeFormatOptions | undefined
if (typeof option === 'string' && listOptions[option]) {
options = listOptions[option]
} else if (typeof option === 'object' && option !== null) {
options = option // Menggunakan opsi yang diberikan langsung
} else {
console.warn(
`Opsi format tanggal "${option}" tidak valid. Menggunakan format 'full' sebagai default.`,
)
options = listOptions.full
}
try {
const dateObject = new Date(date)
return dateObject.toLocaleDateString('id-ID', options)
} catch (error) {
console.error('Gagal memformat tanggal:', error)
return 'Format tanggal tidak valid'
}
}

53
utils/helper.ts Normal file
View File

@@ -0,0 +1,53 @@
export function generateRandomDataPasien(count) {
const baseData = [
{ index: '1', norm: '001', nama: 'firman', tgl_lahir: '2022-08-03', alamat: 'jombang', no_ktp: '01354581564', no_jkn: '32656265', jk: 'L' },
{ index: '2', norm: '002', nama: 'andi', tgl_lahir: '2023-02-03', alamat: 'surabaya', no_ktp: '3453783543', no_jkn: '534535463', jk: 'L' },
{ index: '3', norm: '003', nama: 'budi', tgl_lahir: '2023-03-03', alamat: 'malang', no_ktp: '3453785254637', no_jkn: '247463735', jk: 'L' },
{ index: '4', norm: '004', nama: 'dwi', tgl_lahir: '2022-04-03', alamat: 'malang', no_ktp: '01354581564', no_jkn: '34876355', jk: 'P' },
{ index: '5', norm: '005', nama: 'bayu', tgl_lahir: '2021-07-03', alamat: 'sidoarjo', no_ktp: '34537853245', no_jkn: '453786978', jk: 'L' },
{ index: '6', norm: '006', nama: 'nita', tgl_lahir: '2021-02-03', alamat: 'pasuruan', no_ktp: '3543758524', no_jkn: '35437865', jk: 'P' },
{ index: '7', norm: '007', nama: 'bagus', tgl_lahir: '2021-02-03', alamat: 'pasuruan', no_ktp: '3543758524', no_jkn: '35437865', jk: 'L' },
];
const randomData = [];
for (let i = 0; i < count; i++) {
const randomIndex = Math.floor(Math.random() * baseData.length);
const randomEntry = { ...baseData[randomIndex], norm: String(i + 1).padStart(3, '0') };
randomData.push(randomEntry);
}
return randomData;
}
export function generateRandomListKunjungan(count) {
const baseData = [
{ index: '1', norm: '001', nama: 'firman', tgl_kunjungan: '2022-08-03', caraBayar: 'JKN', alamat: 'jombang', noBilling: '01354581564', no_jkn: '32656265', jk: 'L', klinik: 'IGD - P1', dokter: 'dr.ANDHIKA YUDISTIRA,Sp.OT' },
{ index: '2', norm: '002', nama: 'andi', tgl_kunjungan: '2023-02-03', caraBayar: 'Umum', alamat: 'surabaya', noBilling: '3453783543', no_jkn: '534535463', jk: 'L', klinik: 'IGD - P2', dokter: 'dr.ANDHIKA YUDISTIRA,Sp.OT' },
{ index: '3', norm: '003', nama: 'budi', tgl_kunjungan: '2023-03-03', caraBayar: 'JKN', alamat: 'malang', noBilling: '3453785254637', no_jkn: '247463735', jk: 'L', klinik: 'IGD - P1', dokter: 'dr.YUDDY IMOWANTO,Sp.EM,KEC' },
{ index: '4', norm: '004', nama: 'dwi', tgl_kunjungan: '2022-04-03', caraBayar: 'Umum', alamat: 'malang', noBilling: '01354581564', no_jkn: '34876355', jk: 'P', klinik: 'IGD - P3', dokter: 'dr.SHINTA OKTYA WARDHANI,Sp.PD' },
{ index: '5', norm: '005', nama: 'bayu', tgl_kunjungan: '2021-07-03', caraBayar: 'Umum', alamat: 'sidoarjo', noBilling: '34537853245', no_jkn: '453786978', jk: 'L', klinik: 'IGD - P3', dokter: 'dr.ANDHIKA YUDISTIRA,Sp.OT' },
{ index: '6', norm: '006', nama: 'nita', tgl_kunjungan: '2021-02-03', caraBayar: 'JKN', alamat: 'pasuruan', noBilling: '3543758524', no_jkn: '35437865', jk: 'P', klinik: 'IGD - P1', dokter: 'dr.ANDHIKA YUDISTIRA,Sp.OT' },
{ index: '7', norm: '007', nama: 'bagus', tgl_kunjungan: '2021-02-03', caraBayar: 'Umum', alamat: 'pasuruan', noBilling: '3543758524', no_jkn: '35437865', jk: 'L', klinik: 'IGD - P2', dokter: 'dr.TAUFIQ ABDULLAH,Sp.EM,KTox' },
];
const randomData = [];
for (let i = 0; i < count; i++) {
const randomIndex = Math.floor(Math.random() * baseData.length);
// const randomEntry = { ...baseData[randomIndex], index: String(i + 1) }; // Menggunakan index dari loop
const randomEntry = { ...baseData[randomIndex], index: String(i + 1).padStart(3, '0') };
randomData.push(randomEntry);
}
return randomData;
}
// ______________________________________________________________________________________________
export function formatDate(date) {
const options = { year: 'numeric', month: 'long', day: 'numeric', locale: 'id-ID' };
return new Date(date).toLocaleDateString('id-ID', options);
}
export function capitalizeEachWord(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

30
utils/joinName.ts Normal file
View File

@@ -0,0 +1,30 @@
interface ParsedName {
use?: string
family?: string
given?: string[]
prefix?: string[]
suffix?: string[]
}
function safeJoin(arr: string[]) {
return arr?.length > 0 ? arr.join(' ') + ' ' : ''
}
export function joinName(
names?: ParsedName[],
use: String[] = ['official'],
): String {
if (!names || names.length === 0) {
return 'Nama tidak tersedia'
}
const usedName = names.filter((name) => name && use.includes(name.use))[0]
let name = ''
name += usedName?.prefix?.length > 0 ? usedName.prefix.join(' ') + ' ' : ''
name += usedName?.given?.length > 0 ? usedName.given.join(' ') + ' ' : ''
name += usedName?.family ?? ''
name += usedName?.suffix?.length > 0 ? ' ' + usedName.suffix.join(' ') : ''
return name.trim() || usedName?.text || 'Nama tidak tersedia'
}

62
utils/parseName.ts Normal file
View File

@@ -0,0 +1,62 @@
interface ParsedName {
family?: string
given?: string[]
prefix?: string[]
suffix?: string[]
}
export function parseName(fullName?: string): ParsedName {
let prefix: string[] = []
let suffix: string[] = []
let given: string[] = []
let family: string | null = null
const result: ParsedName = {}
if (fullName === undefined) {
return result
}
const parts = fullName.trim().split(/\s+/)
// Cek awalan (prefix)
while (
parts.length > 0 &&
(parts[0].includes('.') || parts[0].includes(','))
) {
prefix.push(parts.shift()!)
}
// Cek akhiran (suffix)
while (parts.length > 0 && parts[parts.length - 1].includes('.')) {
suffix.push(parts.pop()!)
}
if (parts.length === 1) {
given.push(parts[0].toLowerCase().replace(/\b\w/g, (s) => s.toUpperCase()))
} else if (parts.length > 1) {
family = parts
.pop()!
.toLowerCase()
.replace(/\b\w/g, (s) => s.toUpperCase())
for (let i = 0; i < parts.length; i++) {
given.push(
parts[i].toLowerCase().replace(/\b\w/g, (s) => s.toUpperCase()),
)
}
}
if (family) {
result.family = family
}
if (given.length > 0) {
result.given = given
}
if (prefix.length > 0) {
result.prefix = prefix
}
if (suffix.length > 0) {
result.suffix = suffix.reverse()
}
return result
}

16
utils/periodUtils.ts Normal file
View File

@@ -0,0 +1,16 @@
export interface Period {
start?: Date
end?: Date
}
export function isPeriodActive(period?: Period): boolean {
if (!period) return true // No period means always active
const now = new Date()
const start = period.start ? new Date(period.start) : null
const end = period.end ? new Date(period.end) : null
const isAfterStart = !start || now >= start
const isBeforeEnd = !end || now <= end
return isAfterStart && isBeforeEnd
}

18
utils/switchCase.ts Normal file
View File

@@ -0,0 +1,18 @@
export function switchCase<T extends Record<string, any>, K extends keyof T>(
data: T | null | undefined,
select?: K,
): T[K] | string {
if (!data) {
return 'Tidak ada data'
}
const key: K | 'default' = select !== undefined ? select : ('default' as K) // Type assertion needed here
if (key in data) {
return data[key]
} else if ('default' in data) {
return data['default']
} else {
return 'Data tidak ditemukan'
}
}