Frontend first draft
This commit is contained in:
34
frontend/pweb/lib/app/app.dart
Normal file
34
frontend/pweb/lib/app/app.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/config/constants.dart';
|
||||
import 'package:pshared/provider/locale.dart';
|
||||
|
||||
import 'package:pweb/app/router/router.dart';
|
||||
|
||||
import 'package:pshared/generated/i18n/ps_localizations.dart';
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
final _router = createRouter();
|
||||
|
||||
class PayApp extends StatelessWidget {
|
||||
const PayApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => MaterialApp.router(
|
||||
title: 'Profee Pay',
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Constants.themeColor),
|
||||
useMaterial3: true,
|
||||
),
|
||||
routerConfig: _router,
|
||||
localizationsDelegates: [
|
||||
...PSLocalizations.localizationsDelegates,
|
||||
...AppLocalizations.localizationsDelegates,
|
||||
],
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
locale: context.watch<LocaleProvider>().locale,
|
||||
);
|
||||
}
|
||||
70
frontend/pweb/lib/app/locale_manager.dart
Normal file
70
frontend/pweb/lib/app/locale_manager.dart
Normal file
@@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:intl/find_locale.dart';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:pshared/provider/locale.dart';
|
||||
|
||||
|
||||
String _localeVarStorageName() {
|
||||
return 'mcrm_last_locale';
|
||||
}
|
||||
|
||||
Locale _selectDefaultLocale(List<Locale> appLocales, Locale defaultLocale) {
|
||||
return appLocales.contains(defaultLocale)
|
||||
? defaultLocale
|
||||
: appLocales.isEmpty
|
||||
? throw ArgumentError('empty application locales list', 'appLocales')
|
||||
: appLocales.first;
|
||||
}
|
||||
|
||||
|
||||
class LocaleManager {
|
||||
late SharedPreferences _prefs;
|
||||
final List<Locale> appLocales;
|
||||
final Locale _defaultLocale;
|
||||
final LocaleProvider localeProvider;
|
||||
|
||||
LocaleManager(this.localeProvider, this.appLocales, Locale defaultLocale)
|
||||
: _defaultLocale = _selectDefaultLocale(appLocales, defaultLocale) {
|
||||
SharedPreferences.getInstance().then((prefs) {
|
||||
_prefs = prefs;
|
||||
_initializeLocaleProvider();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _initializeLocaleProvider() async {
|
||||
final initialLocale = await _getInitialLocale();
|
||||
localeProvider.setLocale(initialLocale);
|
||||
localeProvider.addListener(_onLocaleChanged);
|
||||
}
|
||||
|
||||
Future<Locale> _getInitialLocale() async {
|
||||
final locale = await _pickLocale();
|
||||
return appLocales.contains(locale) ? locale : _defaultLocale;
|
||||
}
|
||||
|
||||
Future<Locale> _pickLocale() async {
|
||||
String? savedLocaleCode = _prefs.getString(_localeVarStorageName());
|
||||
if (savedLocaleCode != null) {
|
||||
return Locale(savedLocaleCode);
|
||||
}
|
||||
|
||||
String systemLocaleString = await findSystemLocale();
|
||||
final List<String> localeParts = systemLocaleString.split('_');
|
||||
final Locale systemLocale = Locale(localeParts[0]);
|
||||
|
||||
final res = appLocales.contains(systemLocale);
|
||||
|
||||
return res ? systemLocale : _defaultLocale;
|
||||
}
|
||||
|
||||
Future<bool> saveLocale(Locale locale) async {
|
||||
return _prefs.setString(_localeVarStorageName(), locale.toString());
|
||||
}
|
||||
|
||||
Future<bool> _onLocaleChanged() async {
|
||||
return saveLocale(localeProvider.locale);
|
||||
}
|
||||
}
|
||||
15
frontend/pweb/lib/app/router/page_params.dart
Normal file
15
frontend/pweb/lib/app/router/page_params.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
enum PageParams {
|
||||
token,
|
||||
projectRef,
|
||||
roleRef,
|
||||
taskRef,
|
||||
invitationRef,
|
||||
}
|
||||
|
||||
String routerPageParam(PageParams param) {
|
||||
return ':${param.name}';
|
||||
}
|
||||
|
||||
String routerAddParam(PageParams param) {
|
||||
return '/${routerPageParam(param)}';
|
||||
}
|
||||
60
frontend/pweb/lib/app/router/pages.dart
Normal file
60
frontend/pweb/lib/app/router/pages.dart
Normal file
@@ -0,0 +1,60 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
enum Pages {
|
||||
root,
|
||||
sfactor,
|
||||
login,
|
||||
methods,
|
||||
verify,
|
||||
signup,
|
||||
settings,
|
||||
dashboard,
|
||||
profile,
|
||||
recipients,
|
||||
users,
|
||||
roles,
|
||||
permissions,
|
||||
invitations,
|
||||
}
|
||||
|
||||
String routerPath(String page) {
|
||||
return '/$page';
|
||||
}
|
||||
|
||||
String routerPage(Pages page) {
|
||||
return page == Pages.root ? '/' : routerPath(page.name);
|
||||
}
|
||||
|
||||
String _pagePath(Pages page, {String? objectRef}) => _pagesPath([page], objectRef: objectRef);
|
||||
|
||||
String _pagesPath(List<Pages> pages, {String? objectRef}) {
|
||||
final path = pages.map(routerPage).join();
|
||||
return objectRef != null ? '$path/$objectRef' : path;
|
||||
}
|
||||
|
||||
void navigateAndReplace(BuildContext context, Pages page, {String? objectRef, Object? extra}) {
|
||||
context.go(_pagePath(page, objectRef: objectRef), extra: extra);
|
||||
}
|
||||
|
||||
void navigate(BuildContext context, Pages page, {String? objectRef, Object? extra}) {
|
||||
navigatePages(context, [page], objectRef: objectRef, extra: extra);
|
||||
}
|
||||
|
||||
void navigatePages(BuildContext context, List<Pages> pages, {String? objectRef, Object? extra}) {
|
||||
context.push(_pagesPath(pages, objectRef: objectRef), extra: extra);
|
||||
}
|
||||
|
||||
void navigateNamed(BuildContext context, Pages page, {String? objectRef, Object? extra}) {
|
||||
context.pushNamed(page.name, extra: extra);
|
||||
}
|
||||
|
||||
|
||||
void navigateNamedAndReplace(BuildContext context, Pages page, {String? objectRef, Object? extra}) {
|
||||
context.replaceNamed(page.name, extra: extra);
|
||||
}
|
||||
|
||||
void navigateNext(BuildContext context, Pages page, {Object? extra}) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => navigate(context, page, extra: extra));
|
||||
}
|
||||
57
frontend/pweb/lib/app/router/router.dart
Normal file
57
frontend/pweb/lib/app/router/router.dart
Normal file
@@ -0,0 +1,57 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:pweb/app/router/pages.dart';
|
||||
import 'package:pweb/pages/2fa/page.dart';
|
||||
import 'package:pweb/pages/signup/page.dart';
|
||||
import 'package:pweb/widgets/sidebar/page.dart';
|
||||
import 'package:pweb/pages/login/page.dart';
|
||||
import 'package:pweb/pages/errors/not_found.dart';
|
||||
|
||||
GoRouter createRouter() => GoRouter(
|
||||
debugLogDiagnostics: true,
|
||||
routes: <RouteBase>[
|
||||
GoRoute(
|
||||
name: Pages.root.name,
|
||||
path: routerPage(Pages.root),
|
||||
builder: (_, __) => const LoginPage(),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: Pages.login.name,
|
||||
path: routerPage(Pages.login),
|
||||
builder: (_, __) => const LoginPage(),
|
||||
),
|
||||
GoRoute(
|
||||
name: Pages.dashboard.name,
|
||||
path: routerPage(Pages.dashboard),
|
||||
builder: (_, __) => const PageSelector(),
|
||||
),
|
||||
GoRoute(
|
||||
name: Pages.sfactor.name,
|
||||
path: routerPage(Pages.sfactor),
|
||||
builder: (context, state) {
|
||||
// Определяем откуда пришел пользователь
|
||||
final isFromSignup = state.uri.queryParameters['from'] == 'signup';
|
||||
|
||||
return TwoFactorCodePage(
|
||||
onVerificationSuccess: () {
|
||||
if (isFromSignup) {
|
||||
// После регистрации -> на страницу логина
|
||||
context.goNamed(Pages.login.name);
|
||||
} else {
|
||||
// После логина -> на дашборд
|
||||
context.goNamed(Pages.dashboard.name);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: Pages.signup.name,
|
||||
path: routerPage(Pages.signup),
|
||||
builder: (_, __) => const SignUpPage(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
errorBuilder: (_, __) => const NotFoundPage(),
|
||||
);
|
||||
27
frontend/pweb/lib/app/timeago.dart
Normal file
27
frontend/pweb/lib/app/timeago.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'package:timeago/timeago.dart' as timeago;
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart'; // Ensure this file exports supportedLocales
|
||||
|
||||
// Mapping of language codes to timeago message classes.
|
||||
final Map<String, timeago.LookupMessages> _timeagoLocales = {
|
||||
'en': timeago.EnMessages(),
|
||||
'ru': timeago.RuMessages(),
|
||||
'uk': timeago.UkMessages(),
|
||||
// Add more mappings as needed.
|
||||
};
|
||||
|
||||
/// Initializes timeago using the supported locales from AppLocalisations.
|
||||
/// Optionally, [defaultLocale] can be set (defaults to 'en').
|
||||
void initializeTimeagoLocales({String defaultLocale = 'en'}) {
|
||||
// Assume AppLocalisations.supportedLocales is a static List<Locale>
|
||||
final supportedLocales = AppLocalizations.supportedLocales;
|
||||
|
||||
for (final locale in supportedLocales) {
|
||||
final languageCode = locale.languageCode;
|
||||
if (_timeagoLocales.containsKey(languageCode)) {
|
||||
timeago.setLocaleMessages(languageCode, _timeagoLocales[languageCode]!);
|
||||
}
|
||||
}
|
||||
// Set the default locale.
|
||||
timeago.setDefaultLocale(defaultLocale);
|
||||
}
|
||||
Reference in New Issue
Block a user