Code: here i am getting correct number in filteredModuel
array but it showing only arrays last item in contentView
why? where am i wrong? how to fix.
struct SearchView: View {
@State private var searchKeyword: String = ""
@State private var selectedTab: Int = 0
@State private var optionsArray = ["Module", "Student", "Staff"]
@StateObject var viewModelSidemenu = SideMenuViewModel()
@State private var filteredModuel: [AppMenu] = []
@State private var selectedIndex: Int? = 4
@State private var navigateModule: Bool = false
@State private var moduleId: String = ""
var body: some View {
ZStack {
Color.Neumorphic.main
.ignoresSafeArea()
VStack(spacing: 0) {
headerView()
tabView()
.frame(height: 50)
.background(Color.brandColor)
.padding(.top, 20)
contentView()
}
}
.onAppear {
viewModelSidemenu.fetchAppLayout { success in
filterDataModuel()
}
}
}
private func filterDataModuel() {
filteredModuel = []
guard let menus = viewModelSidemenu.layout?.menus else { return }
for menu in menus {
var result = menu.childMenus?.filter { $0.menuTitle.localizedCaseInsensitiveContains(searchKeyword) } ?? []
if result.isEmpty, menu.menuTitle.localizedCaseInsensitiveContains(searchKeyword) {
result.append(menu)
}
filteredModuel.append(contentsOf: result)
}
print("final filter (filteredModuel)")
}
private func filterDataStu() {
filteredStudents = viewModel.students.filter { student in
let lowercasedKeyword = searchKeyword.lowercased()
return (student.name?.lowercased().contains(lowercasedKeyword) ?? false) ||
(student.admissionNumber?.lowercased().contains(lowercasedKeyword) ?? false)
}
}
@ViewBuilder func headerView() -> some View {
VStack {
HStack {
VStack {
ZStack {
Rectangle()
.fill(Color.clear)
.overlay(
RoundedRectangle(cornerRadius: 30)
.stroke(Color.appGreen2, lineWidth: 2)
)
.cornerRadius(30)
HStack {
TextField("Search...", text: $searchKeyword)
.padding(.horizontal, 10)
.padding(.vertical, 8)
.onChange(of: searchKeyword) { newValue in
filterDataModuel()
filterDataStu()
}
.padding(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
}
.padding(.top, 10)
}
.frame(height: 60)
Spacer()
}
.padding(.leading, 10)
}
}
@ViewBuilder func tabView() -> some View {
GeometryReader { geometry in
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 0) {
ForEach(0..<optionsArray.count, id: .self) { i in
let data = optionsArray[i]
Button {
withAnimation(.easeInOut(duration: 0.3)) {
selectedTab = i
filterDataModuel()
filterDataStu()
}
} label: {
VStack {
Text(data)
.font(.calibriBold(with: 16))
}
.frame(width: (geometry.size.width / CGFloat(optionsArray.count)), height: 45)
}
.buttonStyle(.plain)
}
}
.frame(height: 45)
}
.frame(height: 50)
.background(Color.clear)
}
}
@ViewBuilder func contentView() -> some View {
ScrollView {
LazyVGrid(columns: [GridItem(.fixed(screenWidth/2), spacing: 0), GridItem(.fixed(screenWidth/2), spacing: 0)], spacing: 0) {
if selectedTab == 0 {
ForEach(filteredModuel) { module in
Button {
// Handle module selection
moduleId = module.title?.lowercased() ?? ""
navigateModule = true
print("selected moduel (moduleId)")
} label: {
moduelView(moduel: module)
}
.frame(width: screenWidth/2, height: screenWidth/2)
}
}
else if selectedTab == 1 {
ForEach(filteredStudents) { student in
Button {
selectedStudent = student
gotoStudent = true
} label: {
profileViewStu(student: student)
}
.frame(width: screenWidth/2, height: screenWidth/2)
}
}
}
}
}
@ViewBuilder func moduelView(moduel: AppMenu) -> some View {
VStack {
let urlStr = moduel.icon ?? ""
URLImageView(url: urlStr, placeholder: "NoProfilePic", width: 100, height: 100, renderingMode: .template)
.foregroundStyle(.black)
.padding()
Text(moduel.title ?? " ")
.font(.calibriBold(with: 16))
.foregroundStyle(Color.hex1E1D0E)
.multilineTextAlignment(.center)
}
}
@ViewBuilder func profileViewStu(student: Student) -> some View {
VStack {
let urlStr = student.photo ?? ""
URLImageView(url: urlStr, placeholder: "NoProfilePic", width: 100, height: 100)
.cornerRadius(8)
.padding(.bottom, 15)
Text("(student.name ?? " ") ((student.studentClass ?? " "))")
.font(.calibriBold(with: 15))
.foregroundStyle(Color.hex1E1D0E)
.multilineTextAlignment(.center)
}
}
}
o/p
final filter [e_Care.AppMenu(title: Optional(“Staff Profile”), menuID: Optional(0), chMenuID: Optional(4), url: nil, icon: Optional(“https://api-stavvprofile.svg”), slNo: Optional(0), childMenus: nil), e_Care.AppMenu(title: Optional(“Staff Leave”), menuID: Optional(0), chMenuID: Optional(6), url: nil, icon: Optional(“https://api-leave.svg”), slNo: Optional(0), childMenus: nil), e_Care.AppMenu(title: Optional(“Staff Attendance”), menuID: Optional(0), chMenuID: Optional(62), url: nil, icon: Optional(“https://api-ap-StaffAttendance.svg”), slNo: Optional(0), childMenus: nil)]
but in screen only last item in filter is showing