adding multilingual support
This commit is contained in:
@@ -7,6 +7,15 @@
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
analyzer:
|
||||
exclude:
|
||||
- build/**
|
||||
- android/**
|
||||
- ios/**
|
||||
- web/**
|
||||
- windows/**
|
||||
- macos/**
|
||||
- linux/**
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"student": "Student",
|
||||
"create_student": "Create Student",
|
||||
"update_student": "Update Student",
|
||||
"name": "Name",
|
||||
"phone_number": "Phone Number",
|
||||
"email": "Email"
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"student": "छात्र",
|
||||
"create_student": "छात्र बनाएँ",
|
||||
"update_student": "छात्र अपडेट करें",
|
||||
"name": "नाम",
|
||||
"phone_number": "फ़ोन नंबर",
|
||||
"email": "ईमेल"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
arb-dir: lib/l10n
|
||||
template-arb-file: app_en.arb
|
||||
output-localization-file: app_localizations.dart
|
||||
output-dir: lib/l10n
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:typed_data';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'base_field.dart';
|
||||
import '../utils/entity_field_store.dart';
|
||||
@@ -63,7 +64,9 @@ class AudioUploadField extends BaseField {
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.audiotrack_rounded),
|
||||
label: const Text('Add Audio'),
|
||||
label: Builder(
|
||||
builder: (ctx) =>
|
||||
Text(AppLocalizations.of(ctx)!.addAudio)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
import '../../../shared/widgets/inputs/modern_text_field.dart';
|
||||
|
||||
@@ -255,7 +256,7 @@ class _AutocompleteMultiSelectWidgetState
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'No results',
|
||||
AppLocalizations.of(context)!.noResults,
|
||||
style: TextStyle(
|
||||
color:
|
||||
widget.colorScheme.onSurfaceVariant),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'package:barcode_widget/barcode_widget.dart';
|
||||
import 'base_field.dart';
|
||||
|
||||
@@ -73,19 +74,22 @@ class BarcodeField extends BaseField {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
tooltip: 'Scan Barcode',
|
||||
icon: Icon(Icons.document_scanner_rounded,
|
||||
color: colorScheme.primary),
|
||||
onPressed: scanner == null
|
||||
? null
|
||||
: () async {
|
||||
final val = await scanner!.call();
|
||||
if (val != null) {
|
||||
controller.text = val;
|
||||
onChanged?.call();
|
||||
}
|
||||
},
|
||||
Builder(
|
||||
builder: (ctx) => IconButton(
|
||||
tooltip:
|
||||
AppLocalizations.of(ctx)!.scanBarcode,
|
||||
icon: Icon(Icons.document_scanner_rounded,
|
||||
color: colorScheme.primary),
|
||||
onPressed: scanner == null
|
||||
? null
|
||||
: () async {
|
||||
final val = await scanner!.call();
|
||||
if (val != null) {
|
||||
controller.text = val;
|
||||
onChanged?.call();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
|
||||
/// Read-only Data Grid field
|
||||
@@ -96,7 +97,7 @@ class _DataGridFieldWidgetState extends State<_DataGridFieldWidget> {
|
||||
}
|
||||
final data = snapshot.data ?? const <Map<String, dynamic>>[];
|
||||
if (data.isEmpty) {
|
||||
return Text('No data available',
|
||||
return Text(AppLocalizations.of(context)!.noDataAvailable,
|
||||
style: TextStyle(color: colorScheme.onSurfaceVariant));
|
||||
}
|
||||
final columns = data.first.keys.toList();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
import '../../../shared/widgets/inputs/modern_text_field.dart';
|
||||
|
||||
@@ -152,7 +153,8 @@ class _DynamicDropdownWidgetState extends State<_DynamicDropdownWidget> {
|
||||
children: [
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Search ${widget.label.toLowerCase()}',
|
||||
hintText: AppLocalizations.of(context)!
|
||||
.searchEntity(widget.label),
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
@@ -162,7 +164,8 @@ class _DynamicDropdownWidgetState extends State<_DynamicDropdownWidget> {
|
||||
Flexible(
|
||||
child: filtered.isEmpty
|
||||
? Center(
|
||||
child: Text('No results',
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.noResults,
|
||||
style: TextStyle(color: cs.onSurfaceVariant)),
|
||||
)
|
||||
: ListView.separated(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
import '../../../shared/widgets/inputs/modern_text_field.dart';
|
||||
|
||||
@@ -146,7 +147,8 @@ class _DynamicMultiSelectWidgetState extends State<_DynamicMultiSelectWidget> {
|
||||
children: [
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Search ${widget.label.toLowerCase()}',
|
||||
hintText: AppLocalizations.of(context)!
|
||||
.searchEntity(widget.label),
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
@@ -156,7 +158,8 @@ class _DynamicMultiSelectWidgetState extends State<_DynamicMultiSelectWidget> {
|
||||
Flexible(
|
||||
child: filtered.isEmpty
|
||||
? Center(
|
||||
child: Text('No results',
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.noResults,
|
||||
style: TextStyle(color: cs.onSurfaceVariant)),
|
||||
)
|
||||
: ListView.separated(
|
||||
@@ -188,7 +191,8 @@ class _DynamicMultiSelectWidgetState extends State<_DynamicMultiSelectWidget> {
|
||||
widget.onChanged?.call();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Clear'),
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.clearBtn),
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
@@ -199,7 +203,8 @@ class _DynamicMultiSelectWidgetState extends State<_DynamicMultiSelectWidget> {
|
||||
widget.onChanged?.call();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Done'),
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.doneBtn),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
import '../utils/entity_field_store.dart';
|
||||
|
||||
@@ -62,7 +63,9 @@ class FileUploadField extends BaseField {
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.attach_file_rounded),
|
||||
label: const Text('Add Files'),
|
||||
label: Builder(
|
||||
builder: (ctx) =>
|
||||
Text(AppLocalizations.of(ctx)!.addFiles)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
import '../utils/entity_field_store.dart';
|
||||
|
||||
@@ -57,7 +58,9 @@ class ImageUploadField extends BaseField {
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.image_rounded),
|
||||
label: const Text('Add Image'),
|
||||
label: Builder(
|
||||
builder: (ctx) =>
|
||||
Text(AppLocalizations.of(ctx)!.addImage)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
import '../ui/entity_form.dart';
|
||||
import 'dart:convert';
|
||||
@@ -553,7 +554,9 @@ class _OneToManyWidgetState extends State<_OneToManyWidget> {
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () => _addRow(),
|
||||
icon: Icon(Icons.add, color: cs.onPrimary),
|
||||
label: Text('Add ${widget.label}',
|
||||
label: Text(
|
||||
AppLocalizations.of(context)!
|
||||
.addEntity(widget.label),
|
||||
style: TextStyle(color: cs.onPrimary)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: cs.primary,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import '../../../core/constants/ui_constants.dart';
|
||||
import '../../../core/providers/dynamic_theme_provider.dart';
|
||||
import '../ui/entity_form.dart';
|
||||
@@ -147,7 +147,8 @@ class RelatedEntityInsertField extends BaseField {
|
||||
setLocal(() => isSubmitting = false);
|
||||
}
|
||||
},
|
||||
submitButtonText: 'Create',
|
||||
submitButtonText: AppLocalizations.of(context)!
|
||||
.createEntity(relationTitle),
|
||||
isLoading: isSubmitting,
|
||||
),
|
||||
),
|
||||
@@ -156,7 +157,8 @@ class RelatedEntityInsertField extends BaseField {
|
||||
onPressed: isSubmitting
|
||||
? null
|
||||
: () => Navigator.of(dialogContext).pop(),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(
|
||||
AppLocalizations.of(dialogContext)!.cancel),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -402,7 +404,8 @@ class _RelatedEntityInsertWidgetState
|
||||
ElevatedButton.icon(
|
||||
onPressed: _creating ? null : _openInsertDialog,
|
||||
icon: Icon(Icons.add_rounded, color: cs.onPrimary, size: 18),
|
||||
label: Text('Insert',
|
||||
label: Text(
|
||||
AppLocalizations.of(context)!.insertBtn,
|
||||
style: TextStyle(
|
||||
color: cs.onPrimary, fontWeight: FontWeight.w600)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
@@ -491,7 +494,8 @@ class _RelatedEntityInsertWidgetState
|
||||
TextButton(
|
||||
onPressed:
|
||||
isSubmitting ? null : () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.cancel),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
import '../ui/entity_form.dart';
|
||||
|
||||
@@ -143,7 +144,8 @@ class _ValueListPickerWidgetState extends State<_ValueListPickerWidget> {
|
||||
strokeWidth: 2, color: cs.primary),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text('Loading...',
|
||||
Text(
|
||||
AppLocalizations.of(context)!.loading,
|
||||
style: TextStyle(color: cs.onSurfaceVariant)),
|
||||
],
|
||||
),
|
||||
@@ -152,7 +154,7 @@ class _ValueListPickerWidgetState extends State<_ValueListPickerWidget> {
|
||||
if (snapshot.hasError || _loadError != null) {
|
||||
final String msg = snapshot.error?.toString() ??
|
||||
_loadError ??
|
||||
'Failed to load';
|
||||
AppLocalizations.of(context)!.errorLoadingData;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Container(
|
||||
@@ -186,13 +188,15 @@ class _ValueListPickerWidgetState extends State<_ValueListPickerWidget> {
|
||||
Icon(Icons.inbox_rounded,
|
||||
color: cs.onSurfaceVariant, size: 36),
|
||||
const SizedBox(height: 8),
|
||||
Text('No data found',
|
||||
Text(
|
||||
AppLocalizations.of(context)!.noDataFound,
|
||||
style: TextStyle(color: cs.onSurfaceVariant)),
|
||||
const SizedBox(height: 12),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
icon: const Icon(Icons.close_rounded),
|
||||
label: const Text('Close'),
|
||||
label: Text(
|
||||
AppLocalizations.of(context)!.close),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: cs.primary,
|
||||
foregroundColor: cs.onPrimary,
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:typed_data';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'base_field.dart';
|
||||
import '../utils/entity_field_store.dart';
|
||||
|
||||
@@ -63,7 +64,9 @@ class VideoUploadField extends BaseField {
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.video_library_rounded),
|
||||
label: const Text('Add Video'),
|
||||
label: Builder(
|
||||
builder: (ctx) =>
|
||||
Text(AppLocalizations.of(ctx)!.addVideo)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import '../../../core/providers/dynamic_theme_provider.dart';
|
||||
import '../../../core/constants/ui_constants.dart';
|
||||
import '../../../shared/widgets/app_bar/modern_app_bar.dart';
|
||||
@@ -408,7 +409,7 @@ class _EntityDetailsState extends State<EntityDetails>
|
||||
children: [
|
||||
Expanded(
|
||||
child: ModernButton(
|
||||
text: 'Edit',
|
||||
text: AppLocalizations.of(context)!.edit,
|
||||
type: ModernButtonType.secondary,
|
||||
size: ModernButtonSize.large,
|
||||
onPressed: () => widget.onEdit(widget.entity),
|
||||
@@ -418,7 +419,7 @@ class _EntityDetailsState extends State<EntityDetails>
|
||||
const SizedBox(width: UIConstants.spacing16),
|
||||
Expanded(
|
||||
child: ModernButton(
|
||||
text: 'Delete',
|
||||
text: AppLocalizations.of(context)!.delete,
|
||||
type: ModernButtonType.danger,
|
||||
size: ModernButtonSize.large,
|
||||
onPressed: () => _showDeleteDialog(colorScheme),
|
||||
|
||||
@@ -386,6 +386,7 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import '../../../core/providers/dynamic_theme_provider.dart';
|
||||
import '../fields/base_field.dart';
|
||||
import '../fields/dependent_dropdown_field.dart';
|
||||
@@ -562,7 +563,9 @@ class _EntityFormState extends State<EntityForm> {
|
||||
final pass = passwordByGroup[gid] ?? '';
|
||||
if (confirm.isNotEmpty && confirm != pass) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('Passwords do not match')),
|
||||
SnackBar(
|
||||
content: Text(AppLocalizations.of(context)!
|
||||
.passwordsDoNotMatch)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/providers/dynamic_theme_provider.dart';
|
||||
import '../../../core/constants/ui_constants.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import '../../../shared/widgets/app_bar/modern_app_bar.dart';
|
||||
import 'entity_card.dart';
|
||||
|
||||
@@ -106,7 +107,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
TextButton(
|
||||
onPressed: widget.onInsertAction,
|
||||
child: Text(
|
||||
widget.insertActionLabel ?? 'Unknown',
|
||||
widget.insertActionLabel ?? AppLocalizations.of(context)!.unknown,
|
||||
style: TextStyle(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -117,7 +118,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
IconButton(
|
||||
onPressed: widget.onAddNew,
|
||||
icon: Icon(Icons.add_rounded, color: colorScheme.primary),
|
||||
tooltip: 'Add New',
|
||||
tooltip: AppLocalizations.of(context)!.addNew,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -175,7 +176,8 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Search ${widget.title.toLowerCase()}...',
|
||||
hintText: AppLocalizations.of(context)!
|
||||
.searchEntity(widget.title.toLowerCase()),
|
||||
hintStyle: TextStyle(
|
||||
color: colorScheme.onSurface.withOpacity(0.6),
|
||||
fontSize: 16,
|
||||
@@ -214,7 +216,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
color: colorScheme.onSurface.withOpacity(0.8),
|
||||
size: 22,
|
||||
),
|
||||
tooltip: 'Refresh',
|
||||
tooltip: AppLocalizations.of(context)!.refresh,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -245,7 +247,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
CircularProgressIndicator(color: colorScheme.primary, strokeWidth: 3),
|
||||
const SizedBox(height: UIConstants.spacing16),
|
||||
Text(
|
||||
'Loading ${widget.title.toLowerCase()}...',
|
||||
AppLocalizations.of(context)!.loadingEntity(widget.title.toLowerCase()),
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface.withOpacity(0.7),
|
||||
fontSize: 16,
|
||||
@@ -277,7 +279,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing16),
|
||||
Text(
|
||||
'Error Loading Data',
|
||||
AppLocalizations.of(context)!.errorLoadingData,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface,
|
||||
fontSize: 18,
|
||||
@@ -286,7 +288,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing8),
|
||||
Text(
|
||||
widget.errorMessage ?? 'Something went wrong',
|
||||
widget.errorMessage ?? AppLocalizations.of(context)!.somethingWentWrong,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface.withOpacity(0.7),
|
||||
fontSize: 14,
|
||||
@@ -299,7 +301,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
onPressed: widget.onRefresh,
|
||||
icon: Icon(Icons.refresh_rounded, color: colorScheme.onPrimary),
|
||||
label: Text(
|
||||
'Retry',
|
||||
AppLocalizations.of(context)!.retry,
|
||||
style: TextStyle(
|
||||
color: colorScheme.onPrimary,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -344,7 +346,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing16),
|
||||
Text(
|
||||
'No ${widget.title.toLowerCase()} found',
|
||||
AppLocalizations.of(context)!.noEntityFound(widget.title.toLowerCase()),
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface,
|
||||
fontSize: 18,
|
||||
@@ -354,8 +356,9 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
const SizedBox(height: UIConstants.spacing8),
|
||||
Text(
|
||||
widget.searchQuery.isNotEmpty
|
||||
? 'Try adjusting your search terms'
|
||||
: 'Start by adding your first ${widget.title.toLowerCase()}',
|
||||
? AppLocalizations.of(context)!.adjustSearchTerms
|
||||
: AppLocalizations.of(context)!
|
||||
.startByAdding(widget.title.toLowerCase()),
|
||||
style: TextStyle(
|
||||
color: colorScheme.onSurface.withOpacity(0.7),
|
||||
fontSize: 14,
|
||||
@@ -369,7 +372,7 @@ class _EntityListState extends State<EntityList> with TickerProviderStateMixin {
|
||||
onPressed: widget.onAddNew,
|
||||
icon: Icon(Icons.add_rounded, color: colorScheme.onPrimary),
|
||||
label: Text(
|
||||
'Add ${widget.title}',
|
||||
AppLocalizations.of(context)!.addEntity(widget.title),
|
||||
style: TextStyle(
|
||||
color: colorScheme.onPrimary,
|
||||
fontWeight: FontWeight.w600,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ReusableDropdownField extends StatelessWidget {
|
||||
@@ -46,9 +47,10 @@ class ReusableDropdownField extends StatelessWidget {
|
||||
),
|
||||
value: (value != null && value!.isNotEmpty) ? value : null,
|
||||
items: [
|
||||
const DropdownMenuItem<String>(
|
||||
DropdownMenuItem<String>(
|
||||
value: '',
|
||||
child: Text('Select an option'),
|
||||
child: Text(
|
||||
AppLocalizations.of(context)!.selectOption),
|
||||
),
|
||||
...options.map<DropdownMenuItem<String>>(
|
||||
(item) => DropdownMenuItem<String>(
|
||||
|
||||
@@ -36,6 +36,7 @@ import '../../Entity/angulardatatype/Basicp1/Basicp1_viewModel/Basicp1_view_mode
|
||||
|
||||
import 'package:base_project/utils/image_constant.dart';
|
||||
import 'package:base_project/commans/widgets/custome_drawe_item.dart';
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:base_project/resources/app_colors.dart';
|
||||
import 'package:base_project/routes/route_names.dart';
|
||||
import 'package:base_project/utils/managers/user_manager.dart';
|
||||
@@ -76,13 +77,14 @@ class MyCustomDrawer extends StatelessWidget {
|
||||
height: 60,
|
||||
),
|
||||
),
|
||||
accountName: Text("Hello, $userName"),
|
||||
accountName: Text(
|
||||
AppLocalizations.of(context)!.helloUser(userName)),
|
||||
accountEmail: Text(email.toString()),
|
||||
),
|
||||
DrawerItem(
|
||||
color: AppColors.primary,
|
||||
icon: Icons.person,
|
||||
title: 'Profile',
|
||||
title: AppLocalizations.of(context)!.profile,
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, RouteNames.profileView);
|
||||
},
|
||||
@@ -90,7 +92,7 @@ class MyCustomDrawer extends StatelessWidget {
|
||||
DrawerItem(
|
||||
color: AppColors.primary,
|
||||
icon: Icons.system_security_update,
|
||||
title: 'System Parameters',
|
||||
title: AppLocalizations.of(context)!.systemParameters,
|
||||
onTap: () {
|
||||
// Add navigation or other logic here
|
||||
Navigator.pushNamed(context, RouteNames.systemParamsView);
|
||||
@@ -99,7 +101,7 @@ class MyCustomDrawer extends StatelessWidget {
|
||||
DrawerItem(
|
||||
color: AppColors.primary,
|
||||
icon: Icons.password,
|
||||
title: 'change password',
|
||||
title: AppLocalizations.of(context)!.changePassword,
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, RouteNames.changePasswordView);
|
||||
},
|
||||
@@ -314,7 +316,7 @@ class MyCustomDrawer extends StatelessWidget {
|
||||
DrawerItem(
|
||||
icon: Icons.logout,
|
||||
color: Colors.red,
|
||||
title: 'Logout',
|
||||
title: AppLocalizations.of(context)!.logout,
|
||||
onTap: () async {
|
||||
await UserManager().clearUser();
|
||||
Navigator.pushReplacementNamed(context, RouteNames.splashView);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../providers/locale_provider.dart';
|
||||
|
||||
/// Translates stable, server/form-builder keys with a safe English fallback.
|
||||
extension DynamicStrings on BuildContext {
|
||||
String trDynamic(String key) => watch<LocaleProvider>().dynamicText(key);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
class LocaleProvider extends ChangeNotifier {
|
||||
static const preferenceKey = 'app_locale_code';
|
||||
static const supportedCodes = <String>['en', 'hi'];
|
||||
|
||||
Locale _locale = const Locale('en');
|
||||
Locale get locale => _locale;
|
||||
final Map<String, Map<String, String>> _dynamicTables = {};
|
||||
|
||||
Future<void> initialize() async {
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
final savedCode = preferences.getString(preferenceKey);
|
||||
if (savedCode != null && supportedCodes.contains(savedCode)) {
|
||||
_locale = Locale(savedCode);
|
||||
}
|
||||
await _loadDynamicTables();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> _loadDynamicTables() async {
|
||||
for (final code in supportedCodes) {
|
||||
try {
|
||||
final raw = await rootBundle.loadString('assets/translations_dynamic/$code.json');
|
||||
final decoded = jsonDecode(raw) as Map<String, dynamic>;
|
||||
_dynamicTables[code] = decoded.map(
|
||||
(key, value) => MapEntry(_normalizeKey(key), value.toString()),
|
||||
);
|
||||
} catch (_) {
|
||||
_dynamicTables[code] = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setLocale(String code) async {
|
||||
if (!supportedCodes.contains(code) || code == _locale.languageCode) return;
|
||||
_locale = Locale(code);
|
||||
notifyListeners();
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString(preferenceKey, code);
|
||||
}
|
||||
|
||||
String dynamicText(String key) {
|
||||
final normalized = _normalizeKey(key);
|
||||
return _dynamicTables[_locale.languageCode]?[normalized] ??
|
||||
_dynamicTables['en']?[normalized] ??
|
||||
key.replaceAll('_', ' ');
|
||||
}
|
||||
|
||||
String _normalizeKey(String key) =>
|
||||
key.trim().toLowerCase().replaceAll(RegExp(r'\s+'), '_');
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
{
|
||||
"@@locale": "en",
|
||||
"appTitle": "AuthSec Flutter",
|
||||
"language": "Language",
|
||||
"english": "English",
|
||||
"hindi": "Hindi",
|
||||
"helloUser": "Hello, {name}",
|
||||
"@helloUser": {"placeholders": {"name": {"type": "String"}}},
|
||||
"user": "User",
|
||||
"logout": "Logout",
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm",
|
||||
"retry": "Retry",
|
||||
"refresh": "Refresh",
|
||||
"addNew": "Add new",
|
||||
"searchEntity": "Search {entity}...",
|
||||
"@searchEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"loadingEntity": "Loading {entity}...",
|
||||
"@loadingEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"noEntityFound": "No {entity} found",
|
||||
"@noEntityFound": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"addEntity": "Add {entity}",
|
||||
"@addEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"createEntity": "Create {entity}",
|
||||
"@createEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"updateEntity": "Update {entity}",
|
||||
"@updateEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"entityRequired": "{field} is required",
|
||||
"@entityRequired": {"placeholders": {"field": {"type": "String"}}},
|
||||
"errorLoadingData": "Error loading data",
|
||||
"somethingWentWrong": "Something went wrong",
|
||||
"adjustSearchTerms": "Try adjusting your search terms",
|
||||
"startByAdding": "Start by adding your first {entity}",
|
||||
"@startByAdding": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"unknown": "Unknown",
|
||||
"scanBarcode": "Scan barcode",
|
||||
"enterOrScanBarcode": "Enter or scan barcode",
|
||||
"addAudio": "Add audio",
|
||||
"selectAudioFile": "Select audio file",
|
||||
"pickColor": "Pick a color",
|
||||
"systemParameters": "System Parameters",
|
||||
"editSystemParameters": "Edit System Parameters",
|
||||
"goBack": "Go back",
|
||||
"profile": "Profile",
|
||||
"editProfile": "Edit profile",
|
||||
"accountUpdate": "Account update",
|
||||
"changePassword": "Change password",
|
||||
"confirmLogout": "Confirm logout",
|
||||
"confirmLogoutBody": "Are you sure you want to log out?",
|
||||
"logoutAction": "Log out",
|
||||
"passwordsDoNotMatch": "Passwords do not match",
|
||||
"requiredField": "This field is required",
|
||||
"email": "Email",
|
||||
"password": "Password",
|
||||
"signIn": "Sign in",
|
||||
"signUp": "Sign up",
|
||||
"forgotPassword": "Forgot password?",
|
||||
"loading": "Loading...",
|
||||
"save": "Save",
|
||||
"delete": "Delete",
|
||||
"edit": "Edit",
|
||||
"close": "Close"
|
||||
,"welcomeBack": "Welcome back!"
|
||||
,"signInToContinue": "Sign in to continue to your account"
|
||||
,"emailAddress": "Email address"
|
||||
,"enterYourEmail": "Enter your email"
|
||||
,"emailRequired": "Email is required"
|
||||
,"validEmail": "Please enter a valid email"
|
||||
,"enterYourPassword": "Enter your password"
|
||||
,"passwordRequired": "Password is required"
|
||||
,"passwordMinLength": "Password must be at least 6 characters"
|
||||
,"noAccount": "Don't have an account?"
|
||||
,"orContinueWith": "Or continue with"
|
||||
,"verifyOtp": "Verify OTP"
|
||||
,"otpSentTo": "Enter the 6-digit code sent to"
|
||||
,"yourEmail": "your email"
|
||||
,"enterOtp": "Enter 6-digit OTP"
|
||||
,"didNotReceiveCode": "Didn't receive code?"
|
||||
,"resendIn": "Resend in {seconds}s"
|
||||
,"@resendIn": {"placeholders": {"seconds": {"type": "int"}}}
|
||||
,"resend": "Resend"
|
||||
,"dashboard": "Dashboard"
|
||||
,"settings": "Settings"
|
||||
,"security": "Security"
|
||||
,"reports": "Reports"
|
||||
,"manageAccount": "Manage your account"
|
||||
,"configureSystemSettings": "Configure system settings"
|
||||
,"updateYourPassword": "Update your password"
|
||||
,"getOtp": "Get OTP"
|
||||
,"otpEmailPrompt": "Enter your email to receive a one-time password"
|
||||
,"enterEmailAddress": "Enter your email address"
|
||||
,"sendOtp": "Send OTP"
|
||||
,"sendingOtp": "Sending OTP..."
|
||||
,"alreadyHaveAccount": "Already have an account?"
|
||||
,"backToLogin": "Back to login"
|
||||
,"emailLooksGood": "Email looks good"
|
||||
,"invalidEmailAddress": "Invalid email address"
|
||||
,"noDataAvailable": "No data available"
|
||||
,"noResults": "No results"
|
||||
,"clearBtn": "Clear"
|
||||
,"doneBtn": "Done"
|
||||
,"addFiles": "Add Files"
|
||||
,"addImage": "Add Image"
|
||||
,"addVideo": "Add Video"
|
||||
,"insertBtn": "Insert"
|
||||
,"noDataFound": "No data found"
|
||||
,"sysConfigTitle": "System Configuration"
|
||||
,"sysConfigSubtitle": "Configure system-wide parameters and settings"
|
||||
,"generatingTheme": "Generating dynamic theme..."
|
||||
,"themeApplied": "Dynamic theme applied! Colors extracted from logo."
|
||||
,"themeImmediateNote": "Theme is applied immediately! Click \"Upload Logo\" to save the logo permanently to the database. The dynamic theme will work even if upload fails."
|
||||
,"uploadNewLogo": "Upload New Logo"
|
||||
,"removeLogo": "Remove Logo"
|
||||
,"logoAlreadyUploaded": "Company logo is already uploaded and saved in the system. You can upload a new one or remove the existing logo."
|
||||
,"manualOverride": "Enable Manual Override"
|
||||
,"colorPrimary": "Primary"
|
||||
,"colorSecondary": "Secondary"
|
||||
,"colorTertiary": "Tertiary"
|
||||
,"resetLogoColors": "Reset to Logo Colors"
|
||||
,"resetDefault": "Reset to Default"
|
||||
,"userRegistration": "User Registration"
|
||||
,"allowUserRegistration": "Allow new users to register accounts"
|
||||
,"themeGenerated": "Dynamic Theme Generated"
|
||||
,"resetThemeTooltip": "Reset to Default Theme"
|
||||
,"colorPalette": "Color Palette"
|
||||
,"colorAccent1": "Accent 1"
|
||||
,"colorAccent2": "Accent 2"
|
||||
,"colorN": "Color {n}"
|
||||
,"@colorN": {"placeholders": {"n": {"type": "String"}}}
|
||||
,"themeInfo": "Theme Information"
|
||||
,"totalColors": "Total Colors"
|
||||
,"themeDescription": "Description"
|
||||
,"warmColors": "Warm Colors"
|
||||
,"coolColors": "Cool Colors"
|
||||
,"neutralColors": "Neutral Colors"
|
||||
,"yes": "Yes"
|
||||
,"no": "No"
|
||||
,"primaryButton": "Primary Button"
|
||||
,"secondaryButton": "Secondary Button"
|
||||
,"uploadLogo": "Upload Logo"
|
||||
,"clearLogo": "Clear Logo"
|
||||
,"saveConfiguration": "Save Configuration"
|
||||
,"drawerHome": "Home"
|
||||
,"drawerUsers": "Users"
|
||||
,"drawerRoles": "Roles"
|
||||
,"drawerDepartments": "Departments"
|
||||
,"drawerPositions": "Positions"
|
||||
,"drawerCharges": "Charges"
|
||||
,"drawerWeeks": "Weeks"
|
||||
,"drawerShifts": "Shifts"
|
||||
,"drawerBilling": "Billing"
|
||||
,"drawerEdi": "EDI Settings"
|
||||
,"drawerCompany": "Company"
|
||||
,"drawerLogo": "Logo"
|
||||
,"registerCompany": "Register Company"
|
||||
,"accCompanyName": "Company Name"
|
||||
,"accCompanyHint": "Enter company name"
|
||||
,"accWorkspace": "Workspace"
|
||||
,"accWorkspaceHint": "Enter workspace"
|
||||
,"accGst": "GST Number"
|
||||
,"accGstHint": "Enter GST number"
|
||||
,"accMobile": "Mobile"
|
||||
,"accMobileHint": "Enter mobile number"
|
||||
,"accEmailReadonly": "Email (read-only)"
|
||||
,"accPan": "PAN Card"
|
||||
,"accPanHint": "Enter PAN"
|
||||
,"accWorking": "Working"
|
||||
,"accWorkingHint": "Working status"
|
||||
,"requiredVal": "Required"
|
||||
,"nActive": "Active"
|
||||
,"saveChanges": "Save Changes"
|
||||
,"selectOption": "Select an option"
|
||||
,"removeBtn": "Remove"
|
||||
,"ohSnap": "Oh Snap!"
|
||||
,"alertTitle": "Alert"
|
||||
,"successTitle": "Success"
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
{
|
||||
"@@locale": "hi",
|
||||
"appTitle": "ऑथसेक फ्लटर",
|
||||
"language": "भाषा",
|
||||
"english": "अंग्रेज़ी",
|
||||
"hindi": "हिन्दी",
|
||||
"helloUser": "नमस्ते, {name}",
|
||||
"@helloUser": {"placeholders": {"name": {"type": "String"}}},
|
||||
"user": "उपयोगकर्ता",
|
||||
"logout": "लॉग आउट",
|
||||
"cancel": "रद्द करें",
|
||||
"confirm": "पुष्टि करें",
|
||||
"retry": "पुनः प्रयास करें",
|
||||
"refresh": "रीफ़्रेश",
|
||||
"addNew": "नया जोड़ें",
|
||||
"searchEntity": "{entity} खोजें...",
|
||||
"@searchEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"loadingEntity": "{entity} लोड हो रहा है...",
|
||||
"@loadingEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"noEntityFound": "कोई {entity} नहीं मिला",
|
||||
"@noEntityFound": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"addEntity": "{entity} जोड़ें",
|
||||
"@addEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"createEntity": "{entity} बनाएँ",
|
||||
"@createEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"updateEntity": "{entity} अपडेट करें",
|
||||
"@updateEntity": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"entityRequired": "{field} आवश्यक है",
|
||||
"@entityRequired": {"placeholders": {"field": {"type": "String"}}},
|
||||
"errorLoadingData": "डेटा लोड करने में त्रुटि",
|
||||
"somethingWentWrong": "कुछ गलत हो गया",
|
||||
"adjustSearchTerms": "अपने खोज शब्द बदलें",
|
||||
"startByAdding": "अपना पहला {entity} जोड़कर शुरू करें",
|
||||
"@startByAdding": {"placeholders": {"entity": {"type": "String"}}},
|
||||
"unknown": "अज्ञात",
|
||||
"scanBarcode": "बारकोड स्कैन करें",
|
||||
"enterOrScanBarcode": "बारकोड दर्ज करें या स्कैन करें",
|
||||
"addAudio": "ऑडियो जोड़ें",
|
||||
"selectAudioFile": "ऑडियो फ़ाइल चुनें",
|
||||
"pickColor": "रंग चुनें",
|
||||
"systemParameters": "सिस्टम पैरामीटर",
|
||||
"editSystemParameters": "सिस्टम पैरामीटर संपादित करें",
|
||||
"goBack": "वापस जाएँ",
|
||||
"profile": "प्रोफ़ाइल",
|
||||
"editProfile": "प्रोफ़ाइल संपादित करें",
|
||||
"accountUpdate": "खाता अपडेट",
|
||||
"changePassword": "पासवर्ड बदलें",
|
||||
"confirmLogout": "लॉग आउट की पुष्टि करें",
|
||||
"confirmLogoutBody": "क्या आप वाकई लॉग आउट करना चाहते हैं?",
|
||||
"logoutAction": "लॉग आउट",
|
||||
"passwordsDoNotMatch": "पासवर्ड मेल नहीं खाते",
|
||||
"requiredField": "यह फ़ील्ड आवश्यक है",
|
||||
"email": "ईमेल",
|
||||
"password": "पासवर्ड",
|
||||
"signIn": "साइन इन",
|
||||
"signUp": "साइन अप",
|
||||
"forgotPassword": "पासवर्ड भूल गए?",
|
||||
"loading": "लोड हो रहा है...",
|
||||
"save": "सहेजें",
|
||||
"delete": "हटाएँ",
|
||||
"edit": "संपादित करें",
|
||||
"close": "बंद करें"
|
||||
,"welcomeBack": "वापस स्वागत है!"
|
||||
,"signInToContinue": "अपने खाते में जारी रखने के लिए साइन इन करें"
|
||||
,"emailAddress": "ईमेल पता"
|
||||
,"enterYourEmail": "अपना ईमेल दर्ज करें"
|
||||
,"emailRequired": "ईमेल आवश्यक है"
|
||||
,"validEmail": "कृपया मान्य ईमेल दर्ज करें"
|
||||
,"enterYourPassword": "अपना पासवर्ड दर्ज करें"
|
||||
,"passwordRequired": "पासवर्ड आवश्यक है"
|
||||
,"passwordMinLength": "पासवर्ड कम से कम 6 वर्ण का होना चाहिए"
|
||||
,"noAccount": "क्या आपका खाता नहीं है?"
|
||||
,"orContinueWith": "या इसके साथ जारी रखें"
|
||||
,"verifyOtp": "ओटीपी सत्यापित करें"
|
||||
,"otpSentTo": "भेजा गया 6 अंकों का कोड दर्ज करें"
|
||||
,"yourEmail": "आपका ईमेल"
|
||||
,"enterOtp": "6 अंकों का ओटीपी दर्ज करें"
|
||||
,"didNotReceiveCode": "कोड नहीं मिला?"
|
||||
,"resendIn": "{seconds} सेकंड में पुनः भेजें"
|
||||
,"@resendIn": {"placeholders": {"seconds": {"type": "int"}}}
|
||||
,"resend": "पुनः भेजें"
|
||||
,"dashboard": "डैशबोर्ड"
|
||||
,"settings": "सेटिंग्स"
|
||||
,"security": "सुरक्षा"
|
||||
,"reports": "रिपोर्ट"
|
||||
,"manageAccount": "अपने खाते का प्रबंधन करें"
|
||||
,"configureSystemSettings": "सिस्टम सेटिंग्स कॉन्फ़िगर करें"
|
||||
,"updateYourPassword": "अपना पासवर्ड अपडेट करें"
|
||||
,"getOtp": "ओटीपी प्राप्त करें"
|
||||
,"otpEmailPrompt": "वन-टाइम पासवर्ड पाने के लिए अपना ईमेल दर्ज करें"
|
||||
,"enterEmailAddress": "अपना ईमेल पता दर्ज करें"
|
||||
,"sendOtp": "ओटीपी भेजें"
|
||||
,"sendingOtp": "ओटीपी भेजा जा रहा है..."
|
||||
,"alreadyHaveAccount": "क्या आपका पहले से खाता है?"
|
||||
,"backToLogin": "लॉगिन पर वापस जाएँ"
|
||||
,"emailLooksGood": "ईमेल सही है"
|
||||
,"invalidEmailAddress": "अमान्य ईमेल पता"
|
||||
,"noDataAvailable": "कोई डेटा उपलब्ध नहीं"
|
||||
,"noResults": "कोई परिणाम नहीं"
|
||||
,"clearBtn": "साफ़ करें"
|
||||
,"doneBtn": "हो गया"
|
||||
,"addFiles": "फ़ाइलें जोड़ें"
|
||||
,"addImage": "छवि जोड़ें"
|
||||
,"addVideo": "वीडियो जोड़ें"
|
||||
,"insertBtn": "डालें"
|
||||
,"noDataFound": "कोई डेटा नहीं मिला"
|
||||
,"sysConfigTitle": "सिस्टम कॉन्फ़िगरेशन"
|
||||
,"sysConfigSubtitle": "सिस्टम-व्यापी पैरामीटर और सेटिंग्स कॉन्फ़िगर करें"
|
||||
,"generatingTheme": "डायनामिक थीम बनाई जा रही है..."
|
||||
,"themeApplied": "डायनामिक थीम लागू! लोगो से रंग निकाले गए।"
|
||||
,"themeImmediateNote": "थीम तुरंत लागू होती है! लोगो को डेटाबेस में स्थायी रूप से सहेजने के लिए अपलोड लोगो पर क्लिक करें। अपलोड विफल होने पर भी डायनामिक थीम काम करेगी।"
|
||||
,"uploadNewLogo": "नया लोगो अपलोड करें"
|
||||
,"removeLogo": "लोगो हटाएं"
|
||||
,"logoAlreadyUploaded": "कंपनी का लोगो पहले से अपलोड है और सिस्टम में सहेजा गया है। आप नया अपलोड कर सकते हैं या मौजूदा लोगो हटा सकते हैं।"
|
||||
,"manualOverride": "मैन्युअल ओवरराइड सक्षम करें"
|
||||
,"colorPrimary": "प्राथमिक"
|
||||
,"colorSecondary": "द्वितीयक"
|
||||
,"colorTertiary": "तृतीयक"
|
||||
,"resetLogoColors": "लोगो रंगों पर रीसेट करें"
|
||||
,"resetDefault": "डिफ़ॉल्ट पर रीसेट करें"
|
||||
,"userRegistration": "उपयोगकर्ता पंजीकरण"
|
||||
,"allowUserRegistration": "नए उपयोगकर्ताओं को खाते पंजीकृत करने दें"
|
||||
,"themeGenerated": "डायनामिक थीम बनाई गई"
|
||||
,"resetThemeTooltip": "डिफ़ॉल्ट थीम पर रीसेट करें"
|
||||
,"colorPalette": "रंग पट्टिका"
|
||||
,"colorAccent1": "एक्सेंट 1"
|
||||
,"colorAccent2": "एक्सेंट 2"
|
||||
,"colorN": "रंग {n}"
|
||||
,"themeInfo": "थीम जानकारी"
|
||||
,"totalColors": "कुल रंग"
|
||||
,"themeDescription": "विवरण"
|
||||
,"warmColors": "गर्म रंग"
|
||||
,"coolColors": "ठंडे रंग"
|
||||
,"neutralColors": "तटस्थ रंग"
|
||||
,"yes": "हां"
|
||||
,"no": "नहीं"
|
||||
,"primaryButton": "प्राथमिक बटन"
|
||||
,"secondaryButton": "द्वितीयक बटन"
|
||||
,"uploadLogo": "लोगो अपलोड करें"
|
||||
,"clearLogo": "लोगो साफ़ करें"
|
||||
,"saveConfiguration": "कॉन्फ़िगरेशन सहेजें"
|
||||
,"drawerHome": "होम"
|
||||
,"drawerUsers": "उपयोगकर्ता"
|
||||
,"drawerRoles": "भूमिकाएं"
|
||||
,"drawerDepartments": "विभाग"
|
||||
,"drawerPositions": "पद"
|
||||
,"drawerCharges": "शुल्क"
|
||||
,"drawerWeeks": "सप्ताह"
|
||||
,"drawerShifts": "पारियां"
|
||||
,"drawerBilling": "बिलिंग"
|
||||
,"drawerEdi": "EDI सेटिंग्स"
|
||||
,"drawerCompany": "कंपनी"
|
||||
,"drawerLogo": "लोगो"
|
||||
,"registerCompany": "कंपनी पंजीकृत करें"
|
||||
,"accCompanyName": "कंपनी का नाम"
|
||||
,"accCompanyHint": "कंपनी का नाम दर्ज करें"
|
||||
,"accWorkspace": "कार्यक्षेत्र"
|
||||
,"accWorkspaceHint": "कार्यक्षेत्र दर्ज करें"
|
||||
,"accGst": "जीएसटी नंबर"
|
||||
,"accGstHint": "जीएसटी नंबर दर्ज करें"
|
||||
,"accMobile": "मोबाइल"
|
||||
,"accMobileHint": "मोबाइल नंबर दर्ज करें"
|
||||
,"accEmailReadonly": "ईमेल (केवल-पठन)"
|
||||
,"accPan": "पैन कार्ड"
|
||||
,"accPanHint": "पैन दर्ज करें"
|
||||
,"accWorking": "कार्य"
|
||||
,"accWorkingHint": "कार्य स्थिति"
|
||||
,"requiredVal": "आवश्यक"
|
||||
,"nActive": "सक्रिय"
|
||||
,"saveChanges": "परिवर्तन सहेजें"
|
||||
,"selectOption": "एक विकल्प चुनें"
|
||||
,"removeBtn": "हटाएं"
|
||||
,"ohSnap": "ओह स्नैप!"
|
||||
,"alertTitle": "चेतावनी"
|
||||
,"successTitle": "सफलता"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,526 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for English (`en`).
|
||||
class AppLocalizationsEn extends AppLocalizations {
|
||||
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'AuthSec Flutter';
|
||||
|
||||
@override
|
||||
String get language => 'Language';
|
||||
|
||||
@override
|
||||
String get english => 'English';
|
||||
|
||||
@override
|
||||
String get hindi => 'Hindi';
|
||||
|
||||
@override
|
||||
String helloUser(String name) {
|
||||
return 'Hello, $name';
|
||||
}
|
||||
|
||||
@override
|
||||
String get user => 'User';
|
||||
|
||||
@override
|
||||
String get logout => 'Logout';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancel';
|
||||
|
||||
@override
|
||||
String get confirm => 'Confirm';
|
||||
|
||||
@override
|
||||
String get retry => 'Retry';
|
||||
|
||||
@override
|
||||
String get refresh => 'Refresh';
|
||||
|
||||
@override
|
||||
String get addNew => 'Add new';
|
||||
|
||||
@override
|
||||
String searchEntity(String entity) {
|
||||
return 'Search $entity...';
|
||||
}
|
||||
|
||||
@override
|
||||
String loadingEntity(String entity) {
|
||||
return 'Loading $entity...';
|
||||
}
|
||||
|
||||
@override
|
||||
String noEntityFound(String entity) {
|
||||
return 'No $entity found';
|
||||
}
|
||||
|
||||
@override
|
||||
String addEntity(String entity) {
|
||||
return 'Add $entity';
|
||||
}
|
||||
|
||||
@override
|
||||
String createEntity(String entity) {
|
||||
return 'Create $entity';
|
||||
}
|
||||
|
||||
@override
|
||||
String updateEntity(String entity) {
|
||||
return 'Update $entity';
|
||||
}
|
||||
|
||||
@override
|
||||
String entityRequired(String field) {
|
||||
return '$field is required';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadingData => 'Error loading data';
|
||||
|
||||
@override
|
||||
String get somethingWentWrong => 'Something went wrong';
|
||||
|
||||
@override
|
||||
String get adjustSearchTerms => 'Try adjusting your search terms';
|
||||
|
||||
@override
|
||||
String startByAdding(String entity) {
|
||||
return 'Start by adding your first $entity';
|
||||
}
|
||||
|
||||
@override
|
||||
String get unknown => 'Unknown';
|
||||
|
||||
@override
|
||||
String get scanBarcode => 'Scan barcode';
|
||||
|
||||
@override
|
||||
String get enterOrScanBarcode => 'Enter or scan barcode';
|
||||
|
||||
@override
|
||||
String get addAudio => 'Add audio';
|
||||
|
||||
@override
|
||||
String get selectAudioFile => 'Select audio file';
|
||||
|
||||
@override
|
||||
String get pickColor => 'Pick a color';
|
||||
|
||||
@override
|
||||
String get systemParameters => 'System Parameters';
|
||||
|
||||
@override
|
||||
String get editSystemParameters => 'Edit System Parameters';
|
||||
|
||||
@override
|
||||
String get goBack => 'Go back';
|
||||
|
||||
@override
|
||||
String get profile => 'Profile';
|
||||
|
||||
@override
|
||||
String get editProfile => 'Edit profile';
|
||||
|
||||
@override
|
||||
String get accountUpdate => 'Account update';
|
||||
|
||||
@override
|
||||
String get changePassword => 'Change password';
|
||||
|
||||
@override
|
||||
String get confirmLogout => 'Confirm logout';
|
||||
|
||||
@override
|
||||
String get confirmLogoutBody => 'Are you sure you want to log out?';
|
||||
|
||||
@override
|
||||
String get logoutAction => 'Log out';
|
||||
|
||||
@override
|
||||
String get passwordsDoNotMatch => 'Passwords do not match';
|
||||
|
||||
@override
|
||||
String get requiredField => 'This field is required';
|
||||
|
||||
@override
|
||||
String get email => 'Email';
|
||||
|
||||
@override
|
||||
String get password => 'Password';
|
||||
|
||||
@override
|
||||
String get signIn => 'Sign in';
|
||||
|
||||
@override
|
||||
String get signUp => 'Sign up';
|
||||
|
||||
@override
|
||||
String get forgotPassword => 'Forgot password?';
|
||||
|
||||
@override
|
||||
String get loading => 'Loading...';
|
||||
|
||||
@override
|
||||
String get save => 'Save';
|
||||
|
||||
@override
|
||||
String get delete => 'Delete';
|
||||
|
||||
@override
|
||||
String get edit => 'Edit';
|
||||
|
||||
@override
|
||||
String get close => 'Close';
|
||||
|
||||
@override
|
||||
String get welcomeBack => 'Welcome back!';
|
||||
|
||||
@override
|
||||
String get signInToContinue => 'Sign in to continue to your account';
|
||||
|
||||
@override
|
||||
String get emailAddress => 'Email address';
|
||||
|
||||
@override
|
||||
String get enterYourEmail => 'Enter your email';
|
||||
|
||||
@override
|
||||
String get emailRequired => 'Email is required';
|
||||
|
||||
@override
|
||||
String get validEmail => 'Please enter a valid email';
|
||||
|
||||
@override
|
||||
String get enterYourPassword => 'Enter your password';
|
||||
|
||||
@override
|
||||
String get passwordRequired => 'Password is required';
|
||||
|
||||
@override
|
||||
String get passwordMinLength => 'Password must be at least 6 characters';
|
||||
|
||||
@override
|
||||
String get noAccount => 'Don\'t have an account?';
|
||||
|
||||
@override
|
||||
String get orContinueWith => 'Or continue with';
|
||||
|
||||
@override
|
||||
String get verifyOtp => 'Verify OTP';
|
||||
|
||||
@override
|
||||
String get otpSentTo => 'Enter the 6-digit code sent to';
|
||||
|
||||
@override
|
||||
String get yourEmail => 'your email';
|
||||
|
||||
@override
|
||||
String get enterOtp => 'Enter 6-digit OTP';
|
||||
|
||||
@override
|
||||
String get didNotReceiveCode => 'Didn\'t receive code?';
|
||||
|
||||
@override
|
||||
String resendIn(int seconds) {
|
||||
return 'Resend in ${seconds}s';
|
||||
}
|
||||
|
||||
@override
|
||||
String get resend => 'Resend';
|
||||
|
||||
@override
|
||||
String get dashboard => 'Dashboard';
|
||||
|
||||
@override
|
||||
String get settings => 'Settings';
|
||||
|
||||
@override
|
||||
String get security => 'Security';
|
||||
|
||||
@override
|
||||
String get reports => 'Reports';
|
||||
|
||||
@override
|
||||
String get manageAccount => 'Manage your account';
|
||||
|
||||
@override
|
||||
String get configureSystemSettings => 'Configure system settings';
|
||||
|
||||
@override
|
||||
String get updateYourPassword => 'Update your password';
|
||||
|
||||
@override
|
||||
String get getOtp => 'Get OTP';
|
||||
|
||||
@override
|
||||
String get otpEmailPrompt =>
|
||||
'Enter your email to receive a one-time password';
|
||||
|
||||
@override
|
||||
String get enterEmailAddress => 'Enter your email address';
|
||||
|
||||
@override
|
||||
String get sendOtp => 'Send OTP';
|
||||
|
||||
@override
|
||||
String get sendingOtp => 'Sending OTP...';
|
||||
|
||||
@override
|
||||
String get alreadyHaveAccount => 'Already have an account?';
|
||||
|
||||
@override
|
||||
String get backToLogin => 'Back to login';
|
||||
|
||||
@override
|
||||
String get emailLooksGood => 'Email looks good';
|
||||
|
||||
@override
|
||||
String get invalidEmailAddress => 'Invalid email address';
|
||||
|
||||
@override
|
||||
String get noDataAvailable => 'No data available';
|
||||
|
||||
@override
|
||||
String get noResults => 'No results';
|
||||
|
||||
@override
|
||||
String get clearBtn => 'Clear';
|
||||
|
||||
@override
|
||||
String get doneBtn => 'Done';
|
||||
|
||||
@override
|
||||
String get addFiles => 'Add Files';
|
||||
|
||||
@override
|
||||
String get addImage => 'Add Image';
|
||||
|
||||
@override
|
||||
String get addVideo => 'Add Video';
|
||||
|
||||
@override
|
||||
String get insertBtn => 'Insert';
|
||||
|
||||
@override
|
||||
String get noDataFound => 'No data found';
|
||||
|
||||
@override
|
||||
String get sysConfigTitle => 'System Configuration';
|
||||
|
||||
@override
|
||||
String get sysConfigSubtitle =>
|
||||
'Configure system-wide parameters and settings';
|
||||
|
||||
@override
|
||||
String get generatingTheme => 'Generating dynamic theme...';
|
||||
|
||||
@override
|
||||
String get themeApplied =>
|
||||
'Dynamic theme applied! Colors extracted from logo.';
|
||||
|
||||
@override
|
||||
String get themeImmediateNote =>
|
||||
'Theme is applied immediately! Click \"Upload Logo\" to save the logo permanently to the database. The dynamic theme will work even if upload fails.';
|
||||
|
||||
@override
|
||||
String get uploadNewLogo => 'Upload New Logo';
|
||||
|
||||
@override
|
||||
String get removeLogo => 'Remove Logo';
|
||||
|
||||
@override
|
||||
String get logoAlreadyUploaded =>
|
||||
'Company logo is already uploaded and saved in the system. You can upload a new one or remove the existing logo.';
|
||||
|
||||
@override
|
||||
String get manualOverride => 'Enable Manual Override';
|
||||
|
||||
@override
|
||||
String get colorPrimary => 'Primary';
|
||||
|
||||
@override
|
||||
String get colorSecondary => 'Secondary';
|
||||
|
||||
@override
|
||||
String get colorTertiary => 'Tertiary';
|
||||
|
||||
@override
|
||||
String get resetLogoColors => 'Reset to Logo Colors';
|
||||
|
||||
@override
|
||||
String get resetDefault => 'Reset to Default';
|
||||
|
||||
@override
|
||||
String get userRegistration => 'User Registration';
|
||||
|
||||
@override
|
||||
String get allowUserRegistration => 'Allow new users to register accounts';
|
||||
|
||||
@override
|
||||
String get themeGenerated => 'Dynamic Theme Generated';
|
||||
|
||||
@override
|
||||
String get resetThemeTooltip => 'Reset to Default Theme';
|
||||
|
||||
@override
|
||||
String get colorPalette => 'Color Palette';
|
||||
|
||||
@override
|
||||
String get colorAccent1 => 'Accent 1';
|
||||
|
||||
@override
|
||||
String get colorAccent2 => 'Accent 2';
|
||||
|
||||
@override
|
||||
String colorN(String n) {
|
||||
return 'Color $n';
|
||||
}
|
||||
|
||||
@override
|
||||
String get themeInfo => 'Theme Information';
|
||||
|
||||
@override
|
||||
String get totalColors => 'Total Colors';
|
||||
|
||||
@override
|
||||
String get themeDescription => 'Description';
|
||||
|
||||
@override
|
||||
String get warmColors => 'Warm Colors';
|
||||
|
||||
@override
|
||||
String get coolColors => 'Cool Colors';
|
||||
|
||||
@override
|
||||
String get neutralColors => 'Neutral Colors';
|
||||
|
||||
@override
|
||||
String get yes => 'Yes';
|
||||
|
||||
@override
|
||||
String get no => 'No';
|
||||
|
||||
@override
|
||||
String get primaryButton => 'Primary Button';
|
||||
|
||||
@override
|
||||
String get secondaryButton => 'Secondary Button';
|
||||
|
||||
@override
|
||||
String get uploadLogo => 'Upload Logo';
|
||||
|
||||
@override
|
||||
String get clearLogo => 'Clear Logo';
|
||||
|
||||
@override
|
||||
String get saveConfiguration => 'Save Configuration';
|
||||
|
||||
@override
|
||||
String get drawerHome => 'Home';
|
||||
|
||||
@override
|
||||
String get drawerUsers => 'Users';
|
||||
|
||||
@override
|
||||
String get drawerRoles => 'Roles';
|
||||
|
||||
@override
|
||||
String get drawerDepartments => 'Departments';
|
||||
|
||||
@override
|
||||
String get drawerPositions => 'Positions';
|
||||
|
||||
@override
|
||||
String get drawerCharges => 'Charges';
|
||||
|
||||
@override
|
||||
String get drawerWeeks => 'Weeks';
|
||||
|
||||
@override
|
||||
String get drawerShifts => 'Shifts';
|
||||
|
||||
@override
|
||||
String get drawerBilling => 'Billing';
|
||||
|
||||
@override
|
||||
String get drawerEdi => 'EDI Settings';
|
||||
|
||||
@override
|
||||
String get drawerCompany => 'Company';
|
||||
|
||||
@override
|
||||
String get drawerLogo => 'Logo';
|
||||
|
||||
@override
|
||||
String get registerCompany => 'Register Company';
|
||||
|
||||
@override
|
||||
String get accCompanyName => 'Company Name';
|
||||
|
||||
@override
|
||||
String get accCompanyHint => 'Enter company name';
|
||||
|
||||
@override
|
||||
String get accWorkspace => 'Workspace';
|
||||
|
||||
@override
|
||||
String get accWorkspaceHint => 'Enter workspace';
|
||||
|
||||
@override
|
||||
String get accGst => 'GST Number';
|
||||
|
||||
@override
|
||||
String get accGstHint => 'Enter GST number';
|
||||
|
||||
@override
|
||||
String get accMobile => 'Mobile';
|
||||
|
||||
@override
|
||||
String get accMobileHint => 'Enter mobile number';
|
||||
|
||||
@override
|
||||
String get accEmailReadonly => 'Email (read-only)';
|
||||
|
||||
@override
|
||||
String get accPan => 'PAN Card';
|
||||
|
||||
@override
|
||||
String get accPanHint => 'Enter PAN';
|
||||
|
||||
@override
|
||||
String get accWorking => 'Working';
|
||||
|
||||
@override
|
||||
String get accWorkingHint => 'Working status';
|
||||
|
||||
@override
|
||||
String get requiredVal => 'Required';
|
||||
|
||||
@override
|
||||
String get nActive => 'Active';
|
||||
|
||||
@override
|
||||
String get saveChanges => 'Save Changes';
|
||||
|
||||
@override
|
||||
String get selectOption => 'Select an option';
|
||||
|
||||
@override
|
||||
String get removeBtn => 'Remove';
|
||||
|
||||
@override
|
||||
String get ohSnap => 'Oh Snap!';
|
||||
|
||||
@override
|
||||
String get alertTitle => 'Alert';
|
||||
|
||||
@override
|
||||
String get successTitle => 'Success';
|
||||
}
|
||||
@@ -0,0 +1,526 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for Hindi (`hi`).
|
||||
class AppLocalizationsHi extends AppLocalizations {
|
||||
AppLocalizationsHi([String locale = 'hi']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'ऑथसेक फ्लटर';
|
||||
|
||||
@override
|
||||
String get language => 'भाषा';
|
||||
|
||||
@override
|
||||
String get english => 'अंग्रेज़ी';
|
||||
|
||||
@override
|
||||
String get hindi => 'हिन्दी';
|
||||
|
||||
@override
|
||||
String helloUser(String name) {
|
||||
return 'नमस्ते, $name';
|
||||
}
|
||||
|
||||
@override
|
||||
String get user => 'उपयोगकर्ता';
|
||||
|
||||
@override
|
||||
String get logout => 'लॉग आउट';
|
||||
|
||||
@override
|
||||
String get cancel => 'रद्द करें';
|
||||
|
||||
@override
|
||||
String get confirm => 'पुष्टि करें';
|
||||
|
||||
@override
|
||||
String get retry => 'पुनः प्रयास करें';
|
||||
|
||||
@override
|
||||
String get refresh => 'रीफ़्रेश';
|
||||
|
||||
@override
|
||||
String get addNew => 'नया जोड़ें';
|
||||
|
||||
@override
|
||||
String searchEntity(String entity) {
|
||||
return '$entity खोजें...';
|
||||
}
|
||||
|
||||
@override
|
||||
String loadingEntity(String entity) {
|
||||
return '$entity लोड हो रहा है...';
|
||||
}
|
||||
|
||||
@override
|
||||
String noEntityFound(String entity) {
|
||||
return 'कोई $entity नहीं मिला';
|
||||
}
|
||||
|
||||
@override
|
||||
String addEntity(String entity) {
|
||||
return '$entity जोड़ें';
|
||||
}
|
||||
|
||||
@override
|
||||
String createEntity(String entity) {
|
||||
return '$entity बनाएँ';
|
||||
}
|
||||
|
||||
@override
|
||||
String updateEntity(String entity) {
|
||||
return '$entity अपडेट करें';
|
||||
}
|
||||
|
||||
@override
|
||||
String entityRequired(String field) {
|
||||
return '$field आवश्यक है';
|
||||
}
|
||||
|
||||
@override
|
||||
String get errorLoadingData => 'डेटा लोड करने में त्रुटि';
|
||||
|
||||
@override
|
||||
String get somethingWentWrong => 'कुछ गलत हो गया';
|
||||
|
||||
@override
|
||||
String get adjustSearchTerms => 'अपने खोज शब्द बदलें';
|
||||
|
||||
@override
|
||||
String startByAdding(String entity) {
|
||||
return 'अपना पहला $entity जोड़कर शुरू करें';
|
||||
}
|
||||
|
||||
@override
|
||||
String get unknown => 'अज्ञात';
|
||||
|
||||
@override
|
||||
String get scanBarcode => 'बारकोड स्कैन करें';
|
||||
|
||||
@override
|
||||
String get enterOrScanBarcode => 'बारकोड दर्ज करें या स्कैन करें';
|
||||
|
||||
@override
|
||||
String get addAudio => 'ऑडियो जोड़ें';
|
||||
|
||||
@override
|
||||
String get selectAudioFile => 'ऑडियो फ़ाइल चुनें';
|
||||
|
||||
@override
|
||||
String get pickColor => 'रंग चुनें';
|
||||
|
||||
@override
|
||||
String get systemParameters => 'सिस्टम पैरामीटर';
|
||||
|
||||
@override
|
||||
String get editSystemParameters => 'सिस्टम पैरामीटर संपादित करें';
|
||||
|
||||
@override
|
||||
String get goBack => 'वापस जाएँ';
|
||||
|
||||
@override
|
||||
String get profile => 'प्रोफ़ाइल';
|
||||
|
||||
@override
|
||||
String get editProfile => 'प्रोफ़ाइल संपादित करें';
|
||||
|
||||
@override
|
||||
String get accountUpdate => 'खाता अपडेट';
|
||||
|
||||
@override
|
||||
String get changePassword => 'पासवर्ड बदलें';
|
||||
|
||||
@override
|
||||
String get confirmLogout => 'लॉग आउट की पुष्टि करें';
|
||||
|
||||
@override
|
||||
String get confirmLogoutBody => 'क्या आप वाकई लॉग आउट करना चाहते हैं?';
|
||||
|
||||
@override
|
||||
String get logoutAction => 'लॉग आउट';
|
||||
|
||||
@override
|
||||
String get passwordsDoNotMatch => 'पासवर्ड मेल नहीं खाते';
|
||||
|
||||
@override
|
||||
String get requiredField => 'यह फ़ील्ड आवश्यक है';
|
||||
|
||||
@override
|
||||
String get email => 'ईमेल';
|
||||
|
||||
@override
|
||||
String get password => 'पासवर्ड';
|
||||
|
||||
@override
|
||||
String get signIn => 'साइन इन';
|
||||
|
||||
@override
|
||||
String get signUp => 'साइन अप';
|
||||
|
||||
@override
|
||||
String get forgotPassword => 'पासवर्ड भूल गए?';
|
||||
|
||||
@override
|
||||
String get loading => 'लोड हो रहा है...';
|
||||
|
||||
@override
|
||||
String get save => 'सहेजें';
|
||||
|
||||
@override
|
||||
String get delete => 'हटाएँ';
|
||||
|
||||
@override
|
||||
String get edit => 'संपादित करें';
|
||||
|
||||
@override
|
||||
String get close => 'बंद करें';
|
||||
|
||||
@override
|
||||
String get welcomeBack => 'वापस स्वागत है!';
|
||||
|
||||
@override
|
||||
String get signInToContinue => 'अपने खाते में जारी रखने के लिए साइन इन करें';
|
||||
|
||||
@override
|
||||
String get emailAddress => 'ईमेल पता';
|
||||
|
||||
@override
|
||||
String get enterYourEmail => 'अपना ईमेल दर्ज करें';
|
||||
|
||||
@override
|
||||
String get emailRequired => 'ईमेल आवश्यक है';
|
||||
|
||||
@override
|
||||
String get validEmail => 'कृपया मान्य ईमेल दर्ज करें';
|
||||
|
||||
@override
|
||||
String get enterYourPassword => 'अपना पासवर्ड दर्ज करें';
|
||||
|
||||
@override
|
||||
String get passwordRequired => 'पासवर्ड आवश्यक है';
|
||||
|
||||
@override
|
||||
String get passwordMinLength => 'पासवर्ड कम से कम 6 वर्ण का होना चाहिए';
|
||||
|
||||
@override
|
||||
String get noAccount => 'क्या आपका खाता नहीं है?';
|
||||
|
||||
@override
|
||||
String get orContinueWith => 'या इसके साथ जारी रखें';
|
||||
|
||||
@override
|
||||
String get verifyOtp => 'ओटीपी सत्यापित करें';
|
||||
|
||||
@override
|
||||
String get otpSentTo => 'भेजा गया 6 अंकों का कोड दर्ज करें';
|
||||
|
||||
@override
|
||||
String get yourEmail => 'आपका ईमेल';
|
||||
|
||||
@override
|
||||
String get enterOtp => '6 अंकों का ओटीपी दर्ज करें';
|
||||
|
||||
@override
|
||||
String get didNotReceiveCode => 'कोड नहीं मिला?';
|
||||
|
||||
@override
|
||||
String resendIn(int seconds) {
|
||||
return '$seconds सेकंड में पुनः भेजें';
|
||||
}
|
||||
|
||||
@override
|
||||
String get resend => 'पुनः भेजें';
|
||||
|
||||
@override
|
||||
String get dashboard => 'डैशबोर्ड';
|
||||
|
||||
@override
|
||||
String get settings => 'सेटिंग्स';
|
||||
|
||||
@override
|
||||
String get security => 'सुरक्षा';
|
||||
|
||||
@override
|
||||
String get reports => 'रिपोर्ट';
|
||||
|
||||
@override
|
||||
String get manageAccount => 'अपने खाते का प्रबंधन करें';
|
||||
|
||||
@override
|
||||
String get configureSystemSettings => 'सिस्टम सेटिंग्स कॉन्फ़िगर करें';
|
||||
|
||||
@override
|
||||
String get updateYourPassword => 'अपना पासवर्ड अपडेट करें';
|
||||
|
||||
@override
|
||||
String get getOtp => 'ओटीपी प्राप्त करें';
|
||||
|
||||
@override
|
||||
String get otpEmailPrompt =>
|
||||
'वन-टाइम पासवर्ड पाने के लिए अपना ईमेल दर्ज करें';
|
||||
|
||||
@override
|
||||
String get enterEmailAddress => 'अपना ईमेल पता दर्ज करें';
|
||||
|
||||
@override
|
||||
String get sendOtp => 'ओटीपी भेजें';
|
||||
|
||||
@override
|
||||
String get sendingOtp => 'ओटीपी भेजा जा रहा है...';
|
||||
|
||||
@override
|
||||
String get alreadyHaveAccount => 'क्या आपका पहले से खाता है?';
|
||||
|
||||
@override
|
||||
String get backToLogin => 'लॉगिन पर वापस जाएँ';
|
||||
|
||||
@override
|
||||
String get emailLooksGood => 'ईमेल सही है';
|
||||
|
||||
@override
|
||||
String get invalidEmailAddress => 'अमान्य ईमेल पता';
|
||||
|
||||
@override
|
||||
String get noDataAvailable => 'कोई डेटा उपलब्ध नहीं';
|
||||
|
||||
@override
|
||||
String get noResults => 'कोई परिणाम नहीं';
|
||||
|
||||
@override
|
||||
String get clearBtn => 'साफ़ करें';
|
||||
|
||||
@override
|
||||
String get doneBtn => 'हो गया';
|
||||
|
||||
@override
|
||||
String get addFiles => 'फ़ाइलें जोड़ें';
|
||||
|
||||
@override
|
||||
String get addImage => 'छवि जोड़ें';
|
||||
|
||||
@override
|
||||
String get addVideo => 'वीडियो जोड़ें';
|
||||
|
||||
@override
|
||||
String get insertBtn => 'डालें';
|
||||
|
||||
@override
|
||||
String get noDataFound => 'कोई डेटा नहीं मिला';
|
||||
|
||||
@override
|
||||
String get sysConfigTitle => 'सिस्टम कॉन्फ़िगरेशन';
|
||||
|
||||
@override
|
||||
String get sysConfigSubtitle =>
|
||||
'सिस्टम-व्यापी पैरामीटर और सेटिंग्स कॉन्फ़िगर करें';
|
||||
|
||||
@override
|
||||
String get generatingTheme => 'डायनामिक थीम बनाई जा रही है...';
|
||||
|
||||
@override
|
||||
String get themeApplied => 'डायनामिक थीम लागू! लोगो से रंग निकाले गए।';
|
||||
|
||||
@override
|
||||
String get themeImmediateNote =>
|
||||
'थीम तुरंत लागू होती है! लोगो को डेटाबेस में स्थायी रूप से सहेजने के लिए अपलोड लोगो पर क्लिक करें। अपलोड विफल होने पर भी डायनामिक थीम काम करेगी।';
|
||||
|
||||
@override
|
||||
String get uploadNewLogo => 'नया लोगो अपलोड करें';
|
||||
|
||||
@override
|
||||
String get removeLogo => 'लोगो हटाएं';
|
||||
|
||||
@override
|
||||
String get logoAlreadyUploaded =>
|
||||
'कंपनी का लोगो पहले से अपलोड है और सिस्टम में सहेजा गया है। आप नया अपलोड कर सकते हैं या मौजूदा लोगो हटा सकते हैं।';
|
||||
|
||||
@override
|
||||
String get manualOverride => 'मैन्युअल ओवरराइड सक्षम करें';
|
||||
|
||||
@override
|
||||
String get colorPrimary => 'प्राथमिक';
|
||||
|
||||
@override
|
||||
String get colorSecondary => 'द्वितीयक';
|
||||
|
||||
@override
|
||||
String get colorTertiary => 'तृतीयक';
|
||||
|
||||
@override
|
||||
String get resetLogoColors => 'लोगो रंगों पर रीसेट करें';
|
||||
|
||||
@override
|
||||
String get resetDefault => 'डिफ़ॉल्ट पर रीसेट करें';
|
||||
|
||||
@override
|
||||
String get userRegistration => 'उपयोगकर्ता पंजीकरण';
|
||||
|
||||
@override
|
||||
String get allowUserRegistration =>
|
||||
'नए उपयोगकर्ताओं को खाते पंजीकृत करने दें';
|
||||
|
||||
@override
|
||||
String get themeGenerated => 'डायनामिक थीम बनाई गई';
|
||||
|
||||
@override
|
||||
String get resetThemeTooltip => 'डिफ़ॉल्ट थीम पर रीसेट करें';
|
||||
|
||||
@override
|
||||
String get colorPalette => 'रंग पट्टिका';
|
||||
|
||||
@override
|
||||
String get colorAccent1 => 'एक्सेंट 1';
|
||||
|
||||
@override
|
||||
String get colorAccent2 => 'एक्सेंट 2';
|
||||
|
||||
@override
|
||||
String colorN(String n) {
|
||||
return 'रंग $n';
|
||||
}
|
||||
|
||||
@override
|
||||
String get themeInfo => 'थीम जानकारी';
|
||||
|
||||
@override
|
||||
String get totalColors => 'कुल रंग';
|
||||
|
||||
@override
|
||||
String get themeDescription => 'विवरण';
|
||||
|
||||
@override
|
||||
String get warmColors => 'गर्म रंग';
|
||||
|
||||
@override
|
||||
String get coolColors => 'ठंडे रंग';
|
||||
|
||||
@override
|
||||
String get neutralColors => 'तटस्थ रंग';
|
||||
|
||||
@override
|
||||
String get yes => 'हां';
|
||||
|
||||
@override
|
||||
String get no => 'नहीं';
|
||||
|
||||
@override
|
||||
String get primaryButton => 'प्राथमिक बटन';
|
||||
|
||||
@override
|
||||
String get secondaryButton => 'द्वितीयक बटन';
|
||||
|
||||
@override
|
||||
String get uploadLogo => 'लोगो अपलोड करें';
|
||||
|
||||
@override
|
||||
String get clearLogo => 'लोगो साफ़ करें';
|
||||
|
||||
@override
|
||||
String get saveConfiguration => 'कॉन्फ़िगरेशन सहेजें';
|
||||
|
||||
@override
|
||||
String get drawerHome => 'होम';
|
||||
|
||||
@override
|
||||
String get drawerUsers => 'उपयोगकर्ता';
|
||||
|
||||
@override
|
||||
String get drawerRoles => 'भूमिकाएं';
|
||||
|
||||
@override
|
||||
String get drawerDepartments => 'विभाग';
|
||||
|
||||
@override
|
||||
String get drawerPositions => 'पद';
|
||||
|
||||
@override
|
||||
String get drawerCharges => 'शुल्क';
|
||||
|
||||
@override
|
||||
String get drawerWeeks => 'सप्ताह';
|
||||
|
||||
@override
|
||||
String get drawerShifts => 'पारियां';
|
||||
|
||||
@override
|
||||
String get drawerBilling => 'बिलिंग';
|
||||
|
||||
@override
|
||||
String get drawerEdi => 'EDI सेटिंग्स';
|
||||
|
||||
@override
|
||||
String get drawerCompany => 'कंपनी';
|
||||
|
||||
@override
|
||||
String get drawerLogo => 'लोगो';
|
||||
|
||||
@override
|
||||
String get registerCompany => 'कंपनी पंजीकृत करें';
|
||||
|
||||
@override
|
||||
String get accCompanyName => 'कंपनी का नाम';
|
||||
|
||||
@override
|
||||
String get accCompanyHint => 'कंपनी का नाम दर्ज करें';
|
||||
|
||||
@override
|
||||
String get accWorkspace => 'कार्यक्षेत्र';
|
||||
|
||||
@override
|
||||
String get accWorkspaceHint => 'कार्यक्षेत्र दर्ज करें';
|
||||
|
||||
@override
|
||||
String get accGst => 'जीएसटी नंबर';
|
||||
|
||||
@override
|
||||
String get accGstHint => 'जीएसटी नंबर दर्ज करें';
|
||||
|
||||
@override
|
||||
String get accMobile => 'मोबाइल';
|
||||
|
||||
@override
|
||||
String get accMobileHint => 'मोबाइल नंबर दर्ज करें';
|
||||
|
||||
@override
|
||||
String get accEmailReadonly => 'ईमेल (केवल-पठन)';
|
||||
|
||||
@override
|
||||
String get accPan => 'पैन कार्ड';
|
||||
|
||||
@override
|
||||
String get accPanHint => 'पैन दर्ज करें';
|
||||
|
||||
@override
|
||||
String get accWorking => 'कार्य';
|
||||
|
||||
@override
|
||||
String get accWorkingHint => 'कार्य स्थिति';
|
||||
|
||||
@override
|
||||
String get requiredVal => 'आवश्यक';
|
||||
|
||||
@override
|
||||
String get nActive => 'सक्रिय';
|
||||
|
||||
@override
|
||||
String get saveChanges => 'परिवर्तन सहेजें';
|
||||
|
||||
@override
|
||||
String get selectOption => 'एक विकल्प चुनें';
|
||||
|
||||
@override
|
||||
String get removeBtn => 'हटाएं';
|
||||
|
||||
@override
|
||||
String get ohSnap => 'ओह स्नैप!';
|
||||
|
||||
@override
|
||||
String get alertTitle => 'चेतावनी';
|
||||
|
||||
@override
|
||||
String get successTitle => 'सफलता';
|
||||
}
|
||||
@@ -7,14 +7,18 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'core/providers/dynamic_theme_provider.dart';
|
||||
import 'core/providers/locale_provider.dart';
|
||||
import 'core/providers/theme_provider.dart';
|
||||
import 'core/theme/app_theme.dart';
|
||||
import 'l10n/app_localizations.dart';
|
||||
import 'routes/app_routes.dart';
|
||||
import 'utils/managers/user_manager.dart';
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await UserManager().initialize();
|
||||
final localeProvider = LocaleProvider();
|
||||
await localeProvider.initialize();
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||
|
||||
runApp(MultiProvider(
|
||||
@@ -24,6 +28,7 @@ void main() async {
|
||||
ChangeNotifierProvider(create: (context) => SystemParamsViewModel()),
|
||||
ChangeNotifierProvider(create: (context) => ThemeProvider()),
|
||||
ChangeNotifierProvider(create: (context) => DynamicThemeProvider()),
|
||||
ChangeNotifierProvider.value(value: localeProvider),
|
||||
],
|
||||
child: const MyApp(),
|
||||
));
|
||||
@@ -63,8 +68,8 @@ class MyApp extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer2<ThemeProvider, DynamicThemeProvider>(
|
||||
builder: (context, themeProvider, dynamicThemeProvider, child) {
|
||||
return Consumer3<ThemeProvider, DynamicThemeProvider, LocaleProvider>(
|
||||
builder: (context, themeProvider, dynamicThemeProvider, localeProvider, child) {
|
||||
final theme = AppTheme.getTheme(context);
|
||||
// Set system UI overlay style
|
||||
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
|
||||
@@ -86,6 +91,9 @@ class MyApp extends StatelessWidget {
|
||||
initialRoute: RouteNames.splashView,
|
||||
onGenerateRoute: AppRoutes.generateRoutes,
|
||||
navigatorKey: navigatorKey,
|
||||
locale: localeProvider.locale,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
builder: (context, child) {
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../core/constants/ui_constants.dart';
|
||||
import '../buttons/modern_button.dart';
|
||||
@@ -208,7 +209,7 @@ class _ModernImagePickerState extends State<ModernImagePicker>
|
||||
if (hasImage && widget.onRemoveImage != null) ...[
|
||||
const SizedBox(width: UIConstants.spacing12),
|
||||
ModernButton(
|
||||
text: 'Remove',
|
||||
text: AppLocalizations.of(context)!.removeBtn,
|
||||
type: ModernButtonType.danger,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.delete_outline),
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../core/providers/locale_provider.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
class LanguageSwitcher extends StatelessWidget {
|
||||
const LanguageSwitcher({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final locale = context.watch<LocaleProvider>().locale.languageCode;
|
||||
final strings = AppLocalizations.of(context)!;
|
||||
return DropdownButtonHideUnderline(
|
||||
child: DropdownButton<String>(
|
||||
value: locale,
|
||||
icon: const Icon(Icons.language),
|
||||
onChanged: (code) {
|
||||
if (code != null) context.read<LocaleProvider>().setLocale(code);
|
||||
},
|
||||
items: [
|
||||
DropdownMenuItem(value: 'en', child: Text(strings.english)),
|
||||
DropdownMenuItem(value: 'hi', child: Text(strings.hindi)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../core/constants/ui_constants.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import '../../../utils/managers/user_manager.dart';
|
||||
import '../../../view_model/profile/profile_view_model.dart';
|
||||
import '../buttons/modern_button.dart';
|
||||
import '../language_switcher.dart';
|
||||
|
||||
class ModernDrawer extends StatelessWidget {
|
||||
final List<DrawerItem> items;
|
||||
@@ -52,6 +54,17 @@ class ModernDrawer extends StatelessWidget {
|
||||
// Footer
|
||||
if (footer != null) footer!,
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: UIConstants.spacing24),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(AppLocalizations.of(context)!.language),
|
||||
const LanguageSwitcher(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Logout Section
|
||||
_buildLogoutSection(context, theme, colorScheme),
|
||||
],
|
||||
@@ -122,7 +135,8 @@ class ModernDrawer extends StatelessWidget {
|
||||
|
||||
// User Name
|
||||
Text(
|
||||
"Hello, ${userName ?? 'User'}",
|
||||
AppLocalizations.of(context)!
|
||||
.helloUser(userName ?? AppLocalizations.of(context)!.user),
|
||||
style: theme.textTheme.titleLarge?.copyWith(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -216,7 +230,7 @@ class ModernDrawer extends StatelessWidget {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UIConstants.spacing24),
|
||||
child: ModernButton(
|
||||
text: 'Logout',
|
||||
text: AppLocalizations.of(context)!.logout,
|
||||
type: ModernButtonType.danger,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.logout),
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../core/constants/ui_constants.dart';
|
||||
import '../../core/providers/dynamic_theme_provider.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
class ThemePreview extends StatelessWidget {
|
||||
const ThemePreview({super.key});
|
||||
@@ -56,7 +57,7 @@ class ThemePreview extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Dynamic Theme Generated',
|
||||
AppLocalizations.of(context)!.themeGenerated,
|
||||
style:
|
||||
Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
@@ -79,7 +80,8 @@ class ThemePreview extends StatelessWidget {
|
||||
Icons.refresh,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
tooltip: 'Reset to Default Theme',
|
||||
tooltip: AppLocalizations.of(context)!
|
||||
.resetThemeTooltip,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -88,7 +90,7 @@ class ThemePreview extends StatelessWidget {
|
||||
|
||||
// Color Palette
|
||||
Text(
|
||||
'Color Palette',
|
||||
AppLocalizations.of(context)!.colorPalette,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -103,11 +105,11 @@ class ThemePreview extends StatelessWidget {
|
||||
children: logoColors.take(5).map((color) {
|
||||
final index = logoColors.indexOf(color);
|
||||
final labels = [
|
||||
'Primary',
|
||||
'Secondary',
|
||||
'Tertiary',
|
||||
'Accent 1',
|
||||
'Accent 2'
|
||||
AppLocalizations.of(context)!.colorPrimary,
|
||||
AppLocalizations.of(context)!.colorSecondary,
|
||||
AppLocalizations.of(context)!.colorTertiary,
|
||||
AppLocalizations.of(context)!.colorAccent1,
|
||||
AppLocalizations.of(context)!.colorAccent2
|
||||
];
|
||||
|
||||
return Column(
|
||||
@@ -142,7 +144,8 @@ class ThemePreview extends StatelessWidget {
|
||||
Text(
|
||||
index < labels.length
|
||||
? labels[index]
|
||||
: 'Color ${index + 1}',
|
||||
: AppLocalizations.of(context)!
|
||||
.colorN((index + 1).toString()),
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -169,7 +172,7 @@ class ThemePreview extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Theme Information',
|
||||
AppLocalizations.of(context)!.themeInfo,
|
||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -177,24 +180,27 @@ class ThemePreview extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing8),
|
||||
_buildInfoRow(
|
||||
'Total Colors', '${paletteInfo['totalColors']}'),
|
||||
_buildInfoRow('Description', paletteInfo['description']),
|
||||
AppLocalizations.of(context)!.totalColors,
|
||||
'${paletteInfo['totalColors']}'),
|
||||
_buildInfoRow(
|
||||
AppLocalizations.of(context)!.themeDescription,
|
||||
paletteInfo['description']),
|
||||
if (paletteInfo['characteristics'] != null) ...[
|
||||
_buildInfoRow(
|
||||
'Warm Colors',
|
||||
AppLocalizations.of(context)!.warmColors,
|
||||
paletteInfo['characteristics']['warm']
|
||||
? 'Yes'
|
||||
: 'No'),
|
||||
? AppLocalizations.of(context)!.yes
|
||||
: AppLocalizations.of(context)!.no),
|
||||
_buildInfoRow(
|
||||
'Cool Colors',
|
||||
AppLocalizations.of(context)!.coolColors,
|
||||
paletteInfo['characteristics']['cool']
|
||||
? 'Yes'
|
||||
: 'No'),
|
||||
? AppLocalizations.of(context)!.yes
|
||||
: AppLocalizations.of(context)!.no),
|
||||
_buildInfoRow(
|
||||
'Neutral Colors',
|
||||
AppLocalizations.of(context)!.neutralColors,
|
||||
paletteInfo['characteristics']['neutral']
|
||||
? 'Yes'
|
||||
: 'No'),
|
||||
? AppLocalizations.of(context)!.yes
|
||||
: AppLocalizations.of(context)!.no),
|
||||
],
|
||||
],
|
||||
),
|
||||
@@ -216,7 +222,8 @@ class ThemePreview extends StatelessWidget {
|
||||
BorderRadius.circular(UIConstants.radius12),
|
||||
),
|
||||
),
|
||||
child: const Text('Primary Button'),
|
||||
child: Text(AppLocalizations.of(context)!
|
||||
.primaryButton),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: UIConstants.spacing12),
|
||||
@@ -231,7 +238,8 @@ class ThemePreview extends StatelessWidget {
|
||||
BorderRadius.circular(UIConstants.radius12),
|
||||
),
|
||||
),
|
||||
child: const Text('Secondary Button'),
|
||||
child: Text(AppLocalizations.of(context)!
|
||||
.secondaryButton),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:base_project/commans/widgets/custom_textform_field.dart';
|
||||
import 'package:base_project/commans/widgets/custome_elevated_button.dart';
|
||||
import 'package:base_project/core/constants/ui_constants.dart';
|
||||
import 'package:base_project/core/providers/dynamic_theme_provider.dart';
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:base_project/utils/validator/text_feild_validator.dart';
|
||||
import 'package:base_project/view/auth/sign_up_view.dart';
|
||||
import 'package:base_project/view_model/auth/auth_view_model.dart';
|
||||
@@ -231,7 +232,8 @@ class _AdminRegViewState extends State<AdminRegView>
|
||||
builder: (context, provider, child) {
|
||||
return MyCustomElevatedButton(
|
||||
isLoading: provider.isLoading,
|
||||
child: const Text("Register Company"),
|
||||
child: Text(AppLocalizations.of(context)!
|
||||
.registerCompany),
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
final Map<String, dynamic> signUpData = {
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
class GetOtpView extends StatefulWidget {
|
||||
const GetOtpView({super.key});
|
||||
@@ -483,7 +484,7 @@ class _GetOtpViewState extends State<GetOtpView> with TickerProviderStateMixin {
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Get OTP',
|
||||
AppLocalizations.of(context)!.getOtp,
|
||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -493,7 +494,7 @@ class _GetOtpViewState extends State<GetOtpView> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing12),
|
||||
Text(
|
||||
'Enter your email to receive a one-time password',
|
||||
AppLocalizations.of(context)!.otpEmailPrompt,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurface.withOpacity(0.8),
|
||||
fontWeight: FontWeight.w400,
|
||||
@@ -543,8 +544,8 @@ class _GetOtpViewState extends State<GetOtpView> with TickerProviderStateMixin {
|
||||
children: [
|
||||
// Email Field
|
||||
_buildEnhancedTextField(
|
||||
label: 'Email Address',
|
||||
hint: 'Enter your email address',
|
||||
label: AppLocalizations.of(context)!.emailAddress,
|
||||
hint: AppLocalizations.of(context)!.enterEmailAddress,
|
||||
controller: _emailController,
|
||||
focusNode: _emailFocusNode,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
@@ -554,12 +555,12 @@ class _GetOtpViewState extends State<GetOtpView> with TickerProviderStateMixin {
|
||||
textInputAction: TextInputAction.done,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Email is required';
|
||||
return AppLocalizations.of(context)!.emailRequired;
|
||||
}
|
||||
if (!RegExp(
|
||||
r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
|
||||
.hasMatch(value)) {
|
||||
return 'Please enter a valid email';
|
||||
return AppLocalizations.of(context)!.validEmail;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -847,7 +848,9 @@ class _GetOtpViewState extends State<GetOtpView> with TickerProviderStateMixin {
|
||||
) ??
|
||||
const TextStyle(),
|
||||
child: Text(
|
||||
isLoading ? 'Sending OTP...' : 'Send OTP',
|
||||
isLoading
|
||||
? AppLocalizations.of(context)!.sendingOtp
|
||||
: AppLocalizations.of(context)!.sendOtp,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -919,7 +922,7 @@ class _GetOtpViewState extends State<GetOtpView> with TickerProviderStateMixin {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"Already have an account? ",
|
||||
'${AppLocalizations.of(context)!.alreadyHaveAccount} ',
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.grey.shade700,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -928,7 +931,7 @@ class _GetOtpViewState extends State<GetOtpView> with TickerProviderStateMixin {
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(
|
||||
'Back to Login',
|
||||
AppLocalizations.of(context)!.backToLogin,
|
||||
style: Theme.of(context).textTheme.labelLarge?.copyWith(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -982,8 +985,10 @@ class _GetOtpViewState extends State<GetOtpView> with TickerProviderStateMixin {
|
||||
? Icons.info_outline
|
||||
: (_isEmailValid ? Icons.check_circle : Icons.error_outline);
|
||||
final msg = _emailController.text.isEmpty
|
||||
? 'Enter your email address'
|
||||
: (_isEmailValid ? 'Email looks good' : 'Invalid email address');
|
||||
? AppLocalizations.of(context)!.enterEmailAddress
|
||||
: (_isEmailValid
|
||||
? AppLocalizations.of(context)!.emailLooksGood
|
||||
: AppLocalizations.of(context)!.invalidEmailAddress);
|
||||
|
||||
return Container(
|
||||
width: UIConstants.getResponsiveValue(
|
||||
|
||||
@@ -7,6 +7,7 @@ import 'package:base_project/routes/route_names.dart';
|
||||
import 'package:base_project/view_model/auth/auth_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
import '../../core/providers/dynamic_theme_provider.dart';
|
||||
import '../../core/providers/theme_provider.dart';
|
||||
@@ -497,7 +498,7 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Welcome Back!',
|
||||
AppLocalizations.of(context)!.welcomeBack,
|
||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -507,7 +508,7 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing12),
|
||||
Text(
|
||||
'Sign in to continue to your account',
|
||||
AppLocalizations.of(context)!.signInToContinue,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: colorScheme.onSurface.withOpacity(0.8),
|
||||
fontWeight: FontWeight.w400,
|
||||
@@ -557,8 +558,8 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
children: [
|
||||
// Email Field
|
||||
_buildEnhancedTextField(
|
||||
label: 'Email Address',
|
||||
hint: 'Enter your email',
|
||||
label: AppLocalizations.of(context)!.emailAddress,
|
||||
hint: AppLocalizations.of(context)!.enterYourEmail,
|
||||
controller: _emailController,
|
||||
focusNode: _emailFocusNode,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
@@ -569,11 +570,11 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
onSubmitted: (_) => _passwordFocusNode.requestFocus(),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Email is required';
|
||||
return AppLocalizations.of(context)!.emailRequired;
|
||||
}
|
||||
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$')
|
||||
.hasMatch(value)) {
|
||||
return 'Please enter a valid email';
|
||||
return AppLocalizations.of(context)!.validEmail;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -583,8 +584,8 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
|
||||
// Password Field
|
||||
_buildEnhancedTextField(
|
||||
label: 'Password',
|
||||
hint: 'Enter your password',
|
||||
label: AppLocalizations.of(context)!.password,
|
||||
hint: AppLocalizations.of(context)!.enterYourPassword,
|
||||
controller: _passwordController,
|
||||
focusNode: _passwordFocusNode,
|
||||
obscureText: !_isPasswordVisible,
|
||||
@@ -607,10 +608,10 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
textInputAction: TextInputAction.done,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Password is required';
|
||||
return AppLocalizations.of(context)!.passwordRequired;
|
||||
}
|
||||
if (value.length < 6) {
|
||||
return 'Password must be at least 6 characters';
|
||||
return AppLocalizations.of(context)!.passwordMinLength;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@@ -727,7 +728,7 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
),
|
||||
const SizedBox(width: UIConstants.spacing6),
|
||||
Text(
|
||||
'Forgot Password?',
|
||||
AppLocalizations.of(context)!.forgotPassword,
|
||||
style: Theme.of(context).textTheme.labelSmall?.copyWith(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -771,7 +772,7 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
child: Consumer<AuthViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return ModernButton(
|
||||
text: 'Sign In',
|
||||
text: AppLocalizations.of(context)!.signIn,
|
||||
type: ModernButtonType.primary,
|
||||
size: ModernButtonSize.large,
|
||||
isLoading: provider.isLoading,
|
||||
@@ -823,7 +824,7 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
"Don't have an account? ",
|
||||
'${AppLocalizations.of(context)!.noAccount} ',
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.grey.shade700,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -834,7 +835,7 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
Navigator.pushNamed(context, RouteNames.getOtpView);
|
||||
},
|
||||
child: Text(
|
||||
'Sign Up',
|
||||
AppLocalizations.of(context)!.signUp,
|
||||
style: Theme.of(context).textTheme.labelLarge?.copyWith(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -870,7 +871,7 @@ class _LoginViewState extends State<LoginView> with TickerProviderStateMixin {
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UIConstants.spacing16),
|
||||
child: Text(
|
||||
'Or continue with',
|
||||
AppLocalizations.of(context)!.orContinueWith,
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Colors.white.withOpacity(0.9),
|
||||
fontWeight: FontWeight.w500,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:base_project/core/constants/ui_constants.dart';
|
||||
import 'package:base_project/core/providers/dynamic_theme_provider.dart';
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:base_project/routes/route_names.dart';
|
||||
import 'package:base_project/shared/widgets/app_bar/modern_app_bar.dart';
|
||||
import 'package:base_project/shared/widgets/buttons/modern_button.dart';
|
||||
@@ -322,7 +323,7 @@ class _SignUpViewState extends State<SignUpView> with TickerProviderStateMixin {
|
||||
Consumer<AuthViewModel>(
|
||||
builder: (context, provider, child) {
|
||||
return ModernButton(
|
||||
text: 'Sign Up',
|
||||
text: AppLocalizations.of(context)!.signUp,
|
||||
type: ModernButtonType.primary,
|
||||
size: ModernButtonSize.large,
|
||||
isLoading: provider.isLoading,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SignupView extends StatelessWidget {
|
||||
@@ -14,7 +15,7 @@ class SignupView extends StatelessWidget {
|
||||
},
|
||||
icon: Icon(Icons.adaptive.arrow_back),
|
||||
),
|
||||
title: const Text("SignUp"),
|
||||
title: Text(AppLocalizations.of(context)!.signUp),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:pinput/pinput.dart';
|
||||
import 'package:base_project/commans/widgets/custome_elevated_button.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import 'package:base_project/core/constants/ui_constants.dart';
|
||||
import 'package:base_project/core/providers/dynamic_theme_provider.dart';
|
||||
|
||||
@@ -83,7 +84,7 @@ class _VerifyOtpViewState extends State<VerifyOtpView>
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
title: Text(
|
||||
'Verify OTP',
|
||||
AppLocalizations.of(context)!.verifyOtp,
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
color: colorScheme.primary,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -147,7 +148,7 @@ class _VerifyOtpViewState extends State<VerifyOtpView>
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing16),
|
||||
Text(
|
||||
'Enter the 6-digit code sent to',
|
||||
AppLocalizations.of(context)!.otpSentTo,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
@@ -157,7 +158,7 @@ class _VerifyOtpViewState extends State<VerifyOtpView>
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Text(
|
||||
widget.email ?? 'your email',
|
||||
widget.email ?? AppLocalizations.of(context)!.yourEmail,
|
||||
style:
|
||||
Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: colorScheme.primary,
|
||||
@@ -233,7 +234,7 @@ class _VerifyOtpViewState extends State<VerifyOtpView>
|
||||
onPressed: () async {
|
||||
if (_otpController.text.length < 6) {
|
||||
ToastMessageUtil.showToast(
|
||||
message: 'Enter 6-digit OTP',
|
||||
message: AppLocalizations.of(context)!.enterOtp,
|
||||
toastType: ToastType.error,
|
||||
);
|
||||
return;
|
||||
@@ -268,7 +269,7 @@ class _VerifyOtpViewState extends State<VerifyOtpView>
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text('Verify OTP'),
|
||||
child: Text(AppLocalizations.of(context)!.verifyOtp),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -285,8 +286,9 @@ class _VerifyOtpViewState extends State<VerifyOtpView>
|
||||
children: [
|
||||
Text(
|
||||
provider.isResendEnabled
|
||||
? "Didn't receive code?"
|
||||
: 'Resend in ${provider.start}s',
|
||||
? AppLocalizations.of(context)!.didNotReceiveCode
|
||||
: AppLocalizations.of(context)!
|
||||
.resendIn(provider.start),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
@@ -304,7 +306,7 @@ class _VerifyOtpViewState extends State<VerifyOtpView>
|
||||
}
|
||||
: null,
|
||||
child: Text(
|
||||
'Resend',
|
||||
AppLocalizations.of(context)!.resend,
|
||||
style: TextStyle(
|
||||
color: provider.isResendEnabled
|
||||
? colorScheme.primary
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:base_project/utils/managers/user_manager.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:base_project/view_model/system_params/system_params_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
class HomeView extends StatefulWidget {
|
||||
const HomeView({super.key});
|
||||
@@ -32,54 +33,54 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
// Dashboard stats (replace with real API data)
|
||||
List<Map<String, dynamic>> _dashboardStats = [];
|
||||
|
||||
final List<Map<String, dynamic>> _quickActions = [
|
||||
List<Map<String, dynamic>> _quickActions(BuildContext context) => [
|
||||
{
|
||||
'label': 'Profile',
|
||||
'label': AppLocalizations.of(context)!.profile,
|
||||
'icon': Icons.person,
|
||||
'onTap': () {},
|
||||
'backgroundColor': null, // Use theme default
|
||||
},
|
||||
{
|
||||
'label': 'Settings',
|
||||
'label': AppLocalizations.of(context)!.settings,
|
||||
'icon': Icons.settings,
|
||||
'onTap': () {},
|
||||
'backgroundColor': null,
|
||||
},
|
||||
{
|
||||
'label': 'Security',
|
||||
'label': AppLocalizations.of(context)!.security,
|
||||
'icon': Icons.security,
|
||||
'onTap': () {},
|
||||
'backgroundColor': null,
|
||||
},
|
||||
{
|
||||
'label': 'Reports',
|
||||
'label': AppLocalizations.of(context)!.reports,
|
||||
'icon': Icons.analytics,
|
||||
'onTap': () {},
|
||||
'backgroundColor': null,
|
||||
},
|
||||
];
|
||||
|
||||
final List<DrawerItem> _drawerItems = [
|
||||
List<DrawerItem> _drawerItems(BuildContext context) => [
|
||||
DrawerItem(
|
||||
icon: Icons.person,
|
||||
title: 'Profile',
|
||||
subtitle: 'Manage your account',
|
||||
title: AppLocalizations.of(context)!.profile,
|
||||
subtitle: AppLocalizations.of(context)!.manageAccount,
|
||||
onTap: (context) {
|
||||
Navigator.pushNamed(context, RouteNames.profileView);
|
||||
},
|
||||
),
|
||||
DrawerItem(
|
||||
icon: Icons.system_security_update,
|
||||
title: 'System Parameters',
|
||||
subtitle: 'Configure system settings',
|
||||
title: AppLocalizations.of(context)!.systemParameters,
|
||||
subtitle: AppLocalizations.of(context)!.configureSystemSettings,
|
||||
onTap: (context) {
|
||||
Navigator.pushNamed(context, RouteNames.systemParamsView);
|
||||
},
|
||||
),
|
||||
DrawerItem(
|
||||
icon: Icons.password,
|
||||
title: 'Change Password',
|
||||
subtitle: 'Update your password',
|
||||
title: AppLocalizations.of(context)!.changePassword,
|
||||
subtitle: AppLocalizations.of(context)!.updateYourPassword,
|
||||
onTap: (context) {
|
||||
Navigator.pushNamed(context, RouteNames.changePasswordView);
|
||||
},
|
||||
@@ -226,7 +227,7 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
return Scaffold(
|
||||
backgroundColor: colorScheme.background,
|
||||
appBar: ModernAppBar(
|
||||
title: 'Dashboard',
|
||||
title: AppLocalizations.of(context)!.dashboard,
|
||||
centerTitle: false,
|
||||
showLogoInTitle: true,
|
||||
logoImage: _getDashboardLogoImage(colorScheme),
|
||||
@@ -237,7 +238,7 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
Navigator.pushNamed(context, RouteNames.profileView);
|
||||
},
|
||||
),
|
||||
drawer: ModernDrawer(items: _drawerItems),
|
||||
drawer: ModernDrawer(items: _drawerItems(context)),
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
@@ -339,7 +340,8 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Welcome back, ${userName ?? 'User'}! ð',
|
||||
AppLocalizations.of(context)!
|
||||
.helloUser(userName ?? AppLocalizations.of(context)!.user),
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
color: colorScheme.onBackground,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -468,9 +470,9 @@ class _HomeViewState extends State<HomeView> with TickerProviderStateMixin {
|
||||
mainAxisSpacing: UIConstants.spacing16,
|
||||
childAspectRatio: 1.0,
|
||||
),
|
||||
itemCount: _quickActions.length,
|
||||
itemCount: _quickActions(context).length,
|
||||
itemBuilder: (context, index) {
|
||||
final action = _quickActions[index];
|
||||
final action = _quickActions(context)[index];
|
||||
return QuickActionButton(
|
||||
label: action['label'],
|
||||
icon: action['icon'],
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:base_project/core/constants/ui_constants.dart';
|
||||
import 'package:base_project/core/providers/dynamic_theme_provider.dart';
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:base_project/shared/widgets/app_bar/modern_app_bar.dart';
|
||||
import 'package:base_project/shared/widgets/inputs/modern_text_field.dart';
|
||||
import 'package:base_project/shared/widgets/buttons/modern_button.dart';
|
||||
@@ -160,33 +161,37 @@ class _AccountUpdateViewState extends State<AccountUpdateView>
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
ModernTextField(
|
||||
label: 'Company Name',
|
||||
hint: 'Enter company name',
|
||||
label: AppLocalizations.of(context)!.accCompanyName,
|
||||
hint: AppLocalizations.of(context)!.accCompanyHint,
|
||||
controller: _companyName,
|
||||
prefixIcon: const Icon(Icons.business),
|
||||
validator: (v) =>
|
||||
(v == null || v.isEmpty) ? 'Required' : null,
|
||||
(v == null || v.isEmpty)
|
||||
? AppLocalizations.of(context)!.requiredVal
|
||||
: null,
|
||||
),
|
||||
SizedBox(height: UIConstants.spacing20),
|
||||
ModernTextField(
|
||||
label: 'Workspace',
|
||||
hint: 'Enter workspace',
|
||||
label: AppLocalizations.of(context)!.accWorkspace,
|
||||
hint: AppLocalizations.of(context)!.accWorkspaceHint,
|
||||
controller: _workspace,
|
||||
prefixIcon: const Icon(Icons.apartment_outlined),
|
||||
validator: (v) =>
|
||||
(v == null || v.isEmpty) ? 'Required' : null,
|
||||
(v == null || v.isEmpty)
|
||||
? AppLocalizations.of(context)!.requiredVal
|
||||
: null,
|
||||
),
|
||||
SizedBox(height: UIConstants.spacing20),
|
||||
ModernTextField(
|
||||
label: 'GST Number',
|
||||
hint: 'Enter GST number',
|
||||
label: AppLocalizations.of(context)!.accGst,
|
||||
hint: AppLocalizations.of(context)!.accGstHint,
|
||||
controller: _gstNumber,
|
||||
prefixIcon: const Icon(Icons.confirmation_number_outlined),
|
||||
),
|
||||
SizedBox(height: UIConstants.spacing20),
|
||||
ModernTextField(
|
||||
label: 'Mobile',
|
||||
hint: 'Enter mobile number',
|
||||
label: AppLocalizations.of(context)!.accMobile,
|
||||
hint: AppLocalizations.of(context)!.accMobileHint,
|
||||
controller: _mobile,
|
||||
keyboardType: TextInputType.phone,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
@@ -195,23 +200,23 @@ class _AccountUpdateViewState extends State<AccountUpdateView>
|
||||
SizedBox(height: UIConstants.spacing20),
|
||||
AbsorbPointer(
|
||||
child: ModernTextField(
|
||||
label: 'Email (read-only)',
|
||||
hint: 'Email',
|
||||
label: AppLocalizations.of(context)!.accEmailReadonly,
|
||||
hint: AppLocalizations.of(context)!.email,
|
||||
controller: _email,
|
||||
prefixIcon: const Icon(Icons.email_outlined),
|
||||
),
|
||||
),
|
||||
SizedBox(height: UIConstants.spacing20),
|
||||
ModernTextField(
|
||||
label: 'PAN Card',
|
||||
hint: 'Enter PAN',
|
||||
label: AppLocalizations.of(context)!.accPan,
|
||||
hint: AppLocalizations.of(context)!.accPanHint,
|
||||
controller: _pancard,
|
||||
prefixIcon: const Icon(Icons.badge_outlined),
|
||||
),
|
||||
SizedBox(height: UIConstants.spacing20),
|
||||
ModernTextField(
|
||||
label: 'Working',
|
||||
hint: 'Working status',
|
||||
label: AppLocalizations.of(context)!.accWorking,
|
||||
hint: AppLocalizations.of(context)!.accWorkingHint,
|
||||
controller: _working,
|
||||
prefixIcon: const Icon(Icons.work_outline),
|
||||
),
|
||||
@@ -223,7 +228,7 @@ class _AccountUpdateViewState extends State<AccountUpdateView>
|
||||
onChanged: (v) => setState(() => _active = v),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
const Text('Active')
|
||||
Text(AppLocalizations.of(context)!.nActive)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
@@ -234,7 +239,7 @@ class _AccountUpdateViewState extends State<AccountUpdateView>
|
||||
desktop: UIConstants.spacing48,
|
||||
)),
|
||||
ModernButton(
|
||||
text: 'Update Account',
|
||||
text: AppLocalizations.of(context)!.accountUpdate,
|
||||
type: ModernButtonType.primary,
|
||||
size: ModernButtonSize.large,
|
||||
isLoading: vm.isUpdating,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:base_project/commans/widgets/custom_textform_field.dart';
|
||||
import 'package:base_project/commans/widgets/custome_elevated_button.dart';
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:base_project/resources/app_colors.dart';
|
||||
import 'package:base_project/utils/managers/user_manager.dart';
|
||||
import 'package:base_project/utils/validator/text_feild_validator.dart';
|
||||
@@ -372,7 +373,7 @@ class _ChangePasswordState extends State<ChangePassword>
|
||||
Consumer<ProfileViewModel>(
|
||||
builder: (context, provider, _) {
|
||||
return ModernButton(
|
||||
text: 'Change Password',
|
||||
text: AppLocalizations.of(context)!.changePassword,
|
||||
type: ModernButtonType.primary,
|
||||
size: ModernButtonSize.large,
|
||||
isLoading: provider.isUpdating,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:base_project/commans/widgets/custom_textform_field.dart';
|
||||
import 'package:base_project/commans/widgets/custome_elevated_button.dart';
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:base_project/model/user/user_profile.dart';
|
||||
import 'package:base_project/resources/app_colors.dart';
|
||||
import 'package:base_project/view_model/profile/profile_view_model.dart';
|
||||
@@ -396,7 +397,7 @@ class _EditProfileState extends State<EditProfile>
|
||||
Consumer<ProfileViewModel>(
|
||||
builder: (context, provider, _) {
|
||||
return ModernButton(
|
||||
text: 'Save Changes',
|
||||
text: AppLocalizations.of(context)!.saveChanges,
|
||||
type: ModernButtonType.primary,
|
||||
size: ModernButtonSize.large,
|
||||
isLoading: provider.isUpdating,
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:base_project/utils/managers/user_manager.dart';
|
||||
import 'package:base_project/view/dashboard/profile/edit_profile.dart';
|
||||
import 'package:base_project/view_model/profile/profile_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:base_project/core/providers/dynamic_theme_provider.dart';
|
||||
@@ -77,7 +78,7 @@ class _ProfileViewState extends State<ProfileView>
|
||||
|
||||
return Scaffold(
|
||||
appBar: ModernAppBar(
|
||||
title: 'Profile',
|
||||
title: AppLocalizations.of(context)!.profile,
|
||||
automaticallyImplyLeading: true,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back),
|
||||
@@ -393,7 +394,7 @@ class _ProfileViewState extends State<ProfileView>
|
||||
context,
|
||||
colorScheme: colorScheme,
|
||||
icon: Icons.edit_outlined,
|
||||
title: 'Edit Profile',
|
||||
title: AppLocalizations.of(context)!.editProfile,
|
||||
subtitle: 'Update your personal information',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
@@ -411,7 +412,7 @@ class _ProfileViewState extends State<ProfileView>
|
||||
context,
|
||||
colorScheme: colorScheme,
|
||||
icon: Icons.manage_accounts_outlined,
|
||||
title: 'Account Update',
|
||||
title: AppLocalizations.of(context)!.accountUpdate,
|
||||
subtitle: 'Update company/workspace details',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
@@ -427,7 +428,7 @@ class _ProfileViewState extends State<ProfileView>
|
||||
context,
|
||||
colorScheme: colorScheme,
|
||||
icon: Icons.lock_outline,
|
||||
title: 'Change Password',
|
||||
title: AppLocalizations.of(context)!.changePassword,
|
||||
subtitle: 'Update your account security',
|
||||
onTap: () {
|
||||
Navigator.pushNamed(context, RouteNames.changePasswordView);
|
||||
@@ -438,7 +439,7 @@ class _ProfileViewState extends State<ProfileView>
|
||||
context,
|
||||
colorScheme: colorScheme,
|
||||
icon: Icons.logout,
|
||||
title: 'Logout',
|
||||
title: AppLocalizations.of(context)!.logout,
|
||||
subtitle: 'Sign out of your account',
|
||||
iconColor: colorScheme.error,
|
||||
onTap: () => _showLogoutDialog(context, colorScheme),
|
||||
@@ -541,10 +542,10 @@ class _ProfileViewState extends State<ProfileView>
|
||||
size: UIConstants.iconSizeMedium,
|
||||
),
|
||||
const SizedBox(width: UIConstants.spacing12),
|
||||
const Text("Confirm Logout"),
|
||||
Text(AppLocalizations.of(context)!.confirmLogout),
|
||||
],
|
||||
),
|
||||
content: const Text("Are you sure you want to log out?"),
|
||||
content: Text(AppLocalizations.of(context)!.confirmLogoutBody),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
@@ -563,7 +564,7 @@ class _ProfileViewState extends State<ProfileView>
|
||||
backgroundColor: colorScheme.error,
|
||||
foregroundColor: colorScheme.onError,
|
||||
),
|
||||
child: const Text("Log Out"),
|
||||
child: Text(AppLocalizations.of(context)!.logoutAction),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
|
||||
class EditSystemParams extends StatelessWidget {
|
||||
const EditSystemParams({super.key});
|
||||
@@ -13,9 +14,9 @@ class EditSystemParams extends StatelessWidget {
|
||||
},
|
||||
icon: Icon(Icons.adaptive.arrow_back),
|
||||
),
|
||||
title: const Text("Edit System Parameters"),
|
||||
title: Text(AppLocalizations.of(context)!.editSystemParameters),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import 'package:base_project/shared/widgets/theme_preview.dart';
|
||||
import 'package:base_project/utils/managers/user_manager.dart';
|
||||
import 'package:base_project/view_model/system_params/system_params_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:base_project/core/providers/dynamic_theme_provider.dart';
|
||||
|
||||
@@ -235,7 +236,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
return Scaffold(
|
||||
backgroundColor: colorScheme.background,
|
||||
appBar: ModernAppBar(
|
||||
title: 'System Parameters',
|
||||
title: AppLocalizations.of(context)!.systemParameters,
|
||||
userAvatar: null,
|
||||
userName: userName,
|
||||
onProfilePressed: () {},
|
||||
@@ -409,7 +410,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'System Configuration',
|
||||
AppLocalizations.of(context)!.sysConfigTitle,
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
color: colorScheme.onBackground,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -417,7 +418,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing8),
|
||||
Text(
|
||||
'Configure system-wide parameters and settings',
|
||||
AppLocalizations.of(context)!.sysConfigSubtitle,
|
||||
style: theme.textTheme.bodyLarge?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -691,7 +692,8 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
),
|
||||
const SizedBox(width: UIConstants.spacing8),
|
||||
Text(
|
||||
'Generating dynamic theme...',
|
||||
AppLocalizations.of(context)!
|
||||
.generatingTheme,
|
||||
style: TextStyle(
|
||||
color: Colors.blue,
|
||||
fontSize: 12,
|
||||
@@ -720,7 +722,8 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
),
|
||||
const SizedBox(width: UIConstants.spacing8),
|
||||
Text(
|
||||
'Dynamic theme applied! Colors extracted from logo.',
|
||||
AppLocalizations.of(context)!
|
||||
.themeApplied,
|
||||
style: TextStyle(
|
||||
color: Colors.green,
|
||||
fontSize: 12,
|
||||
@@ -742,7 +745,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ModernButton(
|
||||
text: 'Upload Logo',
|
||||
text: AppLocalizations.of(context)!.uploadLogo,
|
||||
type: ModernButtonType.primary,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.upload),
|
||||
@@ -757,7 +760,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ModernButton(
|
||||
text: 'Clear Logo',
|
||||
text: AppLocalizations.of(context)!.clearLogo,
|
||||
type: ModernButtonType.outline,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.delete_outline),
|
||||
@@ -788,7 +791,8 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
const SizedBox(width: UIConstants.spacing8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Theme is applied immediately! Click "Upload Logo" to save the logo permanently to the database. The dynamic theme will work even if upload fails.',
|
||||
AppLocalizations.of(context)!
|
||||
.themeImmediateNote,
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.info,
|
||||
fontSize: 12,
|
||||
@@ -806,7 +810,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ModernButton(
|
||||
text: 'Upload New Logo',
|
||||
text: AppLocalizations.of(context)!.uploadNewLogo,
|
||||
type: ModernButtonType.primary,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.upload),
|
||||
@@ -821,7 +825,8 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ModernButton(
|
||||
text: 'Remove Logo',
|
||||
text:
|
||||
AppLocalizations.of(context)!.removeLogo,
|
||||
type: ModernButtonType.danger,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.delete_outline),
|
||||
@@ -852,7 +857,8 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
const SizedBox(width: UIConstants.spacing8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Company logo is already uploaded and saved in the system. You can upload a new one or remove the existing logo.',
|
||||
AppLocalizations.of(context)!
|
||||
.logoAlreadyUploaded,
|
||||
style: TextStyle(
|
||||
color: AppColorScheme.success,
|
||||
fontSize: 12,
|
||||
@@ -913,7 +919,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Enable Manual Override',
|
||||
AppLocalizations.of(context)!.manualOverride,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
color: cs.onSurface,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -938,7 +944,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing12),
|
||||
_buildColorRow(
|
||||
label: 'Primary',
|
||||
label: AppLocalizations.of(context)!.colorPrimary,
|
||||
color: effectivePrimary,
|
||||
onPick: () async {
|
||||
final picked = await _pickColor(context, effectivePrimary);
|
||||
@@ -949,7 +955,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing12),
|
||||
_buildColorRow(
|
||||
label: 'Secondary',
|
||||
label: AppLocalizations.of(context)!.colorSecondary,
|
||||
color: effectiveSecondary,
|
||||
onPick: () async {
|
||||
final picked =
|
||||
@@ -961,7 +967,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing12),
|
||||
_buildColorRow(
|
||||
label: 'Tertiary',
|
||||
label: AppLocalizations.of(context)!.colorTertiary,
|
||||
color: effectiveTertiary,
|
||||
onPick: () async {
|
||||
final picked = await _pickColor(context, effectiveTertiary);
|
||||
@@ -975,7 +981,8 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
children: [
|
||||
Expanded(
|
||||
child: ModernButton(
|
||||
text: 'Reset to Logo Colors',
|
||||
text: AppLocalizations.of(context)!
|
||||
.resetLogoColors,
|
||||
type: ModernButtonType.outline,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.refresh),
|
||||
@@ -987,7 +994,8 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
const SizedBox(width: UIConstants.spacing12),
|
||||
Expanded(
|
||||
child: ModernButton(
|
||||
text: 'Reset to Default',
|
||||
text: AppLocalizations.of(context)!
|
||||
.resetDefault,
|
||||
type: ModernButtonType.danger,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.settings_backup_restore),
|
||||
@@ -1041,7 +1049,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
),
|
||||
),
|
||||
ModernButton(
|
||||
text: 'Edit',
|
||||
text: AppLocalizations.of(context)!.edit,
|
||||
type: ModernButtonType.text,
|
||||
size: ModernButtonSize.small,
|
||||
onPressed: () async {
|
||||
@@ -1073,7 +1081,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Pick a color'),
|
||||
title: Text(AppLocalizations.of(context)!.pickColor),
|
||||
content: SizedBox(
|
||||
width: 320,
|
||||
child: GridView.builder(
|
||||
@@ -1105,7 +1113,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(AppLocalizations.of(context)!.cancel),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -1156,7 +1164,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'User Registration',
|
||||
AppLocalizations.of(context)!.userRegistration,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.w600,
|
||||
@@ -1164,7 +1172,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
),
|
||||
const SizedBox(height: UIConstants.spacing4),
|
||||
Text(
|
||||
'Allow new users to register accounts',
|
||||
AppLocalizations.of(context)!.allowUserRegistration,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
@@ -1194,7 +1202,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: ModernButton(
|
||||
text: 'Save Configuration',
|
||||
text: AppLocalizations.of(context)!.saveConfiguration,
|
||||
type: ModernButtonType.primary,
|
||||
size: ModernButtonSize.large,
|
||||
icon: Icon(Icons.save),
|
||||
@@ -1266,16 +1274,18 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
_buildDrawerItem(
|
||||
context, theme, colorScheme, Icons.home, 'Home', () {
|
||||
context, theme, colorScheme, Icons.home,
|
||||
AppLocalizations.of(context)!.drawerHome, () {
|
||||
Navigator.of(context).pushReplacementNamed('/');
|
||||
}),
|
||||
_buildDrawerItem(context, theme, colorScheme, Icons.settings,
|
||||
'System Parameters', () {
|
||||
AppLocalizations.of(context)!.systemParameters, () {
|
||||
Navigator.of(context)
|
||||
.pushReplacementNamed('/system_parameters');
|
||||
}, isSelected: true),
|
||||
_buildDrawerItem(
|
||||
context, theme, colorScheme, Icons.people, 'Users', () {
|
||||
context, theme, colorScheme, Icons.people,
|
||||
AppLocalizations.of(context)!.drawerUsers, () {
|
||||
Navigator.of(context).pushReplacementNamed('/users');
|
||||
}),
|
||||
_buildDrawerItem(
|
||||
@@ -1283,41 +1293,49 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
Navigator.of(context).pushReplacementNamed('/roles');
|
||||
}),
|
||||
_buildDrawerItem(
|
||||
context, theme, colorScheme, Icons.business, 'Departments',
|
||||
context, theme, colorScheme, Icons.business,
|
||||
AppLocalizations.of(context)!.drawerDepartments,
|
||||
() {
|
||||
Navigator.of(context).pushReplacementNamed('/departments');
|
||||
}),
|
||||
_buildDrawerItem(
|
||||
context, theme, colorScheme, Icons.work, 'Positions', () {
|
||||
context, theme, colorScheme, Icons.work,
|
||||
AppLocalizations.of(context)!.drawerPositions, () {
|
||||
Navigator.of(context).pushReplacementNamed('/positions');
|
||||
}),
|
||||
_buildDrawerItem(context, theme, colorScheme,
|
||||
Icons.monetization_on, 'Charges', () {
|
||||
Icons.monetization_on,
|
||||
AppLocalizations.of(context)!.drawerCharges, () {
|
||||
Navigator.of(context).pushReplacementNamed('/charges');
|
||||
}),
|
||||
_buildDrawerItem(
|
||||
context, theme, colorScheme, Icons.calendar_today, 'Weeks',
|
||||
context, theme, colorScheme, Icons.calendar_today,
|
||||
AppLocalizations.of(context)!.drawerWeeks,
|
||||
() {
|
||||
Navigator.of(context).pushReplacementNamed('/weeks');
|
||||
}),
|
||||
_buildDrawerItem(
|
||||
context, theme, colorScheme, Icons.schedule, 'Shifts', () {
|
||||
context, theme, colorScheme, Icons.schedule,
|
||||
AppLocalizations.of(context)!.drawerShifts, () {
|
||||
Navigator.of(context).pushReplacementNamed('/shifts');
|
||||
}),
|
||||
_buildDrawerItem(
|
||||
context, theme, colorScheme, Icons.payment, 'Billing', () {
|
||||
context, theme, colorScheme, Icons.payment,
|
||||
AppLocalizations.of(context)!.drawerBilling, () {
|
||||
Navigator.of(context).pushReplacementNamed('/billing');
|
||||
}),
|
||||
_buildDrawerItem(context, theme, colorScheme, Icons.swap_horiz,
|
||||
'EDI Settings', () {
|
||||
AppLocalizations.of(context)!.drawerEdi, () {
|
||||
Navigator.of(context).pushReplacementNamed('/edi_settings');
|
||||
}),
|
||||
_buildDrawerItem(context, theme, colorScheme,
|
||||
Icons.business_center, 'Company', () {
|
||||
Icons.business_center,
|
||||
AppLocalizations.of(context)!.drawerCompany, () {
|
||||
Navigator.of(context).pushReplacementNamed('/company');
|
||||
}),
|
||||
_buildDrawerItem(
|
||||
context, theme, colorScheme, Icons.image, 'Logo', () {
|
||||
context, theme, colorScheme, Icons.image,
|
||||
AppLocalizations.of(context)!.drawerLogo, () {
|
||||
Navigator.of(context).pushReplacementNamed('/logo');
|
||||
}),
|
||||
],
|
||||
@@ -1328,7 +1346,7 @@ class _SystemParametersViewState extends State<SystemParametersView>
|
||||
Container(
|
||||
padding: const EdgeInsets.all(UIConstants.spacing24),
|
||||
child: ModernButton(
|
||||
text: 'Logout',
|
||||
text: AppLocalizations.of(context)!.logoutAction,
|
||||
type: ModernButtonType.danger,
|
||||
size: ModernButtonSize.medium,
|
||||
icon: Icon(Icons.logout),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:base_project/utils/image_constant.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
@@ -27,16 +28,16 @@ class ShowSnackAlert {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (color1 == Colors.red.shade400)
|
||||
const Text(
|
||||
'Oh Snap!',
|
||||
Text(
|
||||
AppLocalizations.of(context)!.ohSnap,
|
||||
style: TextStyle(fontSize: 18, color: Colors.white),
|
||||
),
|
||||
if (color1 == Colors.orange.shade400)
|
||||
const Text('Alert',
|
||||
Text(AppLocalizations.of(context)!.alertTitle,
|
||||
style:
|
||||
TextStyle(fontSize: 18, color: Colors.white)),
|
||||
if (color1 == Colors.green.shade600)
|
||||
const Text('Success',
|
||||
Text(AppLocalizations.of(context)!.successTitle,
|
||||
style:
|
||||
TextStyle(fontSize: 18, color: Colors.white)),
|
||||
Text(
|
||||
|
||||
+16
-11
@@ -446,6 +446,11 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -692,10 +697,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
|
||||
sha256: "1ca20c894b1717686a2319b8548763d812bc0aabdac580420a44c5178c57a867"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.20.2"
|
||||
version: "0.20.3"
|
||||
intl_phone_number_input:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -844,10 +849,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
|
||||
sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.18"
|
||||
version: "0.12.20"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -860,10 +865,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||
sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.0"
|
||||
version: "1.19.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1353,10 +1358,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
|
||||
sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.9"
|
||||
version: "0.7.12"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1473,10 +1478,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||
sha256: "92b9910f66ed1057fd4da7b040ae7c74cafacf885bdc81be496928d5049b032d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
version: "2.4.3"
|
||||
video_player:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1590,5 +1595,5 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
dart: ">=3.11.0-0 <4.0.0"
|
||||
flutter: ">=3.35.0"
|
||||
|
||||
@@ -30,6 +30,8 @@ environment:
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
another_flushbar: ^1.12.30
|
||||
cupertino_icons: ^1.0.8
|
||||
path_provider: ^2.1.5
|
||||
@@ -100,6 +102,7 @@ dev_dependencies:
|
||||
|
||||
# The following section is specific to Flutter packages.
|
||||
flutter:
|
||||
generate: true
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
@@ -110,6 +113,7 @@ flutter:
|
||||
- assets/
|
||||
- assets/images/
|
||||
- assets/icon/
|
||||
- assets/translations_dynamic/
|
||||
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:base_project/l10n/app_localizations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
test('English and Hindi catalogs expose the same essential messages', () {
|
||||
final english = AppLocalizations(const Locale('en'));
|
||||
final hindi = AppLocalizations(const Locale('hi'));
|
||||
|
||||
expect(english.searchEntity('student'), 'Search student...');
|
||||
expect(hindi.searchEntity('छात्र'), 'छात्र खोजें...');
|
||||
expect(english.entityRequired('Email'), 'Email is required');
|
||||
expect(hindi.entityRequired('ईमेल'), 'ईमेल आवश्यक है');
|
||||
});
|
||||
|
||||
test('only configured locales are supported', () {
|
||||
expect(AppLocalizations.supportedLocales, contains(const Locale('en')));
|
||||
expect(AppLocalizations.supportedLocales, contains(const Locale('hi')));
|
||||
});
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:base_project/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user