import 'dart:convert'; import 'package:icalserver/data.dart'; import 'package:icalserver/icalendar.dart'; import 'package:supabase/supabase.dart'; import 'package:shelf/shelf.dart'; class CalendarHandler { SupabaseClient getSupabaseClient(Request request) { // final supabaseUrl = request.headers['supabase-url']; // final authHeader = request.headers['authorization']; // final token = authHeader!.substring(7); // Remove 'Bearer ' prefix final supabaseUrl = 'http://baas.fares.cyou:8000'; final token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"; return SupabaseClient( supabaseUrl, token, ); } // Handler for the /link route Future getCalendar(Request request) async { final credentials = _getBasicAuthCredentials(request); if (credentials == null) { return Response.unauthorized('Invalid credentials'); } final (username, password) = credentials; if (username != password) { return Response.unauthorized('Invalid credentials'); } final supabase = getSupabaseClient(request); //get licence_csv table into variable final licences = (await supabase.from('licences_csv').select()); //print(licencesCsv); // Execute the query final rosterlist = await supabase.rpc('get_crew_roster', params: {'_tlc': username}); // Handle the response final requester = licences.firstWhere((e) => e['tlc'] == username, orElse: () => {}); print( 'TLC: $username ... EVENTS: ${rosterlist.length} ... Name: ${requester['lname']}, ${requester['fname']}'); // Create an iCalendar object final ical = ICalendar(); if (rosterlist is List) { for (var i = 0; i < rosterlist.length; i++) { final event = rosterlist[i]; final pnleg = Pnleg( date: event['date'], tlc: username, actype: event['actype'], al: event['al'], fnum: event['fnum'], dep: event['dep'], arr: event['des'], depdate: event['ddep'], deptime: event['hdep'], arrdate: event['ddes'], arrtime: event['hdes'], label: event['label'], type: event['type']); final List> crewlist = []; for (var j = 0; j < (event['crew'] as List).length; j++) { final crewmember = event['crew'][j] as String; final crewmemberDataAc = licences.firstWhere( (e) => (e['tlc'] == crewmember) && (e['ac'] == pnleg.ac), orElse: () => {}); final crewmemberData = licences .firstWhere((e) => e['tlc'] == crewmember, orElse: () => {}); crewlist.add([ '${([ "F", "G" ].contains(event['crewtype'][j]) ? "DH " : null) ?? (crewmemberDataAc["college"] ?? "--")}', '${crewmemberData["lname"] ?? "------"}', '${crewmemberData["fname"] ?? "Unknown"}' ]); } final crewlistdisplay = (crewlist ..sort((a, b) { const order = { 'CP': 0, 'FO': 1, 'PU': 2, 'SE': 3, 'ST': 4, 'JU': 5 }; return (order[a[0]] ?? 6).compareTo(order[b[0]] ?? 6); })) .map((e) => "${e[0]}: ${e[1]}, ${e[2]}") .join("\n"); switch (pnleg.dutytype) { case "flight": ical.addEvent( summary: "${pnleg.dep}-${pnleg.arr}", description: """ Flight from ${pnleg.dep} to ${pnleg.arr} Flight number: ${pnleg.al}${pnleg.fnum} Aircraft type: ${pnleg.actype} Departure time: ${pnleg.jdep?.Hm} Arrival time: ${pnleg.jarr?.Hm} Crew: $crewlistdisplay """ .replaceAll("\n", "\\n"), startTime: pnleg.jdep!.dateTime, endTime: pnleg.jarr!.dateTime, attendees: event['crew'], ); break; case "dhflight": ical.addEvent( summary: "DH ${pnleg.dep}-${pnleg.arr}", description: """ DH Flight from ${pnleg.dep} to ${pnleg.arr} Flight number: ${pnleg.al}${pnleg.fnum} Aircraft type: ${pnleg.actype} Departure time: ${pnleg.jdep?.Hm} Arrival time: ${pnleg.jarr?.Hm} Crew: $crewlistdisplay """ .replaceAll("\n", "\\n"), startTime: pnleg.jdep!.dateTime, endTime: pnleg.jarr!.dateTime, attendees: event['crew'], ); break; case "dhlimo": ical.addEvent( summary: "${pnleg.dep}-${pnleg.arr}", description: """ DH Limo from ${pnleg.dep} to ${pnleg.arr} Departure time: ${pnleg.jdep?.Hm} Arrival time: ${pnleg.jarr?.Hm} Crew: $crewlistdisplay """ .replaceAll("\n", "\\n"), startTime: pnleg.jdep!.dateTime, endTime: pnleg.jarr!.dateTime, attendees: event['crew'], ); break; case "standby": ical.addEvent( summary: "STDBY ${pnleg.label}", description: """ Stand By ${pnleg.label} at ${pnleg.dep} Start time: ${pnleg.jdep?.Hm} End time: ${pnleg.jarr?.Hm} """ .replaceAll("\n", "\\n"), startTime: pnleg.jdep!.dateTime, endTime: pnleg.jarr!.dateTime, attendees: event['crew'], ); break; case "ground": ical.addEvent( summary: "${pnleg.label}", description: """ ${pnleg.label} at ${pnleg.dep} Start time: ${pnleg.jdep?.Hm} End time: ${pnleg.jarr?.Hm} Attendee: $crewlistdisplay """ .replaceAll("\n", "\\n"), startTime: pnleg.jdep!.dateTime, endTime: pnleg.jarr!.dateTime, attendees: event['crew'], ); break; case "day": ical.addEvent( summary: "${pnleg.label}", description: """ ${pnleg.label} at ${pnleg.dep} Attendee: $crewlistdisplay """ .replaceAll("\n", "\\n"), startTime: pnleg.jdep!.dateTime, endTime: pnleg.jarr!.dateTime, attendees: event['crew'], allday: true); break; default: } } } // Return the response with the iCalendar content await supabase.dispose(); return Response.ok( ical.serialize(), headers: {'Content-Type': 'text/calendar; charset=utf-8'}, ); } (String, String)? _getBasicAuthCredentials(Request request) { // Get Authorization header if (!request.headers.containsKey('authorization')) { return null; } String authHeader = request.headers['authorization'] ?? ""; if (!authHeader.startsWith('Basic ')) { return null; } // Extract and decode credentials try { String base64Credentials = authHeader.substring('Basic '.length); String credentials = utf8.decode(base64.decode(base64Credentials)); List userPass = credentials.split(':'); if (userPass.length != 2) return null; return (userPass[0], userPass[1]); } catch (e) { return null; } } }