chore(branding): rebrand FixMate to CityPulse across codebase

- Update product name in README, backend docs, and design tokens
- Rename Flutter root widget to CityPulseApp and update tests
- Update dashboard brand strings and HTML title
- Refresh i18n strings (en/ms) and welcome taglines
- Adjust backend API title/description and root message
- Minor formatting in ApiService comments; no logic changes
- Update Android/iOS manifest comments and pubspec description

No API endpoints or response schema changes.
This commit is contained in:
2025-09-27 11:15:15 +08:00
parent 6924455d35
commit ed63a0cbc8
20 changed files with 59 additions and 44 deletions

View File

@@ -10,8 +10,8 @@ import 'screens/settings/settings_screen.dart';
import 'theme/themes.dart';
import 'package:shared_preferences/shared_preferences.dart';
class FixMateApp extends StatelessWidget {
const FixMateApp({super.key});
class CityPulseApp extends StatelessWidget {
const CityPulseApp({super.key});
@override
Widget build(BuildContext context) {

View File

@@ -4,21 +4,21 @@ import 'app.dart';
import 'l10n/i18n.dart';
import 'l10n/locale_provider.dart';
export 'app.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize locale provider
final localeProvider = LocaleProvider();
await localeProvider.init();
// Initialize i18n with the current locale
await I18n.init(localeProvider.locale);
runApp(
ChangeNotifierProvider.value(
value: localeProvider,
child: const FixMateApp(),
child: const CityPulseApp(),
),
);
}

View File

@@ -5,7 +5,7 @@ import 'package:uuid/uuid.dart';
import '../models/report.dart';
import '../models/enums.dart';
/// Service for communicating with the FixMate Backend API
/// Service for communicating with the CityPulse Backend API
class ApiService {
// Configure this to match your backend URL
// Use localhost for web/desktop, network IP for mobile/emulator
@@ -77,8 +77,10 @@ class ApiService {
request.fields['latitude'] = latitude.toString();
request.fields['longitude'] = longitude.toString();
request.fields['description'] = description;
if (userName != null && userName.isNotEmpty) request.fields['user_name'] = userName;
if (address != null && address.isNotEmpty) request.fields['address'] = address;
if (userName != null && userName.isNotEmpty)
request.fields['user_name'] = userName;
if (address != null && address.isNotEmpty)
request.fields['address'] = address;
// Add the image file
request.files.add(
@@ -162,7 +164,9 @@ class ApiService {
if (response.statusCode == 200 || response.statusCode == 204) {
return true;
} else {
print('Failed to delete ticket: ${response.statusCode} ${response.body}');
print(
'Failed to delete ticket: ${response.statusCode} ${response.body}',
);
return false;
}
} catch (e) {
@@ -190,7 +194,8 @@ class ApiService {
/// Convert API ticket response to Report model
static Report _convertApiTicketToReport(Map<String, dynamic> data) {
final id = (data['id'] ?? data['ticket_id'] ?? '').toString();
final imageUrl = (data['image_url'] as String?) ??
final imageUrl =
(data['image_url'] as String?) ??
(data['image_path'] != null
? '$_uploadsUrl/${(data['image_path'] as String).split('/').last}'
: null);
@@ -207,9 +212,19 @@ class ApiService {
lat: (data['latitude'] as num?)?.toDouble() ?? 0.0,
lng: (data['longitude'] as num?)?.toDouble() ?? 0.0,
),
createdAt: (data['created_at'] ?? data['createdAt'] ?? DateTime.now().toIso8601String()) as String,
updatedAt: (data['updated_at'] ?? data['updatedAt'] ?? DateTime.now().toIso8601String()) as String,
deviceId: data['user_id'] != null ? data['user_id'].toString() : 'api-$id',
createdAt:
(data['created_at'] ??
data['createdAt'] ??
DateTime.now().toIso8601String())
as String,
updatedAt:
(data['updated_at'] ??
data['updatedAt'] ??
DateTime.now().toIso8601String())
as String,
deviceId: data['user_id'] != null
? data['user_id'].toString()
: 'api-$id',
notes: data['description'] as String?,
address: data['address'] as String?,
submittedBy: data['user_name'] as String?,

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
/// Design tokens and themes for FixMate (Civic Pro Minimal)
/// Design tokens and themes for CityPulse (Civic Pro Minimal)
class AppColors {
// Primary civic colors
static const Color civicBlue = Color(0xFF2563EB);