import 'dart:convert'; import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:timeago/timeago.dart' as timeago; import 'lat_lng.dart'; import 'place.dart'; import 'uploaded_file.dart'; import '/backend/schema/structs/index.dart'; import '/auth/custom_auth/auth_util.dart'; String? kortDatum(String? rawDatum) { if (rawDatum == null || rawDatum.trim().isEmpty) { return rawDatum; } const weekdagen = { 'maandag': 'ma', 'dinsdag': 'di', 'woensdag': 'wo', 'donderdag': 'do', 'vrijdag': 'vr', 'zaterdag': 'za', 'zondag': 'zo', }; const maandVolledig = { 'januari': 'jan', 'februari': 'feb', 'maart': 'mrt', 'april': 'apr', 'mei': 'mei', 'juni': 'jun', 'juli': 'jul', 'augustus': 'aug', 'september': 'sep', 'oktober': 'okt', 'november': 'nov', 'december': 'dec', }; const maandKort = { 'jan', 'feb', 'mrt', 'apr', 'mei', 'jun', 'jul', 'aug', 'sep', 'okt', 'nov', 'dec', }; // Alles vanaf de komma (bv. ", 15:00") negeren. final zonderTijd = rawDatum.split(',').first.trim().toLowerCase(); final delen = zonderTijd.split(RegExp(r'\s+')); if (delen.length < 3) { return rawDatum; } final weekdag = weekdagen[delen[0]]; final dag = delen[1]; final maandRuw = delen[2].replaceAll('.', ''); final maand = maandVolledig[maandRuw] ?? (maandKort.contains(maandRuw) ? maandRuw : null); if (weekdag == null || maand == null) { return rawDatum; } final tijdDelen = rawDatum.split(','); final tijd = tijdDelen.length > 1 ? tijdDelen.sublist(1).join(',').trim() : ''; return tijd.isNotEmpty ? '$weekdag $dag $maand $tijd' : '$weekdag $dag $maand'; } String? provincieNaamById( List? lijst, String? id, ) { return lijst ?.firstWhere((e) => e.provincieid == id, orElse: () => ProvincieModelStruct()) .provinciename; } /// id String? gemeenteNaamById( List? lijst, String? id, ) { return lijst ?.firstWhere((e) => e.gemeenteid == id, orElse: () => GemeenteModelStruct()) .gemeentename; } String? favorietenBodyNode(String nid) { return '{"entity_id": ' + nid + ', "entity_type": "node"}'; } String googleMapsUrl( String adres, String plaats, ) { return 'https://www.google.com/maps/search/?api=1&query=' + Uri.encodeComponent('$adres, $plaats'); } List filterHorecagelegenheden( List? items, String zoekterm, String? categorieFilter, String titelPad, String categoriePad, ) { final titelKey = titelPad.startsWith(r'$.') ? titelPad.substring(2) : titelPad; final categorieKey = categoriePad.startsWith(r'$.') ? categoriePad.substring(2) : categoriePad; final term = zoekterm .trim() .toLowerCase() .replaceAll('à', 'a') .replaceAll('á', 'a') .replaceAll('ä', 'a') .replaceAll('â', 'a') .replaceAll('è', 'e') .replaceAll('é', 'e') .replaceAll('ë', 'e') .replaceAll('ê', 'e') .replaceAll('ì', 'i') .replaceAll('í', 'i') .replaceAll('ï', 'i') .replaceAll('î', 'i') .replaceAll('ò', 'o') .replaceAll('ó', 'o') .replaceAll('ö', 'o') .replaceAll('ô', 'o') .replaceAll('ù', 'u') .replaceAll('ú', 'u') .replaceAll('ü', 'u') .replaceAll('û', 'u') .replaceAll('ñ', 'n') .replaceAll('ç', 'c'); final catFilter = categorieFilter?.trim(); return (items ?? []).where((item) { final map = item is Map ? item : null; if (term.isNotEmpty) { final titelRaw = map?[titelKey]?.toString() ?? ''; final titel = titelRaw .toLowerCase() .replaceAll('à', 'a') .replaceAll('á', 'a') .replaceAll('ä', 'a') .replaceAll('â', 'a') .replaceAll('è', 'e') .replaceAll('é', 'e') .replaceAll('ë', 'e') .replaceAll('ê', 'e') .replaceAll('ì', 'i') .replaceAll('í', 'i') .replaceAll('ï', 'i') .replaceAll('î', 'i') .replaceAll('ò', 'o') .replaceAll('ó', 'o') .replaceAll('ö', 'o') .replaceAll('ô', 'o') .replaceAll('ù', 'u') .replaceAll('ú', 'u') .replaceAll('ü', 'u') .replaceAll('û', 'u') .replaceAll('ñ', 'n') .replaceAll('ç', 'c'); if (!titel.contains(term)) { return false; } } if (catFilter != null && catFilter.isNotEmpty) { final categorie = map?[categorieKey]; final lijst = (categorie is List) ? categorie : []; final match = lijst .any((c) => c.toString().toLowerCase() == catFilter.toLowerCase()); if (!match) { return false; } } return true; }).toList(); } String? dISABLEdatumVoorApi(String? datum) { if (datum == null) return ''; final s = datum.trim(); if (s.isEmpty) return ''; final punt = s.indexOf('.'); return punt == -1 ? s : s.substring(0, punt); } String? buildStempel() { return const String.fromEnvironment('BUILD_TS', defaultValue: 'onbekend'); } List? categorieSubTids(dynamic respons) { final lijst = respons; final uit = []; if (lijst is! List) return uit; for (final item in lijst) { if (item is! Map) continue; final d = int.tryParse('${item['diepte']}'); if (d != 1) continue; uit.add('${item['tid']}'); } return uit; } List? categorieSubLabels(dynamic respons) { final lijst = respons; final uit = []; if (lijst is! List) return uit; final namen = {}; for (final item in lijst) { if (item is Map) namen['${item['tid']}'] = '${item['naam']}'; } for (final item in lijst) { if (item is! Map) continue; final d = int.tryParse('${item['diepte']}'); if (d != 1) continue; final ouder = namen['${item['parent_tid']}'] ?? ''; uit.add(ouder.isEmpty ? '${item['naam']}' : '$ouder › ${item['naam']}'); } return uit; } String? horecaVoorselectie( dynamic mijnHoreca, String? paramNid, ) { if (paramNid != null && paramNid.trim().isNotEmpty) { return paramNid.trim(); } if (mijnHoreca is List && mijnHoreca.length == 1) { final eerste = mijnHoreca[0]; if (eerste is Map && eerste['nid'] != null) { return eerste['nid'].toString(); } } return null; } String? lijstAlsTekst(dynamic items) { if (items == null) { return ''; } if (items is List) { return items.join(', '); } return items.toString(); } List? categorieAlsLijst(dynamic categorie) { final uit = []; if (categorie == null) return uit; final ruw = categorie is List ? categorie : categorie.toString().split(','); for (final deel in ruw) if (deel != null && deel.toString().trim().isNotEmpty) uit.add(deel.toString().trim()); return uit; } String? filterDatumVan(String? keuze) { final k = (keuze ?? '').toLowerCase().trim(); if (k.length == 10 && k[4] == '-' && k[7] == '-') return '$k 00:00:00'; String soort = ''; if (k.contains('weekend')) { soort = 'weekend'; } else if (k.contains('vandaag') || k.contains('today')) { soort = 'vandaag'; } else if (k.contains('week')) { soort = 'week'; } if (soort == '') { return ''; } final nu = DateTime.now(); int extra = 0; if (soort == 'weekend' && nu.weekday < 6) { extra = 6 - nu.weekday; } final start = DateTime(nu.year, nu.month, nu.day + extra); final maand = start.month.toString().padLeft(2, '0'); final dag = start.day.toString().padLeft(2, '0'); return '${start.year}-$maand-$dag 00:00:00'; } String? filterDatumTot(String? keuze) { final k = (keuze ?? '').toLowerCase().trim(); if (k.length == 10 && k[4] == '-' && k[7] == '-') return '$k 23:59:59'; String soort = ''; if (k.contains('weekend')) { soort = 'weekend'; } else if (k.contains('vandaag') || k.contains('today')) { soort = 'vandaag'; } else if (k.contains('week')) { soort = 'week'; } if (soort == '') { return ''; } final nu = DateTime.now(); int extra = 0; if (soort != 'vandaag' && nu.weekday < 7) { extra = 7 - nu.weekday; } final eind = DateTime(nu.year, nu.month, nu.day + extra); final maand = eind.month.toString().padLeft(2, '0'); final dag = eind.day.toString().padLeft(2, '0'); return '${eind.year}-$maand-$dag 23:59:59'; } String? datumKnopLabel(String? filter) { final k = (filter ?? '').trim(); if (k.length != 10) return ''; if (k[4] != '-') return ''; if (k[7] != '-') return ''; return k.substring(8, 10) + '-' + k.substring(5, 7) + '-' + k.substring(0, 4); } String datumFilterVanPicker(DateTime? gekozen) { if (gekozen == null) return ''; if (gekozen.hour != 0) return ''; if (gekozen.minute != 0) return ''; if (gekozen.second != 0) return ''; final m = gekozen.month.toString().padLeft(2, '0'); final d = gekozen.day.toString().padLeft(2, '0'); return gekozen.year.toString() + '-' + m + '-' + d; } List? horcatSubTids( dynamic respons, String? horcatTid, ) { final uit = []; if (respons is! List) return uit; final ouder = horcatTid == null ? '' : horcatTid.trim(); if (ouder.isEmpty) return uit; for (final item in respons) { if (item is! Map) continue; final p = item['parent_tid'] == null ? '' : item['parent_tid'].toString().trim(); if (p != ouder) continue; final t = item['tid'] == null ? '' : item['tid'].toString().trim(); if (t.isEmpty) continue; uit.add(t); } return uit; } List? horcatSubLabels( dynamic respons, String? horcatTid, ) { final uit = []; if (respons is! List) return uit; final ouder = horcatTid == null ? '' : horcatTid.trim(); if (ouder.isEmpty) return uit; for (final item in respons) { if (item is! Map) continue; final p = item['parent_tid'] == null ? '' : item['parent_tid'].toString().trim(); if (p != ouder) continue; final t = item['tid'] == null ? '' : item['tid'].toString().trim(); if (t.isEmpty) continue; final n = item['naam'] == null ? '' : item['naam'].toString().trim(); uit.add(n.isEmpty ? t : n); } return uit; } List? horcatOptiesVoorTab( dynamic respons, int? tabIndex, ) { final tids = ['17969', '17963', '34', '17965', '17967', '17968']; final uit = ['']; final i = tabIndex == null ? 0 : tabIndex; if (i < 0 || i >= tids.length) return uit; final sub = horcatSubLabels(respons, tids[i]); if (sub != null) uit.addAll(sub); return uit; } List? horcatLabelsVoorTab( dynamic respons, int? tabIndex, ) { final tids = ['17969', '17963', '34', '17965', '17967', '17968']; final uit = ['Alle categorieen']; final i = tabIndex == null ? 0 : tabIndex; if (i < 0 || i >= tids.length) return uit; final sub = horcatSubLabels(respons, tids[i]); if (sub != null) uit.addAll(sub); return uit; } String headerLocatie( bool? landelijk, String? plaatsId, String? provincieId, String? provincieNaam, String? gemeenteNaam, ) { if (landelijk == true) return 'Heel Nederland'; if (plaatsId != null && plaatsId.isNotEmpty && provincieId != null && plaatsId == provincieId && provincieNaam != null && provincieNaam.isNotEmpty) return provincieNaam; if (gemeenteNaam != null && gemeenteNaam.isNotEmpty) return gemeenteNaam; return 'Kies je gemeente'; } String organisatorTekst(String? waarde) { if (waarde == null) return ''; final schoon = waarde.trim(); if (schoon.isEmpty || schoon.toLowerCase() == 'null') return ''; return schoon; } String adresRegel( String? adres, String? plaats, ) { final a = (adres ?? '').trim(); final p = (plaats ?? '').trim(); if (a.isEmpty) return p; if (p.isEmpty) return a; return a + ', ' + p; } String? gemeenteVoorselectie( dynamic mijnGemeenten, String? paramTid, ) { if (paramTid != null && paramTid.trim().isNotEmpty) { return paramTid.trim(); } if (mijnGemeenten is List && mijnGemeenten.length == 1) { final eerste = mijnGemeenten[0]; if (eerste is Map && eerste['tid'] != null) { return eerste['tid'].toString(); } } return null; } List? favorieteGemeenteNids(List? lijst) { final result = []; for (final item in (lijst ?? [])) { if (item is Map) { final nid = item['nid']; if (nid != null && nid.toString().isNotEmpty) { result.add(nid.toString()); } } } return result; } bool isOngepubliceerd(dynamic item) { if (item is! Map) { return false; } final ruw = item['status']; if (ruw != null) { return ruw.toString().trim() != '1'; } final label = item['status_label']; if (label != null) { return label.toString().trim().toLowerCase() != 'gepubliceerd'; } return false; } bool isHuidigeGemeente( dynamic nid, String? huidig, ) { if (nid == null) { return false; } final a = nid.toString().trim(); final b = (huidig ?? '').trim(); return a.isNotEmpty && a == b; } String kloonTekst( dynamic bron, String sleutel, ) { if (bron == null || bron is! Map) return ''; final waarde = bron[sleutel]; if (waarde == null) return ''; return waarde.toString(); } List kloonLijst( dynamic bron, String sleutel, ) { final uit = []; if (bron == null || bron is! Map) return uit; final waarde = bron[sleutel]; if (waarde is! List) return uit; for (final item in waarde) if (item != null) uit.add(item.toString()); return uit; }