This is my API response structure in postman
{
"errorCode": 0,
"status": "ok",
"message": "App Layout",
"menus": [
{
"menuID": 1,
"title": "Students", //------------------------------------------Top menu
"childMenus": [//---------------------------- Menu's > childMenu
{
"chMenuID": 1,
"menuID": 0,
"title": "Student Profile",
"childMenus": null
},
{
"chMenuID": 41,
"menuID": 0,
"title": "Update Record",
"childMenus": [//---------------- Menu's > childMenu > subChildMenu
{
"sbChMenuID": 1,
"chMenuID": 0,
"title": "Class Promotion",
},
]
]
}
{
"menuID": 2,
"title": "Staff",
"childMenus": [
{
"chMenuID": 4,
"menuID": 0,
"title": "Staff Profile",
"childMenus": null
},
{
"chMenuID": 6,
"menuID": 0,
"title": "Staff Leave",
"childMenus": null
},
{
"chMenuID": 62,
"menuID": 0,
"title": "Staff Attendance",
"childMenus": null
},
Code: here i need if title
matches in any hierarchy i need that menu in filteredModuel but with my code only any one coming.
1)in above response if i search for keyword “staf”
then i need [staff profile, staff leave, staff attendance]
2)if i search for “profil”
then i need [staff profile, student profile]
how to get this kind of filter… please guide me
struct SearchView: View {
@State private var searchKeyword: String = ""
@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 {
VStack(spacing: 0) {
// in tabview i will show filterDataModuel()
filterDataModuel()
// some other code
}
}
.onAppear {
viewModelSidemenu.fetchAppLayout { success in
filterDataModuel()
}
}
}
private func filterDataModuel() {
let lowercasedKeyword = searchKeyword.lowercased()
filteredModuel = []
if let menus = viewModelSidemenu.layout?.menus {
for menu in menus {
let filteredChildMenus = menu.childMenus?.filter { childMenu in
let childTitleMatches = childMenu.title?.lowercased().contains(lowercasedKeyword) ?? false
return childTitleMatches
} ?? []
let titleMatches = menu.title?.lowercased().contains(lowercasedKeyword) ?? false
if !filteredChildMenus.isEmpty {
filteredModuel.append(contentsOf: filteredChildMenus)
}
if titleMatches && filteredChildMenus.isEmpty {
filteredModuel.append(menu)
}
}
}
}
@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)
}
}
}
model for this above response
// MARK: - AppLayoutModel
struct AppLayoutModel: Codable {
let status: String?
let isAuthenticated: Bool?
let menus: [AppMenu]?
let errorCode: Int?
enum CodingKeys: String, CodingKey {
case status, isAuthenticated, menus,
case userInfo, errorCode
}
}
struct AppMenu: Codable, Identifiable {
let title: String?
let menuID, chMenuID: Int?
let slNo: Int?
var childMenus: [AppMenu]?
var uniqueID: Int {
return menuID ?? -1
}
var id: Int {
return uniqueID
}
}