Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ uni/android/key.properties
**.jks

# Custom Lint log
custom_lint.log
custom_lint.log
.direnv
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
ndkVersions = ["28.2.13676358"];
};

flutter = pkgs.flutter338;
flutter = pkgs.flutter;
jdks = with pkgs; [jdk21 jdk17];
};
} {
Expand Down
50 changes: 50 additions & 0 deletions packages/uni_app/lib/controller/fetchers/parking_lot_fetcher.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'dart:convert';

import 'package:uni/controller/networking/network_router.dart';
import 'package:uni/model/entities/parking_lot_occupation.dart';
import 'package:uni/session/flows/base/session.dart';

class ParkingLotFetcher {
static const _endpoint = 'instalacs_geral.ocupacao_parques';

Future<ParkingLotOccupation> getParkingLotOccupation(Session session) async {
final url = '${NetworkRouter.getBaseUrl('feup')}$_endpoint';

final response = await NetworkRouter.getWithCookies(url, {}, session);
return _parse(response.body);
}

ParkingLotOccupation _parse(String body) {
final json = jsonDecode(body) as Map<String, dynamic>;
final itdc = json['itdc'] as List<dynamic>;
final resposta =
(itdc.first as Map<String, dynamic>)['resposta']
as Map<String, dynamic>;

final lots = [
ParkingLot(
id: 'P1',
type: ParkingLotType.permanentStaff,
capacity: resposta['p1lotacao'] as int,
occupied: resposta['p1ocupados'] as int,
free: resposta['p1livres'] as int,
),
ParkingLot(
id: 'P3',
type: ParkingLotType.students,
capacity: resposta['p3lotacao'] as int,
occupied: resposta['p3ocupados'] as int,
free: resposta['p3livres'] as int,
),
ParkingLot(
id: 'P4',
type: ParkingLotType.nonPermanentStaff,
capacity: resposta['p4lotacao'] as int,
occupied: resposta['p4ocupados'] as int,
free: resposta['p4livres'] as int,
),
];

return ParkingLotOccupation(lots);
}
}
13 changes: 13 additions & 0 deletions packages/uni_app/lib/generated/intl/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,17 @@ class MessageLookup extends MessageLookupByLibrary {
"no_library_info": MessageLookupByLibrary.simpleMessage(
"No library occupation information available",
),
"no_parking_info": MessageLookupByLibrary.simpleMessage(
"No parking lot information available",
),
"parking_lot_free": MessageLookupByLibrary.simpleMessage("free"),
"parking_lot_non_permanent_staff": MessageLookupByLibrary.simpleMessage(
"Non-Permanent Staff",
),
"parking_lot_permanent_staff": MessageLookupByLibrary.simpleMessage(
"Permanent Staff",
),
"parking_lot_students": MessageLookupByLibrary.simpleMessage("Students"),
"no_link": MessageLookupByLibrary.simpleMessage(
"We couldn\'t open the link",
),
Expand Down Expand Up @@ -383,6 +394,8 @@ class MessageLookup extends MessageLookupByLibrary {
"Error opening the file",
),
"other_links": MessageLookupByLibrary.simpleMessage("Other links"),
"parking": MessageLookupByLibrary.simpleMessage("Parking"),
"parking_lots": MessageLookupByLibrary.simpleMessage("Parking Lots"),
"pass_change_request": MessageLookupByLibrary.simpleMessage(
"For security reasons, passwords must be changed periodically.",
),
Expand Down
15 changes: 15 additions & 0 deletions packages/uni_app/lib/generated/intl/messages_pt_PT.dart
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,17 @@ class MessageLookup extends MessageLookupByLibrary {
"no_library_info": MessageLookupByLibrary.simpleMessage(
"Sem informação de ocupação",
),
"no_parking_info": MessageLookupByLibrary.simpleMessage(
"Sem informação de estacionamento disponível",
),
"parking_lot_free": MessageLookupByLibrary.simpleMessage("livre"),
"parking_lot_non_permanent_staff": MessageLookupByLibrary.simpleMessage(
"Pessoal Não Permanente",
),
"parking_lot_permanent_staff": MessageLookupByLibrary.simpleMessage(
"Pessoal Permanente",
),
"parking_lot_students": MessageLookupByLibrary.simpleMessage("Estudantes"),
"no_link": MessageLookupByLibrary.simpleMessage(
"Não conseguimos abrir o link",
),
Expand Down Expand Up @@ -405,6 +416,10 @@ class MessageLookup extends MessageLookupByLibrary {
"Erro ao abrir o ficheiro",
),
"other_links": MessageLookupByLibrary.simpleMessage("Outros links"),
"parking": MessageLookupByLibrary.simpleMessage("Estacionamento"),
"parking_lots": MessageLookupByLibrary.simpleMessage(
"Parques de Estacionamento",
),
"pass_change_request": MessageLookupByLibrary.simpleMessage(
"Por razões de segurança, as palavras-passe têm de ser alteradas periodicamente.",
),
Expand Down
60 changes: 60 additions & 0 deletions packages/uni_app/lib/generated/l10n.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions packages/uni_app/lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,20 @@
"@leave_feedback": {},
"library_occupation": "Library Occupation",
"@library_occupation": {},
"parking_lots": "Parking Lots",
"@parking_lots": {},
"parking": "Parking",
"@parking": {},
"no_parking_info": "No parking lot information available",
"@no_parking_info": {},
"parking_lot_permanent_staff": "Permanent Staff",
"@parking_lot_permanent_staff": {},
"parking_lot_students": "Students",
"@parking_lot_students": {},
"parking_lot_non_permanent_staff": "Non-Permanent Staff",
"@parking_lot_non_permanent_staff": {},
"parking_lot_free": "free",
"@parking_lot_free": {},
"lunch": "Lunch",
"@lunch": {},
"download_error": "Error downloading the file",
Expand Down
14 changes: 14 additions & 0 deletions packages/uni_app/lib/l10n/intl_pt_PT.arb
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@
"@load_error": {},
"library_occupation": "Ocupação da Biblioteca",
"@library_occupation": {},
"parking_lots": "Parques de Estacionamento",
"@parking_lots": {},
"parking": "Estacionamento",
"@parking": {},
"no_parking_info": "Sem informação de estacionamento disponível",
"@no_parking_info": {},
"parking_lot_permanent_staff": "Pessoal Permanente",
"@parking_lot_permanent_staff": {},
"parking_lot_students": "Estudantes",
"@parking_lot_students": {},
"parking_lot_non_permanent_staff": "Pessoal Não Permanente",
"@parking_lot_non_permanent_staff": {},
"parking_lot_free": "livre",
"@parking_lot_free": {},
"lunch": "Almoço",
"@lunch": {},
"download_error": "Erro ao descarregar o ficheiro",
Expand Down
25 changes: 25 additions & 0 deletions packages/uni_app/lib/model/entities/parking_lot_occupation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
enum ParkingLotType { permanentStaff, students, nonPermanentStaff }

class ParkingLot {
ParkingLot({
required this.id,
required this.type,
required this.capacity,
required this.occupied,
required this.free,
});

final String id;
final ParkingLotType type;
final int capacity;
final int occupied;
final int free;

double get occupancyRatio => capacity > 0 ? occupied / capacity : 0.0;
}

class ParkingLotOccupation {
ParkingLotOccupation(this.lots);

final List<ParkingLot> lots;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:uni/controller/fetchers/parking_lot_fetcher.dart';
import 'package:uni/model/entities/parking_lot_occupation.dart';
import 'package:uni/model/providers/riverpod/cached_async_notifier.dart';
import 'package:uni/model/providers/riverpod/session_provider.dart';

final parkingLotProvider =
AsyncNotifierProvider<ParkingLotNotifier, ParkingLotOccupation?>(
ParkingLotNotifier.new,
);

final class ParkingLotNotifier
extends CachedAsyncNotifier<ParkingLotOccupation?> {
Comment on lines +7 to +13
@override
Duration? get cacheDuration => const Duration(minutes: 15);

@override
Future<ParkingLotOccupation?> loadFromStorage() async {
return null;
}
Comment on lines +15 to +20

@override
Future<ParkingLotOccupation?> loadFromRemote() async {
final session = await ref.read(sessionProvider.future);
if (session == null) {
return null;
}

return ParkingLotFetcher().getParkingLotOccupation(session);
}
}
1 change: 1 addition & 0 deletions packages/uni_app/lib/utils/favorite_widget_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ enum FavoriteWidgetType {
restaurants,
calendar,
news,
parking,
}
11 changes: 10 additions & 1 deletion packages/uni_app/lib/view/faculty/faculty.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:uni/generated/l10n.dart';
import 'package:uni/model/providers/riverpod/library_occupation_provider.dart';
import 'package:uni/model/providers/riverpod/parking_lot_provider.dart';
import 'package:uni/utils/navigation_items.dart';
import 'package:uni/view/faculty/widgets/service_cards.dart';
import 'package:uni/view/home/widgets/calendar/calendar_home_card.dart';
import 'package:uni/view/home/widgets/library/library_home_card.dart';
import 'package:uni/view/home/widgets/parking/parking_home_card.dart';
import 'package:uni/view/widgets/pages_layouts/general/general.dart';

class FacultyPageView extends ConsumerStatefulWidget {
Expand All @@ -25,6 +27,10 @@ class FacultyPageViewState extends GeneralPageViewState<FacultyPageView> {
return ListView(
children: const [
LibraryHomeCard(),
Padding(
padding: EdgeInsets.symmetric(vertical: 10),
child: ParkingLotHomeCard(),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 10),
child: CalendarHomeCard(),
Expand All @@ -39,6 +45,9 @@ class FacultyPageViewState extends GeneralPageViewState<FacultyPageView> {

@override
Future<void> onRefresh() async {
await ref.read(libraryProvider.notifier).refreshRemote();
await Future.wait([
ref.read(libraryProvider.notifier).refreshRemote(),
ref.read(parkingLotProvider.notifier).refreshRemote(),
]);
}
}
4 changes: 4 additions & 0 deletions packages/uni_app/lib/view/home/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:uni/model/providers/riverpod/exam_provider.dart';
import 'package:uni/model/providers/riverpod/lecture_provider.dart';
import 'package:uni/model/providers/riverpod/library_occupation_provider.dart';
import 'package:uni/model/providers/riverpod/news_provider.dart';
import 'package:uni/model/providers/riverpod/parking_lot_provider.dart';
import 'package:uni/model/providers/riverpod/pedagogical_surveys_provider.dart';
import 'package:uni/model/providers/riverpod/profile_provider.dart';
import 'package:uni/model/providers/riverpod/restaurant_provider.dart';
Expand All @@ -23,6 +24,7 @@ import 'package:uni/view/home/widgets/connectivity_warning.dart';
import 'package:uni/view/home/widgets/exams/exam_home_card.dart';
import 'package:uni/view/home/widgets/library/library_home_card.dart';
import 'package:uni/view/home/widgets/news/news_home_card.dart';
import 'package:uni/view/home/widgets/parking/parking_home_card.dart';
import 'package:uni/view/home/widgets/pedagogical_surveys_info.dart';
import 'package:uni/view/home/widgets/restaurants/restaurant_home_card.dart';
import 'package:uni/view/home/widgets/schedule/schedule_home_card.dart';
Expand Down Expand Up @@ -60,6 +62,7 @@ class HomePageViewState extends ConsumerState<HomePageView> {
FavoriteWidgetType.library: libraryProvider,
FavoriteWidgetType.restaurants: restaurantProvider,
FavoriteWidgetType.news: newsProvider,
FavoriteWidgetType.parking: parkingLotProvider,
};

@override
Expand Down Expand Up @@ -104,6 +107,7 @@ class HomePageViewState extends ConsumerState<HomePageView> {
FavoriteWidgetType.restaurants: const RestaurantHomeCard(),
FavoriteWidgetType.calendar: const CalendarHomeCard(),
FavoriteWidgetType.news: const NewsHomeCard(),
FavoriteWidgetType.parking: const ParkingLotHomeCard(),
};

return AnnotatedRegion<SystemUiOverlayStyle>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import 'package:uni_ui/icons.dart';
return (S.of(context).calendar, const UniIcon(UniIcons.calendar));
case FavoriteWidgetType.news:
return (S.of(context).news, const UniIcon(UniIcons.news));
case FavoriteWidgetType.parking:
return (S.of(context).parking, const UniIcon(UniIcons.parking));
// case 'ucs':
// title = 'UCS';
// icon = const UniIcon(UniIcons.graduationCap);
Expand Down
Loading
Loading