Skip to content

Commit

Permalink
Merge branch 'main' into prod/festapp
Browse files Browse the repository at this point in the history
  • Loading branch information
miakh committed Nov 10, 2024
2 parents 7fafc9f + b9644fc commit 46fffe0
Show file tree
Hide file tree
Showing 19 changed files with 444 additions and 116 deletions.
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ if (flutterVersionName == null) {
android {
namespace = "fstapp.fstapp"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
ndkVersion = "25.1.8937393"

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down
4 changes: 3 additions & 1 deletion assets/translations/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@
"Welcome in {name}!": "Vítejte v aplikaci {name}!",
"Invite": "Pozvat",
"Invited": "Pozván",
"Users will get invitation via e-mail.": "Uživatelé obdrží pozvánku e-mailem.",
"Invite users who have already been invited?": "Pozvat i uživatele, kteří již byli pozváni?",
"Invited: {user}.": "Pozván: {user}.",
"Token is not valid.": "Token není platný.",
Expand Down Expand Up @@ -258,5 +257,8 @@
"Food": "Jídlo",
"To create food, fill in the title, unique code, and the reference of the event.": "Pro vytvoření jídla vyplňte název, jedinečný kód a referenci na program.",
"Not specified": "Nespecifikováno",
"Users will get a sign in code via e-mail.": "Uživatelé obdrží přihlašovací kód e-mailem.",
"Users ({count}) invited successfully.": "Uživatelé ({count}) byli úspěšně pozváni.",
"Progress": "Postup",
"_": "_"
}
4 changes: 3 additions & 1 deletion assets/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@
"Welcome in {name}!": "Willkommen in {name}!",
"Invite": "Einladen",
"Invited": "Eingeladen",
"Users will get invitation via e-mail.": "Benutzer erhalten eine Einladung per E-Mail.",
"Invite users who have already been invited?": "Benutzer einladen, die bereits eingeladen wurden?",
"Invited: {user}.": "Eingeladen: {user}.",
"Token is not valid.": "Token ist ungültig.",
Expand Down Expand Up @@ -258,5 +257,8 @@
"Food": "Essen",
"To create food, fill in the title, unique code, and the reference of the event.": "Um Essen zu erstellen, füllen Sie den Titel, den eindeutigen Code und die Referenz des Programms aus.",
"Not specified": "Nicht angegeben",
"Users will get a sign in code via e-mail.": "Benutzer erhalten einen Anmeldecode per E-Mail.",
"Users ({count}) invited successfully.": "Benutzer ({count}) wurden erfolgreich eingeladen.",
"Progress": "Fortschritt",
"_": "_"
}
4 changes: 3 additions & 1 deletion assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@
"Welcome in {name}!": "Welcome in {name}!",
"Invite": "Invite",
"Invited": "Invited",
"Users will get invitation via e-mail.": "Users will get invitation via e-mail.",
"Invite users who have already been invited?": "Invite users who have already been invited?",
"Invited: {user}.": "Invited: {user}.",
"Token is not valid.": "Token is not valid.",
Expand Down Expand Up @@ -258,5 +257,8 @@
"Food": "Food",
"To create food, fill in the title, unique code, and the reference of the event.": "To create food, fill in the title, unique code, and the reference of the event.",
"Not specified": "Not specified",
"Users will get a sign in code via e-mail.": "Users will get a sign in code via e-mail.",
"Users ({count}) invited successfully.": "Users ({count}) invited successfully.",
"Progress": "Progress",
"_":"_"
}
4 changes: 3 additions & 1 deletion assets/translations/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@
"Welcome in {name}!": "Witaj w {name}!",
"Invite": "Zaproś",
"Invited": "Zaproszony",
"Users will get invitation via e-mail.": "Użytkownicy otrzymają zaproszenie drogą e-mailową.",
"Invite users who have already been invited?": "Zaprosić użytkowników, którzy już zostali zaproszeni?",
"Invited: {user}.": "Zaproszony: {user}.",
"Token is not valid.": "Token nie jest ważny.",
Expand Down Expand Up @@ -257,5 +256,8 @@
"Food": "Jedzenie",
"To create food, fill in the title, unique code, and the reference of the event.": "Aby utworzyć jedzenie, wypełnij tytuł, unikalny kod i odniesienie do programu.",
"Not specified": "Nieokreślony",
"Users will get a sign in code via e-mail.": "Użytkownicy otrzymają kod logowania za pomocą e-maila.",
"Users ({count}) invited successfully.": "Użytkownicy ({count}) zostali pomyślnie zaproszeni.",
"Progress": "Postęp",
"_": "_"
}
4 changes: 3 additions & 1 deletion assets/translations/sk.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@
"Invite": "Pozvať",
"You can sign in from {time}.": "Môžeš sa prihlásiť od času {time}.",
"Invited": "Pozvaný",
"Users will get invitation via e-mail.": "Používatelia dostanú pozvánku e-mailom.",
"Invite users who have already been invited?": "Pozvať používateľov, ktorí už boli pozvaní?",
"Invited: {user}.": "Pozvaný: {user}.",
"Token is not valid.": "Token nie je platný.",
Expand Down Expand Up @@ -258,5 +257,8 @@
"Food": "Jedlo",
"To create food, fill in the title, unique code, and the reference of the event.": "Na vytvorenie jedla vyplňte názov, jedinečný kód a referenciu na program.",
"Not specified": "Neurčené",
"Users will get a sign in code via e-mail.": "Používatelia dostanú prihlasovací kód e-mailom.",
"Users ({count}) invited successfully.": "Používatelia ({count}) boli úspešne pozvaní.",
"Progress": "Postup",
"_": "_"
}
4 changes: 3 additions & 1 deletion assets/translations/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@
"Welcome in {name}!": "Ласкаво просимо до {name}!",
"Invite": "Запросити",
"Invited": "Запрошено",
"Users will get invitation via e-mail.": "Користувачі отримають запрошення по електронній пошті.",
"Invite users who have already been invited?": "Запросити користувачів, які вже були запрошені?",
"Invited: {user}.": "Запрошено: {user}.",
"Token is not valid.": "Токен недійсний.",
Expand Down Expand Up @@ -258,5 +257,8 @@
"Food": "Їжа",
"To create food, fill in the title, unique code, and the reference of the event.": "Щоб створити їжу, заповніть назву, унікальний код та посилання на програму.",
"Not specified": "Не вказано",
"Users will get a sign in code via e-mail.": "Користувачі отримають код для входу на електронну пошту.",
"Users ({count}) invited successfully.": "Користувачі ({count}) успішно запрошені.",
"Progress": "Прогрес",
"_": "_"
}
20 changes: 0 additions & 20 deletions lib/dataModels/UserInfoModel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class UserInfoModel {
String? sex;
String? role;
String? phone;
String? accommodation;
DateTime? birthDate;
bool? isAdmin = false;
bool? isEditor = false;
Expand Down Expand Up @@ -61,7 +60,6 @@ class UserInfoModel {
this.isAdmin,
this.isEditor,
this.phone,
this.accommodation,
this.accommodationPlace,
this.userGroup,
this.occasionUser,
Expand All @@ -78,12 +76,6 @@ class UserInfoModel {
email: json[emailReadonlyColumn]??json[Tb.user_info.data]?[Tb.occasion_users.data_email]??json["email"],
name: json[nameColumn],
surname: json[surnameColumn],
//todo remove
phone: json[phoneColumn],
//todo remove
role: json[roleColumn],
//todo remove
accommodation: json[accommodationColumn],
accommodationPlace: json[placeColumn]!=null?PlaceModel.fromJson(json[placeColumn]):null,
userGroup: json[userGroupColumn]!=null?UserGroupInfoModel.fromJson(json[userGroupColumn]):null,
occasionUser: json[occasionUserColumn]!=null?OccasionUserModel.fromJson(json[occasionUserColumn]):null,
Expand Down Expand Up @@ -143,18 +135,6 @@ class UserInfoModel {

return "Not specified".tr();
}
bool importedEquals(Map<String, dynamic> u) {
return
u[emailReadonlyColumn].toString().trim().toLowerCase() == email
&& u[nameColumn].toString().trim() == name
&& u[surnameColumn].toString().trim() == surname
&& u[accommodationColumn].toString().trim() == accommodation
&& u[roleColumn].toString().trim() == role
&& u[phoneColumn].toString().trim() == phone
//todo fix
//&& ((u.containsKey(birthDateColumn) && u[birthDateColumn] != null) ? DateTime.parse(u[birthDateColumn]):null) == birthDate
&& (u[sexColumn].toString().trim().toLowerCase().startsWith("m") ? "male" : "female") == sex;
}

@override
int get hashCode {
Expand Down
6 changes: 5 additions & 1 deletion lib/dataServices/AuthService.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ class AuthService {
}

static Future<dynamic> resetPasswordForEmail(String email) async {
return await _supabase.functions.invoke("email", body: {"email": email, "organization": AppConfig.organization});
return await _supabase.functions.invoke("send-reset-password-link", body: {"email": email, "organization": AppConfig.organization});
}

static Future<dynamic> sendSignInCode(OccasionUserModel ou) async {
return await _supabase.functions.invoke("send-sign-in-code", body: {"oc": ou.occasion, "usr": ou.user,});
}

static UserInfoModel? currentUser;
Expand Down
1 change: 0 additions & 1 deletion lib/dataServices/DataService.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class ImportService {
Tb.occasion_users.data_name: userInfo.name,
Tb.occasion_users.data_surname: userInfo.surname,
Tb.occasion_users.data_phone: userInfo.phone,
Tb.occasion_users.data_accommodation: userInfo.accommodation,
Tb.occasion_users.data_birthDate: userInfo.birthDate?.toIso8601String(),
Tb.occasion_users.data_isInvited: true,
}
Expand Down
41 changes: 36 additions & 5 deletions lib/pages/AdministrationOccasion/UsersTab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,46 @@ class _UsersTabState extends State<UsersTab> {
}

Future<void> _processInvites(List<OccasionUserModel> users, SingleTableDataGrid dataGrid) async {
var confirm = await DialogHelper.showConfirmationDialogAsync(context, "Invite".tr(), "${"Users will get invitation via e-mail.".tr()} (${users.length}):\n${users.map((u) => u.toBasicString()).join(",\n")}");
var confirm = await DialogHelper.showConfirmationDialogAsync(
context,
"Invite".tr(),
"${"Users will get a sign in code invitation via e-mail.".tr()} (${users.length}):\n${users.map((u) => u.toBasicString()).join(",\n")}"
);

if (confirm) {
ValueNotifier<int> invitedCount = ValueNotifier(0);

// Show the progress dialog and update the count via the notifier
DialogHelper.showProgressDialogAsync(
context,
"Invite".tr(),
users.length,
invitedCount,
);

for (var user in users) {
await AuthService.resetPasswordForEmail(user.data![Tb.occasion_users.data_email]);
user.data![Tb.occasion_users.data_isInvited] = true;
await DbUsers.updateOccasionUser(user);
ToastHelper.Show(context, "Invited: {user}.".tr(namedArgs: {"user": user.data![Tb.occasion_users.data_email]}));
await AuthService.sendSignInCode(user);
invitedCount.value++;

// Show toast notification after each invitation
ToastHelper.Show(
context,
"Invited: {user}.".tr(namedArgs: {"user": user.data![Tb.occasion_users.data_email]}),
);
}

// Close the dialog after all users are invited
Navigator.of(context).pop();

await loadUsers(); // Reload users and force rebuild

// Display final information dialog
await DialogHelper.showInformationDialogAsync(
context,
"Invite".tr(),
"Users ({count}) invited successfully.".tr(namedArgs: {"count": invitedCount.value.toString()}),
);

}
}
}
3 changes: 1 addition & 2 deletions lib/pages/SignupPage.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/cupertino.dart';
import 'package:fstapp/RouterService.dart';
import 'package:fstapp/appConfig.dart';
import 'package:fstapp/dataServices/AuthService.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:fstapp/services/FormHelper.dart';
Expand Down Expand Up @@ -69,7 +68,7 @@ class _SignupPageState extends State<SignupPage> {
text: TextSpan(
children: [
TextSpan(
style: const TextStyle(fontSize: 18, color: Colors.black),
style: TextStyle(fontSize: 18, color: ThemeConfig.blackColor(context)),
text: "Almost done! Your credentials for signing in to the app have been sent to your email {email}. Please check your inbox to complete the registration.".tr(namedArgs: {"email": fieldsData?["email"]}),
),
const WidgetSpan(
Expand Down
30 changes: 30 additions & 0 deletions lib/services/DialogHelper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -303,4 +303,34 @@ class DialogHelper{
);
return result;
}

static Future<void> showProgressDialogAsync(
BuildContext context,
String title,
int total,
ValueNotifier<int> progressNotifier,
) async {
await showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return ValueListenableBuilder<int>(
valueListenable: progressNotifier,
builder: (context, progress, _) {
return AlertDialog(
title: Text(title),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("${"Progress".tr()}: $progress/$total"),
SizedBox(height: 20),
LinearProgressIndicator(value: total > 0 ? progress / total : 0),
],
),
);
},
);
},
);
}
}
2 changes: 1 addition & 1 deletion lib/services/MailerSendHelper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class MailerSendHelper{

allVars.addAll(_getSalutationPresalutation(recipient));
await ImportService.emailMailerSend(recipient.email!, "templateid", allVars);
ToastHelper.Show("E-mail with credentials was sent to: {email}.".tr(namedArgs: {"email":recipient.email!}));
//ToastHelper.Show("E-mail with credentials was sent to: {email}.".tr(namedArgs: {"email":recipient.email!}));
await Future.delayed(const Duration(milliseconds: 6000));
}

Expand Down
69 changes: 69 additions & 0 deletions supabase/functions/_shared/emailClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// _shared/emailClient.ts
import { SMTPClient } from "https://deno.land/x/denomailer/mod.ts";

const _SMTP_HOSTNAME = Deno.env.get("SMTP_HOSTNAME")!;
const _SMTP_USER_NAME = Deno.env.get("SMTP_USER_NAME")!;
const _SMTP_USER_PASSWORD = Deno.env.get("SMTP_USER_PASSWORD")!;
const _DEFAULT_EMAIL = Deno.env.get("DEFAULT_EMAIL")!;

const smtpClient = new SMTPClient({
connection: {
hostname: _SMTP_HOSTNAME,
port: 465,
tls: true,
auth: {
username: _SMTP_USER_NAME,
password: _SMTP_USER_PASSWORD,
},
},
});

export async function sendEmail({
to,
subject,
html,
from = `${_DEFAULT_EMAIL}`,
}: {
to: string;
subject: string;
html: string;
from?: string;
}) {
try {
await smtpClient.send({
from,
to,
subject,
html,
});
console.log("Email sent successfully to:", to);
} catch (error) {
console.error("Failed to send email:", error);
} finally {
await smtpClient.close();
}
}

export async function sendEmailWithSubs({
to,
subject,
content,
subs,
from = `${_DEFAULT_EMAIL}`,
}: {
to: string;
subject: string;
content: string;
subs: Record<string, string>;
from?: string;
}) {
// Replace placeholders in content with values from subs
let html = content;
for (const [key, value] of Object.entries(subs)) {
const placeholder = `{{${key}}}`;
html = html.replaceAll(placeholder, value);
}

// Use the sendEmail function to send the processed email
await sendEmail({ to, subject, html, from });
}
Loading

0 comments on commit 46fffe0

Please sign in to comment.