Skip to content

Commit

Permalink
Merge pull request #45 from thaidmfinnick/develop
Browse files Browse the repository at this point in the history
improve(mobile): build 1.0.0+16
  • Loading branch information
thaidmfinnick authored Jan 2, 2025
2 parents 0cb543c + 622c0c6 commit b646ae9
Show file tree
Hide file tree
Showing 14 changed files with 242 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,8 @@ defmodule CecrUnwomenWeb.ContributionController do
end

today = Helper.get_vietnam_date_today()
{start_month, end_month} = {Date.beginning_of_month(today), Date.end_of_month(today)}
# {start_month, end_month} = {Date.beginning_of_month(today), Date.end_of_month(today)}
{start_month, end_month} = {Date.new!(2024, 11, 01), Date.end_of_month(today)}
overall_data_one_month = get_overall_contribution_one_month(user_id, role_id, start_month, end_month)

sum_factors = if role_id == 2 do
Expand Down Expand Up @@ -346,7 +347,8 @@ defmodule CecrUnwomenWeb.ContributionController do
scraper_overall_data = Helper.aggregate_with_fields(OverallScraperContribution, keys) |> Map.put(:count_scraper, count_scraper_user)

today = Helper.get_vietnam_date_today()
{start_month, end_month} = {Date.beginning_of_month(today), Date.end_of_month(today)}
# {start_month, end_month} = {Date.beginning_of_month(today), Date.end_of_month(today)}
{start_month, end_month} = {Date.new!(2024, 11, 01), Date.end_of_month(today)}
{overall_scrapers_one_month, overall_households_one_month} = get_user_contributions_by_range(start_month, end_month)
{scraper_total_kgco2e_seven_days, household_total_kgco2e_seven_days} = get_total_kgco2e_seven_days()

Expand Down
20 changes: 18 additions & 2 deletions api/lib/cecr_unwomen_web/controllers/user_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defmodule CecrUnwomenWeb.UserController do

is_ready_to_insert = !is_nil(first_name) && !is_nil(last_name) && is_pass_password
response = cond do
!is_pass_phone_number -> Helper.response_json_message(false, "Số điện thoại không đúng hoặc đã tồn tại!", 279)
!is_pass_phone_number -> Helper.response_json_message(false, "Số điện thoại đã tồn tại hoặc đã bị xoá khỏi hệ thống", 279)
!is_ready_to_insert -> Helper.response_json_message(false, "Bạn nhập thiếu các thông tin cần thiết! Vui lòng kiểm tra lại!", 301)
!is_pass_admin_role -> Helper.response_json_message(false, "Bạn không thể đăng ký làm admin!", 301)
true ->
Expand Down Expand Up @@ -89,7 +89,7 @@ defmodule CecrUnwomenWeb.UserController do
!is_pass_phone_number -> Helper.response_json_message(false, "Không tìm thấy số điện thoại!", 280)
!is_pass_password_length -> Helper.response_json_message(false, "Sai số điện thoại hoặc mật khẩu", 301)
true ->
from(u in User, where: u.phone_number == ^phone_number, select: u)
from(u in User, where: u.phone_number == ^phone_number and u.is_removed != true, select: u)
|> Repo.one
|> case do
nil -> Helper.response_json_message(false, "Không tìm thấy tài khoản!", 302)
Expand Down Expand Up @@ -130,6 +130,22 @@ defmodule CecrUnwomenWeb.UserController do
json conn, res
end

def delete_user(conn, _params) do
user_id = conn.assigns.user.user_id
res = Repo.get_by(User, %{id: user_id, is_removed: false})
|> case do
nil -> Helper.response_json_message(false, "Không tìm thấy người dùng!", 300)
user ->
Ecto.Changeset.change(user, %{is_removed: true, refresh_token: nil})
|> Repo.update
|> case do
{:ok, _} -> Helper.response_json_message(true, "Xóa người dùng thành công!")
_ -> Helper.response_json_message(false, "Có lỗi xảy ra!", 303)
end
end
json conn, res
end

def logout(conn, params) do
user_id = params["user_id"]

Expand Down
3 changes: 2 additions & 1 deletion api/lib/cecr_unwomen_web/models/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ defmodule CecrUnwomenWeb.Models.User do
field :location, :string
field :refresh_token, :string
field :verified, :boolean
field :is_removed, :boolean, default: false

belongs_to :role, Role, foreign_key: :role_id, type: :integer
timestamps()
end

@required_fields [:id, :first_name, :last_name, :phone_number, :password_hash, :role_id, :refresh_token]
@optional_fields [:avatar_url, :email, :gender, :date_of_birth, :location, :verified]
@optional_fields [:avatar_url, :email, :gender, :date_of_birth, :location, :verified, :is_removed]

def changeset(user, params \\ %{}) do
user
Expand Down
1 change: 1 addition & 0 deletions api/lib/cecr_unwomen_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ defmodule CecrUnwomenWeb.Router do

pipe_through :token
post "/logout", UserController, :logout
post "/delete_user", UserController, :delete_user
post "/get_info", UserController, :get_info
post "/update_info", UserController, :update_info
post "/change_password", UserController, :change_password
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule CecrUnwomen.Repo.Migrations.AddFieldIsRemovedUserTable do
use Ecto.Migration

def change do
alter table(:user) do
add :is_removed, :boolean, default: false
end
end
end
1 change: 1 addition & 0 deletions mobile/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ app.*.map.json

pubspec.lock
*/Podfile.lock
/android/key.properties

# FVM Version Cache
.fvm/
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState>
on<LogoutRequest>(_onLogoutRequest);
on<AutoLogin>(_onAutoLogin);
on<UpdateInfo>(_onUpdateInfo);
on<DeleteAccount>(_onDeleteAccount);
}

Future<void> _onAuthSubscription(AuthSubscription event, Emitter emit) async {
Expand Down Expand Up @@ -61,6 +62,10 @@ class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState>
}
}

void _onDeleteAccount(DeleteAccount event, Emitter emit) {
AuthRepository.deleteAccount();
}

Future<void> _onUpdateInfo(UpdateInfo event, Emitter emit) async {
try {
emit(state.copyWith(status: AuthenticationStatus.authorized, user: event.user));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class AuthSubscription extends AuthenticationEvent {}

class LogoutRequest extends AuthenticationEvent {}

class DeleteAccount extends AuthenticationEvent {}

class AutoLogin extends AuthenticationEvent {}

class UpdateInfo extends AuthenticationEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ class AuthenticationApi {
const String url = "/user/logout";
await dioConfigInterceptor.post(url, data: {"user_id": userId});
}

static Future<Map> deleteUser() async {
const String url = "/user/delete_user";
final Response response = await dioConfigInterceptor.post(url);
return response.data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ class AuthRepository {
}
}

static Future<void> deleteAccount() async {
try {
final Map res = await AuthenticationApi.deleteUser();
final bool isSuccess = res["success"];
if (isSuccess) {
await AuthRepository.logoutNoCredentials();
_controller.add(AuthenticationStatus.unauthorized);
} else {
_controller.add(AuthenticationStatus.authorized);
// _controller.add(AuthenticationStatus.authorized);
}
} catch (e) {
print('gndkjf:$e');
_controller.add(AuthenticationStatus.error);
}
}

static Future<void> logout() async {
await AuthRepository.logoutNoCredentials();
// await AuthenticationApi.logout(userId);
Expand Down
9 changes: 9 additions & 0 deletions mobile/lib/features/user/view/user_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ class _UserInfoState extends State<UserInfo> {
context.read<AuthenticationBloc>().add(LogoutRequest());
},
),
NavigationButton(
text: "Xóa tài khoản",
isWarning: true,
icon: PhosphorIcons.regular.userMinus,
onTap: () {
context.read<AuthenticationBloc>().add(DeleteAccount());
// context.read<AuthenticationBloc>().add(LogoutRequest());
},
),
],
),
),
Expand Down
118 changes: 118 additions & 0 deletions mobile/lib/widgets/confirm_card.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import 'package:flutter/material.dart';

class ConfirmCard extends StatelessWidget {
const ConfirmCard({
super.key,
this.user,
this.bigIcon,
required this.title,
required this.subtitle,
required this.dangerousTextInButton,
this.onClick,
});

final Map? user;
final Widget? bigIcon;
final String title;
final String subtitle;
final String dangerousTextInButton;
final VoidCallback? onClick;

// use with showDialog, showCupertinoDialog

@override
Widget build(BuildContext context) {
const Color backgroundColorHeader = Colors.white;
const Color colorBackButton = Color(0xFF1D2939);

return Material(
color : Colors.transparent,
child: Dialog(
child: Wrap(
children: [
Container(
// height: 270,
width: 327,
decoration: BoxDecoration(
color: backgroundColorHeader,
borderRadius: BorderRadius.circular(8)
),
padding: const EdgeInsets.only(left: 20, right: 20, top: 16, bottom: 10),
child: Column(children: [
// else if (bigIcon != null) bigIcon!
// else Container(),

const SizedBox(height: 14),

Text(title,
style: const TextStyle(fontSize: 16,
fontWeight: FontWeight.w700,
)),
const SizedBox(height: 12),
Text(subtitle,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: Color(0xFF667085)
),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),

SizedBox(
height: 44,
width: 300,
child: ElevatedButton(
onPressed: () {
if (onClick != null) {
onClick!.call();
}
},
style: ButtonStyle(
backgroundColor: const WidgetStatePropertyAll(Color(0xFFFF3048)),
shape: WidgetStatePropertyAll(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))
),
padding: const WidgetStatePropertyAll(EdgeInsets.symmetric(vertical: 10))
),
child: Text(dangerousTextInButton,
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600,
)
)
)
),
const SizedBox(height: 14),

SizedBox(
height: 44,
width: 300,
child: TextButton(
onPressed: () {
Navigator.pop(context);
},
style: ButtonStyle(
shape: WidgetStatePropertyAll(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))
),
padding: const WidgetStatePropertyAll(EdgeInsets.symmetric(vertical: 10))
),
child: const Text("Hủy",
style: TextStyle(
color: colorBackButton,
fontSize: 16,
fontWeight: FontWeight.w600,
)
),
),
),
]),
),
],
),
),
);
}
}
79 changes: 49 additions & 30 deletions mobile/lib/widgets/navigation_button.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:cecr_unwomen/widgets/confirm_card.dart';
import 'package:flutter/material.dart';
import 'package:flutter_switch/flutter_switch.dart';
import 'package:phosphor_flutter/phosphor_flutter.dart';
Expand Down Expand Up @@ -61,38 +62,56 @@ class NavigationButton extends StatelessWidget {
margin: const EdgeInsets.only(bottom: 12),
child: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () => onTap == null ? null : onTap!(),
onTap: () async {
if (isWarning) {
final bool? isConfirm = await showDialog(
context: context,
builder: (context) => ConfirmCard(
title: "Xác nhận ${text.toLowerCase()}",
subtitle: "Bạn có chắc chắn muốn thực hiện hành động này?",
dangerousTextInButton: "Xác nhận",
onClick: () {
Navigator.pop(context, true);
},
),
);
if (isConfirm == null) return;
onTap?.call();
} else {
onTap?.call();
}
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Row(
crossAxisAlignment: subTitleWidget != null ? CrossAxisAlignment.start : CrossAxisAlignment.center,
children: [
Container(
width: 36,
height: 36,
decoration: BoxDecoration(
color: iconBgColor,
shape: BoxShape.circle,
),
child: Icon(icon, size: 20, color: iconColor),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Row(
crossAxisAlignment: subTitleWidget != null ? CrossAxisAlignment.start : CrossAxisAlignment.center,
children: [
Container(
width: 36,
height: 36,
decoration: BoxDecoration(
color: iconBgColor,
shape: BoxShape.circle,
),
const SizedBox(width: 14),
Flexible(
child: subTitleWidget != null
? Column(
children: [
option,
subTitleWidget ?? Container(),
],
)
: option,
),
],
)),
child: Icon(icon, size: 20, color: iconColor),
),
const SizedBox(width: 14),
Flexible(
child: subTitleWidget != null
? Column(
children: [
option,
subTitleWidget ?? Container(),
],
)
: option,
),
],
)),
),
),
);
Expand Down
Loading

0 comments on commit b646ae9

Please sign in to comment.