diff --git a/app/(application)/search.tsx b/app/(application)/search.tsx
index 6541b76..3f418f2 100644
--- a/app/(application)/search.tsx
+++ b/app/(application)/search.tsx
@@ -9,13 +9,12 @@ import Styles from "@/constants/Styles";
import { apiGetSearch } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
-import { AntDesign, MaterialIcons } from "@expo/vector-icons";
+import { AntDesign, Feather, MaterialIcons } from "@expo/vector-icons";
import { router, Stack } from "expo-router";
import React, { useState } from "react";
-import { RefreshControl, SafeAreaView, ScrollView, View } from "react-native";
+import { RefreshControl, SafeAreaView, ScrollView, TouchableOpacity, View } from "react-native";
import Toast from "react-native-toast-message";
-// ... types ...
type PropsUser = {
id: string
name: string
@@ -38,6 +37,27 @@ type PropDivisi = {
group: string
}
+type FilterType = "all" | "member" | "division" | "project"
+
+function SectionHeader({ label, count, colors }: { label: string; count: number; colors: any }) {
+ return (
+
+
+ {label}
+
+
+ {count}
+
+
+ )
+}
+
export default function Search() {
const { token, decryptToken } = useAuthSession()
const [dataUser, setDataUser] = useState([])
@@ -45,11 +65,16 @@ export default function Search() {
const [dataProject, setDataProject] = useState([])
const [refreshing, setRefreshing] = useState(false)
const [search, setSearch] = useState('')
+ const [activeFilter, setActiveFilter] = useState("all")
const { colors } = useTheme();
+ const totalResults = dataUser.length + dataDivisi.length + dataProject.length
+ const hasSearch = search.length >= 3
+
async function handleSearch(cari: string) {
try {
setSearch(cari)
+ setActiveFilter("all")
if (cari.length >= 3) {
const user = await decryptToken(String(token?.current))
const hasil = await apiGetSearch({ text: cari, user: user })
@@ -58,7 +83,7 @@ export default function Search() {
setDataDivisi(hasil.data.division)
setDataProject(hasil.data.project)
} else {
- return Toast.show({ type: 'small', text1: hasil.message, })
+ return Toast.show({ type: 'small', text1: hasil.message })
}
} else {
setDataUser([])
@@ -68,15 +93,10 @@ export default function Search() {
} catch (error: any) {
console.error(error);
const message = error?.response?.data?.message || "Gagal melakukan pencarian"
-
- Toast.show({
- type: 'small',
- text1: message
- })
+ Toast.show({ type: 'small', text1: message })
}
}
-
const handleRefresh = async () => {
setRefreshing(true)
handleSearch(search)
@@ -84,114 +104,203 @@ export default function Search() {
setRefreshing(false)
};
+ const filters: { key: FilterType; label: string; count: number }[] = [
+ { key: "all", label: "Semua", count: totalResults },
+ { key: "member", label: "Anggota", count: dataUser.length },
+ { key: "division", label: "Divisi", count: dataDivisi.length },
+ { key: "project", label: "Kegiatan", count: dataProject.length },
+ ]
+
+ const showUser = activeFilter === "all" || activeFilter === "member"
+ const showDivision = activeFilter === "all" || activeFilter === "division"
+ const showProject = activeFilter === "all" || activeFilter === "project"
+
+ const activeFilterEmpty =
+ (activeFilter === "member" && dataUser.length === 0) ||
+ (activeFilter === "division" && dataDivisi.length === 0) ||
+ (activeFilter === "project" && dataProject.length === 0)
return (
- <>
-
- (
- router.back()} />
- )
- }}
- />
-
+
+ (
+ router.back()} />
+ )
+ }}
+ />
+
+
+ {/* Search bar */}
+
- {
- dataProject.length + dataDivisi.length + dataUser.length > 0
- ?
-
- }
- >
- {
- dataUser.length > 0 &&
-
- ANGGOTA
- {
- dataUser.map((item, index) => (
- }
- title={item.name}
- subtitle={`${item.group}-${item.position}`}
- onPress={() => {
- router.push(`/member/${item.id}`)
- }}
- />
- ))
- }
-
- }
-
- {
- dataDivisi.length > 0 &&
-
- DIVISI
- {
- dataDivisi.map((item, index) => (
-
-
-
- }
- title={item.name}
- subtitle={item.group}
- onPress={() => {
- router.push(`/division/${item.id}`)
- }}
- />
- ))
- }
-
- }
-
-
- {
- dataProject.length > 0 &&
-
- KEGIATAN
- {
- dataProject.map((item, index) => (
-
-
-
- }
- title={item.title}
- subtitle={item.group}
- onPress={() => {
- router.push(`/project/${item.id}`)
- }}
- />
- ))
- }
-
- }
-
- :
-
- Tidak ada data
-
- }
-
-
- >
+
+ {/* Filter tabs */}
+ {hasSearch && totalResults > 0 && (
+
+
+ {filters.map((f) => {
+ const isActive = activeFilter === f.key
+ return (
+ setActiveFilter(f.key)}
+ style={{
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingVertical: 6,
+ paddingHorizontal: 14,
+ borderRadius: 20,
+ marginRight: 8,
+ borderWidth: 1,
+ borderColor: isActive ? colors.tabActive : colors.icon + '40',
+ backgroundColor: isActive ? colors.tabActive + '20' : 'transparent',
+ }}
+ >
+
+ {f.label}
+
+ {f.count > 0 && (
+
+
+ {f.count}
+
+
+ )}
+
+ )
+ })}
+
+
+ )}
+
+ {/* Content */}
+
+ {!hasSearch ? (
+
+
+
+ Ketik minimal 3 karakter untuk mencari
+
+
+ ) : totalResults === 0 ? (
+
+
+
+ Tidak ada hasil untuk "{search}"
+
+
+ ) : (
+
+ }
+ >
+ {/* Anggota */}
+ {showUser && dataUser.length > 0 && (
+
+
+ {dataUser.map((item, index) => (
+
+ }
+ title={item.name}
+ subtitle={`${item.group} ยท ${item.position}`}
+ onPress={() => router.push(`/member/${item.id}`)}
+ colorPress
+ />
+
+ ))}
+
+ )}
+
+ {/* Divisi */}
+ {showDivision && dataDivisi.length > 0 && (
+
+
+ {dataDivisi.map((item, index) => (
+
+
+
+
+ }
+ title={item.name}
+ subtitle={item.group}
+ onPress={() => router.push(`/division/${item.id}`)}
+ colorPress
+ />
+
+ ))}
+
+ )}
+
+ {/* Kegiatan */}
+ {showProject && dataProject.length > 0 && (
+
+
+ {dataProject.map((item, index) => (
+
+
+
+
+ }
+ title={item.title}
+ subtitle={item.group}
+ onPress={() => router.push(`/project/${item.id}`)}
+ colorPress
+ />
+
+ ))}
+
+ )}
+
+ {/* Empty state untuk filter aktif */}
+ {activeFilter !== "all" && activeFilterEmpty && (
+
+
+
+ Tidak ada hasil di kategori ini
+
+
+ )}
+
+ )}
+
+
+
)
-}
\ No newline at end of file
+}