Skip to content

Commit

Permalink
Add resident payment page
Browse files Browse the repository at this point in the history
  • Loading branch information
Serious-senpai committed Nov 27, 2024
1 parent fcdb8b7 commit d562bd0
Show file tree
Hide file tree
Showing 14 changed files with 1,156 additions and 786 deletions.
2 changes: 1 addition & 1 deletion app/resident_manager/lib/src/config.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
final epoch = DateTime.utc(2024, 1, 1);
const int DB_PAGINATION_QUERY = 50;
const DB_PAGINATION_QUERY = 50;
const DEFAULT_ADMIN_USERNAME = "admin";
const DEFAULT_ADMIN_PASSWORD = "NgaiLongGey";
44 changes: 44 additions & 0 deletions app/resident_manager/lib/src/models/fee.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import "snowflake.dart";
import "../utils.dart";

class Fee with Snowflake {
@override
final int id;

final String name;
final double lower;
final double upper;
final double perArea;
final double perMotorbike;
final double perCar;
final Date deadline;
final String description;
final int flags;

Fee({
required this.id,
required this.name,
required this.lower,
required this.upper,
required this.perArea,
required this.perMotorbike,
required this.perCar,
required this.deadline,
required this.description,
required this.flags,
});

Fee.fromJson(dynamic data)
: this(
id: data["id"] as int,
name: data["name"] as String,
lower: data["lower"] as double,
upper: data["upper"] as double,
perArea: data["per_area"] as double,
perMotorbike: data["per_motorbike"] as double,
perCar: data["per_car"] as double,
deadline: Date.parse(data["deadline"] as String)!,
description: data["description"] as String,
flags: data["flags"] as int,
);
}
25 changes: 25 additions & 0 deletions app/resident_manager/lib/src/models/payment.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import "snowflake.dart";

class Payment with Snowflake {
@override
final int id;

final int room;
final double amount;
final int feeId;

Payment({
required this.id,
required this.room,
required this.amount,
required this.feeId,
});

Payment.fromJson(dynamic data)
: this(
id: data["id"] as int,
room: data["room"] as int,
amount: data["amount"] as double,
feeId: data["fee_id"] as int,
);
}
52 changes: 52 additions & 0 deletions app/resident_manager/lib/src/models/payment_status.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import "dart:convert";

import "fee.dart";
import "payment.dart";
import "results.dart";
import "../state.dart";

class PaymentStatus {
final Fee fee;
final double lowerBound;
final double upperBound;
final Payment? payment;

PaymentStatus({
required this.fee,
required this.lowerBound,
required this.upperBound,
required this.payment,
});

PaymentStatus.fromJson(dynamic data)
: this(
fee: Fee.fromJson(data["fee"]),
lowerBound: data["lower_bound"] as double,
upperBound: data["upper_bound"] as double,
payment: data["payment"] == null ? null : Payment.fromJson(data["payment"]),
);

static Future<Result<List<PaymentStatus>?>> query({
required ApplicationState state,
required int offset,
required DateTime createdFrom,
required DateTime createdTo,
}) async {
final response = await state.get(
"/api/v1/residents/fee",
queryParameters: {
"offset": offset.toString(),
"created_from": createdFrom.toUtc().toIso8601String(),
"created_to": createdTo.toUtc().toIso8601String(),
},
);
final result = json.decode(utf8.decode(response.bodyBytes));

if (response.statusCode == 200) {
final data = result["data"] as List<dynamic>;
return Result(0, List<PaymentStatus>.from(data.map(PaymentStatus.fromJson)));
}

return Result(result["code"], null);
}
}
27 changes: 27 additions & 0 deletions app/resident_manager/lib/src/translations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ class AppLocale {
static const String Payment = "Payment";
static const String Admin = "Admin";
static const String NotYetLoggedIn = "NotYetLoggedIn";
static const String NoData = "NoData";
static const String AmountPaid = "AmountPaid";
static const String NotPaid = "NotPaid";
static const String Deadline = "Deadline";
static const String PaymentHistory = "PaymentHistory";
static const String Fee = "Fee";
static const String Description = "Description";
static const String Minimum = "Minimum";
static const String Maximum = "Maximum";

// Error codes
static const String Error0 = "Error0";
Expand Down Expand Up @@ -181,6 +190,15 @@ class AppLocale {
Payment: "Payment",
Admin: "Admin",
NotYetLoggedIn: "Not yet logged in",
NoData: "No data available.",
AmountPaid: "Amount paid",
NotPaid: "Not paid",
Deadline: "Deadline",
PaymentHistory: "Payment history",
Fee: "Fee",
Description: "Description",
Minimum: "Minimum",
Maximum: "Maximum",

// Error codes
Error0: "Operation completed successfully.",
Expand Down Expand Up @@ -283,6 +301,15 @@ class AppLocale {
Payment: "Thanh toán",
Admin: "Quản trị viên",
NotYetLoggedIn: "Chưa đăng nhập",
NoData: "Không có dữ liệu.",
AmountPaid: "Số tiền đã trả",
NotPaid: "Chưa thanh toán",
Deadline: "Hạn thanh toán",
PaymentHistory: "Lịch sử thanh toán",
Fee: "Phí",
Description: "Mô tả",
Minimum: "Tối thiểu",
Maximum: "Tối đa",

// Error codes
Error0: "Thao tác thành công.",
Expand Down
42 changes: 19 additions & 23 deletions app/resident_manager/lib/src/widgets/admin/home.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import "package:flutter/material.dart";
import "package:flutter_localization/flutter_localization.dart";
import "package:one_clock/one_clock.dart";
import "package:resident_manager/src/routes.dart";

import "../common.dart";
import "../state.dart";
import "../../routes.dart";
import "../../translations.dart";
import "../../utils.dart";

Expand All @@ -23,31 +23,27 @@ class _CardBuilder {
_CardBuilder({this.backgroundColor, this.onPressed, required this.children});

Widget call(int flex) {
return Builder(
builder: (context) {
return _ShrinkableFlex(
flex: flex,
child: Container(
return _ShrinkableFlex(
flex: flex,
child: Container(
padding: const EdgeInsets.all(5),
child: ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: backgroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: Padding(
padding: const EdgeInsets.all(5),
child: ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: backgroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: Padding(
padding: const EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: children,
),
),
);
},
),
),
);
}
}
Expand Down
18 changes: 2 additions & 16 deletions app/resident_manager/lib/src/widgets/admin/reg_queue.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "package:flutter_localization/flutter_localization.dart";

import "../common.dart";
import "../state.dart";
import "../utils.dart";
import "../../config.dart";
import "../../state.dart";
import "../../translations.dart";
Expand Down Expand Up @@ -204,22 +205,7 @@ class _RegisterQueuePageState extends AbstractCommonState<RegisterQueuePage> wit
initialData: queryLoader.lastData,
builder: (context, _) {
if (queryLoader.isLoading) {
return SliverFillRemaining(
hasScrollBody: false,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox.square(
dimension: 50,
child: CircularProgressIndicator(),
),
const SizedBox.square(dimension: 5),
Text(AppLocale.Loading.getString(context)),
],
),
),
);
return const SliverCircularProgressFullScreen();
}

final code = queryLoader.lastData;
Expand Down
Loading

0 comments on commit d562bd0

Please sign in to comment.