feat: tambah fitur kalender umum village dengan indikator per jenis event

- Tambah halaman /village-calendar dengan monthly grid dan agenda view
- Tampilkan acara divisi (DivisionCalendarReminder) dan kegiatan (ProjectTask) se-village
- Indikator dot dua warna pada kalender: ungu untuk acara divisi, biru-abu untuk kegiatan
- Tambah endpoint apiGetVillageCalendarByDate dan apiGetVillageCalendarIndicator
- Tambah menu Kalender di halaman /feature dengan grid layout flexWrap
- Sesuaikan warna EventItem dengan TYPE_COLORS village-calendar
- Pindahkan inline style ke Styles.ts sebagai class baru
This commit is contained in:
2026-05-11 15:19:21 +08:00
parent 74d8b8ef31
commit 84935e8188
7 changed files with 362 additions and 19 deletions

View File

@@ -14,11 +14,11 @@ export function ButtonFiturMenu({ onPress, icon, text }: Props) {
const { colors } = useTheme();
return (
<TouchableWithoutFeedback onPress={onPress}>
<View style={{ alignItems: 'center' }}>
<View style={{ alignItems: 'center', width: '25%' }}>
<View style={[Styles.btnFiturMenu, { backgroundColor: colors.card, borderColor: colors.icon + '20', shadowColor: colors.text }]}>
{icon}
</View>
<Text style={[Styles.mt05, { color: colors.text }]}>{text}</Text>
<Text style={[Styles.mt05, { color: colors.text, textAlign: 'center', fontSize: 12 }]}>{text}</Text>
</View>
</TouchableWithoutFeedback>
)

View File

@@ -6,19 +6,28 @@ import Text from "../Text";
type Props = {
text: string;
isSelected: boolean;
isSign: boolean;
isSign?: boolean;
isSignCalendar?: boolean;
isSignTask?: boolean;
onPress?: () => void;
}
export default function ItemDateCalendar({ text, isSelected, isSign, onPress }: Props) {
export default function ItemDateCalendar({ text, isSelected, isSign, isSignCalendar, isSignTask, onPress }: Props) {
const { colors } = useTheme()
const showMulti = isSignCalendar !== undefined || isSignTask !== undefined;
return (
<>
<Pressable style={{ alignItems: 'center' }} onPress={onPress}>
<Text style={[isSelected ? Styles.cWhite : { color: colors.text }]}>{text}</Text>
<View style={[Styles.signDate, { backgroundColor: isSign ? 'red' : 'transparent' }]}></View>
</Pressable>
</>
<Pressable style={Styles.contentItemCenter} onPress={onPress}>
<Text style={[isSelected ? Styles.cWhite : { color: colors.text }]}>{text}</Text>
{showMulti ? (
<View style={Styles.calendarDotRow}>
<View style={[Styles.calendarDot, { backgroundColor: isSignCalendar ? (isSelected ? 'white' : '#7886C7') : 'transparent' }]} />
<View style={[Styles.calendarDot, { backgroundColor: isSignTask ? (isSelected ? 'white' : '#94B4C1') : 'transparent' }]} />
</View>
) : (
<View style={[Styles.signDate, { backgroundColor: isSign ? 'red' : 'transparent' }]} />
)}
</Pressable>
)
}

View File

@@ -17,16 +17,16 @@ export default function EventItem({ category, title, user, jamAwal, jamAkhir, on
const getBackgroundColor = (cat: 'purple' | 'orange') => {
if (activeTheme === 'dark') {
return cat === 'orange' ? '#547792' : '#1D546D';
return cat === 'purple' ? '#2D2B5E' : '#1C3347';
}
return cat === 'orange' ? '#D6E6F2' : '#A9B5DF';
return cat === 'purple' ? '#A9B5DF' : '#D6E6F2';
};
const getStickColor = (cat: 'purple' | 'orange') => {
if (activeTheme === 'dark') {
return cat === 'orange' ? '#94B4C1' : '#5F9598';
return cat === 'purple' ? '#7886C7' : '#94B4C1';
}
return cat === 'orange' ? '#F5F5F5' : '#7886C7';
return cat === 'purple' ? '#7886C7' : '#94B4C1';
};
return (