Frontend first draft

This commit is contained in:
Arseni
2025-11-13 15:06:15 +03:00
parent e47f343afb
commit ddb54ddfdc
504 changed files with 25498 additions and 1 deletions

View 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,
);
}

View 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);
}
}

View 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)}';
}

View 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));
}

View 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(),
);

View 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);
}