import Styles from "@/constants/Styles"; import { useTheme } from "@/providers/ThemeProvider"; import { MaterialCommunityIcons } from "@expo/vector-icons"; import { useState } from "react"; import { LayoutChangeEvent, Pressable, View } from "react-native"; import Text from "./Text"; type FileItem = { name: string extension: string } type Props = { status?: number // 0=belum selesai, 1=selesai, 2=menunggu persetujuan title: string dateStart: string dateEnd: string files?: FileItem[] onPress?: () => void } const CHAR_W = 6.5 const ICON_W = 17 const PAD_H = 16 const GAP = 6 const PLUS_W = 72 function estimateChipWidth(label: string) { return PAD_H + ICON_W + label.length * CHAR_W } function getVisibleChips(files: FileItem[], containerWidth: number) { if (containerWidth === 0) return { visible: [], extra: files.length } let used = 0 const visible: FileItem[] = [] for (let i = 0; i < files.length; i++) { const label = `${files[i].name}.${files[i].extension}` const chipW = estimateChipWidth(label) const isLast = i === files.length - 1 const plusChipW = isLast ? 0 : PLUS_W + GAP const gapW = visible.length > 0 ? GAP : 0 if (used + gapW + chipW + plusChipW <= containerWidth) { visible.push(files[i]) used += gapW + chipW } else { break } } return { visible, extra: files.length - visible.length } } function getFileIcon(extension: string): keyof typeof MaterialCommunityIcons.glyphMap { const ext = extension.toLowerCase() if (['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic', 'heif'].includes(ext)) return 'image-outline' if (ext === 'pdf') return 'file-pdf-box' if (['mp4', 'mov', 'avi', 'mkv'].includes(ext)) return 'video-outline' if (['doc', 'docx'].includes(ext)) return 'file-word-outline' if (['xls', 'xlsx'].includes(ext)) return 'file-excel-outline' if (['zip', 'rar', '7z'].includes(ext)) return 'zip-box-outline' return 'file-outline' } const AMBER = '#FFA94D' function getStatusStyle(status: number | undefined, successColor: string, dimmed: string) { if (status === 1) return { accent: successColor, badge: successColor + '25', text: successColor, label: 'Selesai' } if (status === 2) return { accent: AMBER, badge: AMBER + '25', text: AMBER, label: 'Menunggu Persetujuan' } return { accent: dimmed + '80', badge: dimmed + '18', text: dimmed, label: 'Belum Selesai' } } export default function ItemSectionTanggalTugas({ status, title, dateStart, dateEnd, files = [], onPress }: Props) { const { colors, activeTheme } = useTheme() const [containerWidth, setContainerWidth] = useState(0) const { visible, extra } = getVisibleChips(files, containerWidth) function onChipsLayout(e: LayoutChangeEvent) { const w = e.nativeEvent.layout.width if (w !== containerWidth) setContainerWidth(w) } const dimmed = colors.dimmed.slice(0, 7) const successColor = activeTheme === 'dark' ? '#51CF66' : colors.success const statusStyle = getStatusStyle(status, successColor, dimmed) return ( {/* Accent bar kiri */} {status !== undefined && ( )} {/* Konten */} {/* Judul + badge status */} {title} {status !== undefined && ( {statusStyle.label} )} {/* Tanggal */} 0 ? 8 : 0 }}> {dateStart} {dateEnd} {/* Chips lampiran */} {files.length > 0 && ( {visible.map((file, index) => { const label = `${file.name}.${file.extension}` const chipW = Math.min(estimateChipWidth(label), containerWidth * 0.55) return ( {label} ) })} {extra > 0 && ( +{extra} lainnya )} )} ) }