Update: 2026-07-12 05:49:17
This commit is contained in:
@@ -22,25 +22,29 @@ class TransitHomePage extends StatelessWidget {
|
|||||||
title: 'Mawasalati'.tr,
|
title: 'Mawasalati'.tr,
|
||||||
isleading: true,
|
isleading: true,
|
||||||
body: [
|
body: [
|
||||||
Expanded(
|
Column(
|
||||||
child: RefreshIndicator(
|
children: [
|
||||||
onRefresh: c.fetchMyEnrollments,
|
Expanded(
|
||||||
child: c.isLoadingEnrollments
|
child: RefreshIndicator(
|
||||||
? const Center(child: CircularProgressIndicator())
|
onRefresh: c.fetchMyEnrollments,
|
||||||
: c.myEnrollments.isEmpty
|
child: c.isLoadingEnrollments
|
||||||
? _emptyState(c)
|
? const Center(child: CircularProgressIndicator())
|
||||||
: ListView(
|
: c.myEnrollments.isEmpty
|
||||||
padding: const EdgeInsets.all(16),
|
? _emptyState(c)
|
||||||
children: [
|
: ListView(
|
||||||
Text('My Memberships'.tr,
|
padding: const EdgeInsets.all(16),
|
||||||
style: AppStyle.headTitle2.copyWith(fontSize: 18)),
|
children: [
|
||||||
const SizedBox(height: 12),
|
Text('My Memberships'.tr,
|
||||||
...c.myEnrollments.map((e) => _enrollmentCard(e, c)),
|
style: AppStyle.headTitle2.copyWith(fontSize: 18)),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 12),
|
||||||
_addOrgTile(),
|
...c.myEnrollments.map((e) => _enrollmentCard(e, c)),
|
||||||
],
|
const SizedBox(height: 20),
|
||||||
),
|
_addOrgTile(),
|
||||||
),
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ class _TransitOrgBrowsePageState extends State<TransitOrgBrowsePage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
Get.find<TransitController>().browseOrgs();
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
Get.find<TransitController>().browseOrgs();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -32,59 +34,69 @@ class _TransitOrgBrowsePageState extends State<TransitOrgBrowsePage> {
|
|||||||
title: 'Choose your institution'.tr,
|
title: 'Choose your institution'.tr,
|
||||||
isleading: true,
|
isleading: true,
|
||||||
body: [
|
body: [
|
||||||
Padding(
|
Column(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
children: [
|
||||||
child: TextField(
|
Padding(
|
||||||
controller: _searchCtrl,
|
padding:
|
||||||
onSubmitted: (v) => c.browseOrgs(search: v),
|
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
decoration: InputDecoration(
|
child: TextField(
|
||||||
hintText: 'Search for a university or institution...'.tr,
|
controller: _searchCtrl,
|
||||||
prefixIcon: const Icon(Icons.search),
|
onSubmitted: (v) => c.browseOrgs(search: v),
|
||||||
filled: true,
|
decoration: InputDecoration(
|
||||||
fillColor: AppColor.cardColor,
|
hintText: 'Search for a university or institution...'.tr,
|
||||||
border: OutlineInputBorder(
|
prefixIcon: const Icon(Icons.search),
|
||||||
borderRadius: BorderRadius.circular(12),
|
filled: true,
|
||||||
borderSide: BorderSide(color: AppColor.borderColor),
|
fillColor: AppColor.cardColor,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
borderSide: BorderSide(color: AppColor.borderColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
),
|
child: c.isLoadingOrgs
|
||||||
Expanded(
|
? const Center(child: CircularProgressIndicator())
|
||||||
child: c.isLoadingOrgs
|
: c.browsableOrgs.isEmpty
|
||||||
? const Center(child: CircularProgressIndicator())
|
? Center(
|
||||||
: c.browsableOrgs.isEmpty
|
child: Text('No results'.tr, style: AppStyle.title),
|
||||||
? Center(
|
)
|
||||||
child: Text('No results'.tr, style: AppStyle.title),
|
: ListView.builder(
|
||||||
)
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
: ListView.builder(
|
itemCount: c.browsableOrgs.length,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
itemBuilder: (_, i) {
|
||||||
itemCount: c.browsableOrgs.length,
|
final org = c.browsableOrgs[i];
|
||||||
itemBuilder: (_, i) {
|
return Card(
|
||||||
final org = c.browsableOrgs[i];
|
margin: const EdgeInsets.only(bottom: 10),
|
||||||
return Card(
|
color: AppColor.cardColor,
|
||||||
margin: const EdgeInsets.only(bottom: 10),
|
elevation: 0,
|
||||||
color: AppColor.cardColor,
|
shape: RoundedRectangleBorder(
|
||||||
elevation: 0,
|
borderRadius: BorderRadius.circular(14),
|
||||||
shape: RoundedRectangleBorder(
|
side: BorderSide(color: AppColor.borderColor),
|
||||||
borderRadius: BorderRadius.circular(14),
|
),
|
||||||
side: BorderSide(color: AppColor.borderColor),
|
child: ListTile(
|
||||||
),
|
title:
|
||||||
child: ListTile(
|
Text(org.nameAr, style: AppStyle.title),
|
||||||
title: Text(org.nameAr, style: AppStyle.title),
|
subtitle:
|
||||||
subtitle: Text(org.city, style: AppStyle.subtitle),
|
Text(org.city, style: AppStyle.subtitle),
|
||||||
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
|
trailing: const Icon(Icons.arrow_forward_ios,
|
||||||
onTap: () => _showActivateSheet(context, c, org),
|
size: 16),
|
||||||
),
|
onTap: () =>
|
||||||
);
|
_showActivateSheet(context, c, org),
|
||||||
},
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showActivateSheet(BuildContext context, TransitController c, TransitOrg org) {
|
void _showActivateSheet(
|
||||||
|
BuildContext context, TransitController c, TransitOrg org) {
|
||||||
final idCtrl = TextEditingController();
|
final idCtrl = TextEditingController();
|
||||||
bool loading = false;
|
bool loading = false;
|
||||||
|
|
||||||
@@ -107,7 +119,8 @@ class _TransitOrgBrowsePageState extends State<TransitOrgBrowsePage> {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(org.nameAr, style: AppStyle.headTitle2.copyWith(fontSize: 18)),
|
Text(org.nameAr,
|
||||||
|
style: AppStyle.headTitle2.copyWith(fontSize: 18)),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
Text('Enter your student/employee ID to activate membership'.tr,
|
Text('Enter your student/employee ID to activate membership'.tr,
|
||||||
style: AppStyle.subtitle),
|
style: AppStyle.subtitle),
|
||||||
@@ -118,7 +131,8 @@ class _TransitOrgBrowsePageState extends State<TransitOrgBrowsePage> {
|
|||||||
hintText: 'Student ID'.tr,
|
hintText: 'Student ID'.tr,
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: AppColor.secondaryColor,
|
fillColor: AppColor.secondaryColor,
|
||||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)),
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(12)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
@@ -128,7 +142,8 @@ class _TransitOrgBrowsePageState extends State<TransitOrgBrowsePage> {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (idCtrl.text.trim().isEmpty) return;
|
if (idCtrl.text.trim().isEmpty) return;
|
||||||
setState(() => loading = true);
|
setState(() => loading = true);
|
||||||
final ok = await c.activateEnrollment(org.id, idCtrl.text.trim());
|
final ok =
|
||||||
|
await c.activateEnrollment(org.id, idCtrl.text.trim());
|
||||||
setState(() => loading = false);
|
setState(() => loading = false);
|
||||||
if (ok && ctx.mounted) {
|
if (ok && ctx.mounted) {
|
||||||
Navigator.pop(ctx);
|
Navigator.pop(ctx);
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ class _TransitRoutesPageState extends State<TransitRoutesPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
Get.find<TransitController>().openOrgRoutes(widget.orgId);
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
Get.find<TransitController>().openOrgRoutes(widget.orgId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -31,41 +33,45 @@ class _TransitRoutesPageState extends State<TransitRoutesPage> {
|
|||||||
title: widget.orgName,
|
title: widget.orgName,
|
||||||
isleading: true,
|
isleading: true,
|
||||||
body: [
|
body: [
|
||||||
Expanded(
|
Column(
|
||||||
child: c.isLoadingRoutes
|
children: [
|
||||||
? const Center(child: CircularProgressIndicator())
|
Expanded(
|
||||||
: c.currentOrgRoutes.isEmpty
|
child: c.isLoadingRoutes
|
||||||
? Center(
|
? const Center(child: CircularProgressIndicator())
|
||||||
child: Text('No active routes currently'.tr, style: AppStyle.title),
|
: c.currentOrgRoutes.isEmpty
|
||||||
)
|
? Center(
|
||||||
: ListView.builder(
|
child: Text('No active routes currently'.tr, style: AppStyle.title),
|
||||||
padding: const EdgeInsets.all(16),
|
)
|
||||||
itemCount: c.currentOrgRoutes.length,
|
: ListView.builder(
|
||||||
itemBuilder: (_, i) {
|
padding: const EdgeInsets.all(16),
|
||||||
final r = c.currentOrgRoutes[i];
|
itemCount: c.currentOrgRoutes.length,
|
||||||
return Card(
|
itemBuilder: (_, i) {
|
||||||
margin: const EdgeInsets.only(bottom: 10),
|
final r = c.currentOrgRoutes[i];
|
||||||
color: AppColor.cardColor,
|
return Card(
|
||||||
elevation: 0,
|
margin: const EdgeInsets.only(bottom: 10),
|
||||||
shape: RoundedRectangleBorder(
|
color: AppColor.cardColor,
|
||||||
borderRadius: BorderRadius.circular(14),
|
elevation: 0,
|
||||||
side: BorderSide(color: AppColor.borderColor),
|
shape: RoundedRectangleBorder(
|
||||||
),
|
borderRadius: BorderRadius.circular(14),
|
||||||
child: ListTile(
|
side: BorderSide(color: AppColor.borderColor),
|
||||||
leading: CircleAvatar(
|
),
|
||||||
backgroundColor: AppColor.accentColor.withOpacity(0.15),
|
child: ListTile(
|
||||||
child: Icon(Icons.directions_bus, color: AppColor.accentColor),
|
leading: CircleAvatar(
|
||||||
),
|
backgroundColor: AppColor.accentColor.withOpacity(0.15),
|
||||||
title: Text(r.nameAr, style: AppStyle.title),
|
child: Icon(Icons.directions_bus, color: AppColor.accentColor),
|
||||||
subtitle: Text('${r.stopCount} ${'Stops'.tr}', style: AppStyle.subtitle),
|
),
|
||||||
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
|
title: Text(r.nameAr, style: AppStyle.title),
|
||||||
onTap: () => Get.to(
|
subtitle: Text('${r.stopCount} ${'Stops'.tr}', style: AppStyle.subtitle),
|
||||||
() => TransitLiveMapPage(routeId: r.id, routeName: r.nameAr),
|
trailing: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
),
|
onTap: () => Get.to(
|
||||||
),
|
() => TransitLiveMapPage(routeId: r.id, routeName: r.nameAr),
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
),
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user