Merge branch 'dev' into 493-implement-rapid-order-creation-voice-text-in-client-mobile-app
This commit is contained in:
5
Makefile
5
Makefile
@@ -66,7 +66,8 @@ help:
|
|||||||
@echo " make dataconnect-deploy [ENV=dev] Deploy Data Connect schemas (dev/staging)"
|
@echo " make dataconnect-deploy [ENV=dev] Deploy Data Connect schemas (dev/staging)"
|
||||||
@echo " make dataconnect-sql-migrate [ENV=dev] Apply pending SQL migrations"
|
@echo " make dataconnect-sql-migrate [ENV=dev] Apply pending SQL migrations"
|
||||||
@echo " make dataconnect-generate-sdk [ENV=dev] Regenerate Data Connect client SDK"
|
@echo " make dataconnect-generate-sdk [ENV=dev] Regenerate Data Connect client SDK"
|
||||||
@echo " make dataconnect-sync [ENV=dev] Full sync: deploy + migrate + generate SDK"
|
@echo " make dataconnect-sync [ENV=dev] Fast sync: deploy connector + generate SDK"
|
||||||
|
@echo " make dataconnect-sync-full [ENV=dev] Full sync: deploy + migrate + generate SDK"
|
||||||
@echo " make dataconnect-seed [ENV=dev] Seed database with test data"
|
@echo " make dataconnect-seed [ENV=dev] Seed database with test data"
|
||||||
@echo " make dataconnect-clean [ENV=dev] Delete all data from Data Connect"
|
@echo " make dataconnect-clean [ENV=dev] Delete all data from Data Connect"
|
||||||
@echo " make dataconnect-test [ENV=dev] Test Data Connect deployment (dry-run)"
|
@echo " make dataconnect-test [ENV=dev] Test Data Connect deployment (dry-run)"
|
||||||
@@ -101,6 +102,6 @@ help:
|
|||||||
@echo ""
|
@echo ""
|
||||||
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
@echo " 💡 Tip: Run 'make mobile-install' first for mobile development"
|
@echo " 💡 Tip: Run 'make mobile-install' first for mobile development"
|
||||||
@echo " 💡 Tip: Use 'make dataconnect-sync' after schema changes"
|
@echo " 💡 Tip: Use 'make dataconnect-sync-full' after schema changes"
|
||||||
@echo " 💡 Tip: Default ENV=dev, use ENV=staging for staging environment"
|
@echo " 💡 Tip: Default ENV=dev, use ENV=staging for staging environment"
|
||||||
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
@echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
|||||||
@@ -36,10 +36,10 @@
|
|||||||
@import image_picker_ios;
|
@import image_picker_ios;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __has_include(<record_darwin/RecordPlugin.h>)
|
#if __has_include(<record_ios/RecordIosPlugin.h>)
|
||||||
#import <record_darwin/RecordPlugin.h>
|
#import <record_ios/RecordIosPlugin.h>
|
||||||
#else
|
#else
|
||||||
@import record_darwin;
|
@import record_ios;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __has_include(<shared_preferences_foundation/SharedPreferencesPlugin.h>)
|
#if __has_include(<shared_preferences_foundation/SharedPreferencesPlugin.h>)
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
[FLTFirebaseAuthPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseAuthPlugin"]];
|
[FLTFirebaseAuthPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseAuthPlugin"]];
|
||||||
[FLTFirebaseCorePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseCorePlugin"]];
|
[FLTFirebaseCorePlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTFirebaseCorePlugin"]];
|
||||||
[FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]];
|
[FLTImagePickerPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTImagePickerPlugin"]];
|
||||||
[RecordPlugin registerWithRegistrar:[registry registrarForPlugin:@"RecordPlugin"]];
|
[RecordIosPlugin registerWithRegistrar:[registry registrarForPlugin:@"RecordIosPlugin"]];
|
||||||
[SharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"SharedPreferencesPlugin"]];
|
[SharedPreferencesPlugin registerWithRegistrar:[registry registrarForPlugin:@"SharedPreferencesPlugin"]];
|
||||||
[URLLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"URLLauncherPlugin"]];
|
[URLLauncherPlugin registerWithRegistrar:[registry registrarForPlugin:@"URLLauncherPlugin"]];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import file_selector_macos
|
|||||||
import firebase_app_check
|
import firebase_app_check
|
||||||
import firebase_auth
|
import firebase_auth
|
||||||
import firebase_core
|
import firebase_core
|
||||||
import record_darwin
|
import record_macos
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin"))
|
FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin"))
|
||||||
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
|
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
|
||||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||||
RecordPlugin.register(with: registry.registrar(forPlugin: "RecordPlugin"))
|
RecordMacOsPlugin.register(with: registry.registrar(forPlugin: "RecordMacOsPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ extension StaffNavigator on IModularNavigator {
|
|||||||
///
|
///
|
||||||
/// Manage personal information, documents, and preferences.
|
/// Manage personal information, documents, and preferences.
|
||||||
void toProfile() {
|
void toProfile() {
|
||||||
pushNamedAndRemoveUntil(StaffPaths.profile, (_) => false);
|
navigate(StaffPaths.profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
@@ -189,7 +189,7 @@ extension StaffNavigator on IModularNavigator {
|
|||||||
///
|
///
|
||||||
/// Record previous work experience and qualifications.
|
/// Record previous work experience and qualifications.
|
||||||
void toExperience() {
|
void toExperience() {
|
||||||
pushNamed(StaffPaths.experience);
|
navigate(StaffPaths.experience);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes the attire preferences page.
|
/// Pushes the attire preferences page.
|
||||||
|
|||||||
@@ -27,4 +27,3 @@ dependencies:
|
|||||||
file_picker: ^8.1.7
|
file_picker: ^8.1.7
|
||||||
record: ^6.2.0
|
record: ^6.2.0
|
||||||
firebase_auth: ^6.1.4
|
firebase_auth: ^6.1.4
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import 'domain/usecases/create_permanent_order_usecase.dart';
|
|||||||
import 'domain/usecases/create_recurring_order_usecase.dart';
|
import 'domain/usecases/create_recurring_order_usecase.dart';
|
||||||
import 'domain/usecases/create_rapid_order_usecase.dart';
|
import 'domain/usecases/create_rapid_order_usecase.dart';
|
||||||
import 'domain/usecases/get_order_details_for_reorder_usecase.dart';
|
import 'domain/usecases/get_order_details_for_reorder_usecase.dart';
|
||||||
|
import 'domain/usecases/parse_rapid_order_usecase.dart';
|
||||||
import 'domain/usecases/transcribe_rapid_order_usecase.dart';
|
import 'domain/usecases/transcribe_rapid_order_usecase.dart';
|
||||||
import 'presentation/blocs/index.dart';
|
import 'presentation/blocs/index.dart';
|
||||||
import 'presentation/pages/create_order_page.dart';
|
import 'presentation/pages/create_order_page.dart';
|
||||||
@@ -24,7 +25,7 @@ import 'presentation/pages/recurring_order_page.dart';
|
|||||||
/// presentation layer BLoCs.
|
/// presentation layer BLoCs.
|
||||||
class ClientCreateOrderModule extends Module {
|
class ClientCreateOrderModule extends Module {
|
||||||
@override
|
@override
|
||||||
List<Module> get imports => <Module>[DataConnectModule(), CoreModule()];
|
List<Module> get imports => <Module>[DataConnectModule()];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void binds(Injector i) {
|
void binds(Injector i) {
|
||||||
@@ -39,13 +40,14 @@ class ClientCreateOrderModule extends Module {
|
|||||||
i.addLazySingleton(CreateRecurringOrderUseCase.new);
|
i.addLazySingleton(CreateRecurringOrderUseCase.new);
|
||||||
i.addLazySingleton(CreateRapidOrderUseCase.new);
|
i.addLazySingleton(CreateRapidOrderUseCase.new);
|
||||||
i.addLazySingleton(TranscribeRapidOrderUseCase.new);
|
i.addLazySingleton(TranscribeRapidOrderUseCase.new);
|
||||||
|
i.addLazySingleton(ParseRapidOrderTextToOrderUseCase.new);
|
||||||
i.addLazySingleton(GetOrderDetailsForReorderUseCase.new);
|
i.addLazySingleton(GetOrderDetailsForReorderUseCase.new);
|
||||||
|
|
||||||
// BLoCs
|
// BLoCs
|
||||||
i.add<RapidOrderBloc>(
|
i.add<RapidOrderBloc>(
|
||||||
(Injector i) => RapidOrderBloc(
|
(Injector i) => RapidOrderBloc(
|
||||||
i.get<CreateRapidOrderUseCase>(),
|
|
||||||
i.get<TranscribeRapidOrderUseCase>(),
|
i.get<TranscribeRapidOrderUseCase>(),
|
||||||
|
i.get<ParseRapidOrderTextToOrderUseCase>(),
|
||||||
i.get<AudioRecorderService>(),
|
i.get<AudioRecorderService>(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:krow_core/core.dart';
|
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||||
import 'package:krow_domain/krow_domain.dart' as domain;
|
import 'package:krow_domain/krow_domain.dart' as domain;
|
||||||
import '../../domain/repositories/client_create_order_repository_interface.dart';
|
import '../../domain/repositories/client_create_order_repository_interface.dart';
|
||||||
@@ -14,14 +13,10 @@ import '../../domain/repositories/client_create_order_repository_interface.dart'
|
|||||||
/// on delegation and data mapping, without business logic.
|
/// on delegation and data mapping, without business logic.
|
||||||
class ClientCreateOrderRepositoryImpl
|
class ClientCreateOrderRepositoryImpl
|
||||||
implements ClientCreateOrderRepositoryInterface {
|
implements ClientCreateOrderRepositoryInterface {
|
||||||
ClientCreateOrderRepositoryImpl({
|
ClientCreateOrderRepositoryImpl({required dc.DataConnectService service})
|
||||||
required dc.DataConnectService service,
|
: _service = service;
|
||||||
required RapidOrderService rapidOrderService,
|
|
||||||
}) : _service = service,
|
|
||||||
_rapidOrderService = rapidOrderService;
|
|
||||||
|
|
||||||
final dc.DataConnectService _service;
|
final dc.DataConnectService _service;
|
||||||
final RapidOrderService _rapidOrderService;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> createOneTimeOrder(domain.OneTimeOrder order) async {
|
Future<void> createOneTimeOrder(domain.OneTimeOrder order) async {
|
||||||
@@ -372,6 +367,44 @@ class ClientCreateOrderRepositoryImpl
|
|||||||
throw UnimplementedError('Rapid order IA is not connected yet.');
|
throw UnimplementedError('Rapid order IA is not connected yet.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<domain.OneTimeOrder> parseRapidOrder(String text) async {
|
||||||
|
final RapidOrderParseResponse response = await _rapidOrderService.parseText(
|
||||||
|
text: text,
|
||||||
|
);
|
||||||
|
final RapidOrderParsedData data = response.parsed;
|
||||||
|
|
||||||
|
final DateTime startAt =
|
||||||
|
DateTime.tryParse(data.startAt ?? '') ?? DateTime.now();
|
||||||
|
final DateTime endAt =
|
||||||
|
DateTime.tryParse(data.endAt ?? '') ??
|
||||||
|
startAt.add(const Duration(hours: 8));
|
||||||
|
|
||||||
|
final String startTimeStr = DateFormat('hh:mm a').format(startAt);
|
||||||
|
final String endTimeStr = DateFormat('hh:mm a').format(endAt);
|
||||||
|
|
||||||
|
return domain.OneTimeOrder(
|
||||||
|
date: startAt,
|
||||||
|
location: data.locationHint ?? '',
|
||||||
|
eventName: data.notes ?? '',
|
||||||
|
hub: data.locationHint != null
|
||||||
|
? domain.OneTimeOrderHubDetails(
|
||||||
|
id: '',
|
||||||
|
name: data.locationHint!,
|
||||||
|
address: '',
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
positions: data.positions.map((RapidOrderPosition p) {
|
||||||
|
return domain.OneTimeOrderPosition(
|
||||||
|
role: p.role,
|
||||||
|
count: p.count,
|
||||||
|
startTime: startTimeStr,
|
||||||
|
endTime: endTimeStr,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> transcribeRapidOrder(String audioPath) async {
|
Future<String> transcribeRapidOrder(String audioPath) async {
|
||||||
final RapidOrderTranscriptionResponse response = await _rapidOrderService
|
final RapidOrderTranscriptionResponse response = await _rapidOrderService
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ abstract interface class ClientCreateOrderRepositoryInterface {
|
|||||||
/// [audioPath] is the local path to the recorded audio file.
|
/// [audioPath] is the local path to the recorded audio file.
|
||||||
Future<String> transcribeRapidOrder(String audioPath);
|
Future<String> transcribeRapidOrder(String audioPath);
|
||||||
|
|
||||||
|
/// Parses the text description for a rapid order into a structured draft.
|
||||||
|
///
|
||||||
|
/// [text] is the text message describing the need.
|
||||||
|
Future<OneTimeOrder> parseRapidOrder(String text);
|
||||||
|
|
||||||
/// Reorders an existing staffing order with a new date.
|
/// Reorders an existing staffing order with a new date.
|
||||||
///
|
///
|
||||||
/// [previousOrderId] is the ID of the order to reorder.
|
/// [previousOrderId] is the ID of the order to reorder.
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
|
import '../repositories/client_create_order_repository_interface.dart';
|
||||||
|
|
||||||
|
/// Use case for parsing rapid order text into a structured OneTimeOrder.
|
||||||
|
class ParseRapidOrderTextToOrderUseCase {
|
||||||
|
ParseRapidOrderTextToOrderUseCase({
|
||||||
|
required ClientCreateOrderRepositoryInterface repository,
|
||||||
|
}) : _repository = repository;
|
||||||
|
|
||||||
|
final ClientCreateOrderRepositoryInterface _repository;
|
||||||
|
|
||||||
|
Future<OneTimeOrder> call(String text) async {
|
||||||
|
return _repository.parseRapidOrder(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -136,9 +136,7 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadManagersForHub(
|
Future<void> _loadManagersForHub(String hubId) async {
|
||||||
String hubId,
|
|
||||||
) async {
|
|
||||||
final List<OneTimeOrderManagerOption>? managers =
|
final List<OneTimeOrderManagerOption>? managers =
|
||||||
await handleErrorWithResult(
|
await handleErrorWithResult(
|
||||||
action: () async {
|
action: () async {
|
||||||
@@ -163,7 +161,9 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
.toList();
|
.toList();
|
||||||
},
|
},
|
||||||
onError: (_) {
|
onError: (_) {
|
||||||
add(const OneTimeOrderManagersLoaded(<OneTimeOrderManagerOption>[]));
|
add(
|
||||||
|
const OneTimeOrderManagersLoaded(<OneTimeOrderManagerOption>[]),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -172,7 +172,6 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> _onVendorsLoaded(
|
Future<void> _onVendorsLoaded(
|
||||||
OneTimeOrderVendorsLoaded event,
|
OneTimeOrderVendorsLoaded event,
|
||||||
Emitter<OneTimeOrderState> emit,
|
Emitter<OneTimeOrderState> emit,
|
||||||
@@ -216,7 +215,6 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _onHubChanged(
|
void _onHubChanged(
|
||||||
OneTimeOrderHubChanged event,
|
OneTimeOrderHubChanged event,
|
||||||
Emitter<OneTimeOrderState> emit,
|
Emitter<OneTimeOrderState> emit,
|
||||||
@@ -239,7 +237,6 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
emit(state.copyWith(managers: event.managers));
|
emit(state.copyWith(managers: event.managers));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _onEventNameChanged(
|
void _onEventNameChanged(
|
||||||
OneTimeOrderEventNameChanged event,
|
OneTimeOrderEventNameChanged event,
|
||||||
Emitter<OneTimeOrderState> emit,
|
Emitter<OneTimeOrderState> emit,
|
||||||
@@ -349,6 +346,45 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
|||||||
final DateTime? startDate = data['startDate'] as DateTime?;
|
final DateTime? startDate = data['startDate'] as DateTime?;
|
||||||
final String? orderId = data['orderId']?.toString();
|
final String? orderId = data['orderId']?.toString();
|
||||||
|
|
||||||
|
// Handle Rapid Order Draft
|
||||||
|
if (data['isRapidDraft'] == true) {
|
||||||
|
final OneTimeOrder? order = data['order'] as OneTimeOrder?;
|
||||||
|
if (order != null) {
|
||||||
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
eventName: order.eventName ?? '',
|
||||||
|
date: order.date,
|
||||||
|
positions: order.positions,
|
||||||
|
location: order.location,
|
||||||
|
isRapidDraft: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Try to match vendor if available
|
||||||
|
if (order.vendorId != null) {
|
||||||
|
final Vendor? vendor = state.vendors
|
||||||
|
.where((Vendor v) => v.id == order.vendorId)
|
||||||
|
.firstOrNull;
|
||||||
|
if (vendor != null) {
|
||||||
|
emit(state.copyWith(selectedVendor: vendor));
|
||||||
|
await _loadRolesForVendor(vendor.id, emit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to match hub if available
|
||||||
|
if (order.hub != null) {
|
||||||
|
final OneTimeOrderHubOption? hub = state.hubs
|
||||||
|
.where((OneTimeOrderHubOption h) => h.id == order.hub?.id)
|
||||||
|
.firstOrNull;
|
||||||
|
if (hub != null) {
|
||||||
|
emit(state.copyWith(selectedHub: hub));
|
||||||
|
await _loadManagersForHub(hub.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emit(state.copyWith(eventName: title, date: startDate ?? DateTime.now()));
|
emit(state.copyWith(eventName: title, date: startDate ?? DateTime.now()));
|
||||||
|
|
||||||
if (orderId == null || orderId.isEmpty) return;
|
if (orderId == null || orderId.isEmpty) return;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class OneTimeOrderState extends Equatable {
|
|||||||
this.roles = const <OneTimeOrderRoleOption>[],
|
this.roles = const <OneTimeOrderRoleOption>[],
|
||||||
this.managers = const <OneTimeOrderManagerOption>[],
|
this.managers = const <OneTimeOrderManagerOption>[],
|
||||||
this.selectedManager,
|
this.selectedManager,
|
||||||
|
this.isRapidDraft = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory OneTimeOrderState.initial() {
|
factory OneTimeOrderState.initial() {
|
||||||
@@ -47,6 +48,7 @@ class OneTimeOrderState extends Equatable {
|
|||||||
final List<OneTimeOrderRoleOption> roles;
|
final List<OneTimeOrderRoleOption> roles;
|
||||||
final List<OneTimeOrderManagerOption> managers;
|
final List<OneTimeOrderManagerOption> managers;
|
||||||
final OneTimeOrderManagerOption? selectedManager;
|
final OneTimeOrderManagerOption? selectedManager;
|
||||||
|
final bool isRapidDraft;
|
||||||
|
|
||||||
OneTimeOrderState copyWith({
|
OneTimeOrderState copyWith({
|
||||||
DateTime? date,
|
DateTime? date,
|
||||||
@@ -62,6 +64,7 @@ class OneTimeOrderState extends Equatable {
|
|||||||
List<OneTimeOrderRoleOption>? roles,
|
List<OneTimeOrderRoleOption>? roles,
|
||||||
List<OneTimeOrderManagerOption>? managers,
|
List<OneTimeOrderManagerOption>? managers,
|
||||||
OneTimeOrderManagerOption? selectedManager,
|
OneTimeOrderManagerOption? selectedManager,
|
||||||
|
bool? isRapidDraft,
|
||||||
}) {
|
}) {
|
||||||
return OneTimeOrderState(
|
return OneTimeOrderState(
|
||||||
date: date ?? this.date,
|
date: date ?? this.date,
|
||||||
@@ -77,6 +80,7 @@ class OneTimeOrderState extends Equatable {
|
|||||||
roles: roles ?? this.roles,
|
roles: roles ?? this.roles,
|
||||||
managers: managers ?? this.managers,
|
managers: managers ?? this.managers,
|
||||||
selectedManager: selectedManager ?? this.selectedManager,
|
selectedManager: selectedManager ?? this.selectedManager,
|
||||||
|
isRapidDraft: isRapidDraft ?? this.isRapidDraft,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +113,7 @@ class OneTimeOrderState extends Equatable {
|
|||||||
roles,
|
roles,
|
||||||
managers,
|
managers,
|
||||||
selectedManager,
|
selectedManager,
|
||||||
|
isRapidDraft,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,10 +176,7 @@ class OneTimeOrderRoleOption extends Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OneTimeOrderManagerOption extends Equatable {
|
class OneTimeOrderManagerOption extends Equatable {
|
||||||
const OneTimeOrderManagerOption({
|
const OneTimeOrderManagerOption({required this.id, required this.name});
|
||||||
required this.id,
|
|
||||||
required this.name,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
final String name;
|
final String name;
|
||||||
@@ -182,4 +184,3 @@ class OneTimeOrderManagerOption extends Equatable {
|
|||||||
@override
|
@override
|
||||||
List<Object?> get props => <Object?>[id, name];
|
List<Object?> get props => <Object?>[id, name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:client_create_order/src/domain/arguments/rapid_order_arguments.dart';
|
import 'package:client_create_order/src/domain/usecases/parse_rapid_order_usecase.dart';
|
||||||
import 'package:client_create_order/src/domain/usecases/create_rapid_order_usecase.dart';
|
|
||||||
import 'package:client_create_order/src/domain/usecases/transcribe_rapid_order_usecase.dart';
|
import 'package:client_create_order/src/domain/usecases/transcribe_rapid_order_usecase.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:krow_core/core.dart';
|
import 'package:krow_core/core.dart';
|
||||||
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
|
|
||||||
import 'rapid_order_event.dart';
|
import 'rapid_order_event.dart';
|
||||||
import 'rapid_order_state.dart';
|
import 'rapid_order_state.dart';
|
||||||
@@ -11,8 +11,8 @@ import 'rapid_order_state.dart';
|
|||||||
class RapidOrderBloc extends Bloc<RapidOrderEvent, RapidOrderState>
|
class RapidOrderBloc extends Bloc<RapidOrderEvent, RapidOrderState>
|
||||||
with BlocErrorHandler<RapidOrderState> {
|
with BlocErrorHandler<RapidOrderState> {
|
||||||
RapidOrderBloc(
|
RapidOrderBloc(
|
||||||
this._createRapidOrderUseCase,
|
|
||||||
this._transcribeRapidOrderUseCase,
|
this._transcribeRapidOrderUseCase,
|
||||||
|
this._parseRapidOrderUseCase,
|
||||||
this._audioRecorderService,
|
this._audioRecorderService,
|
||||||
) : super(
|
) : super(
|
||||||
const RapidOrderInitial(
|
const RapidOrderInitial(
|
||||||
@@ -28,8 +28,8 @@ class RapidOrderBloc extends Bloc<RapidOrderEvent, RapidOrderState>
|
|||||||
on<RapidOrderSubmitted>(_onSubmitted);
|
on<RapidOrderSubmitted>(_onSubmitted);
|
||||||
on<RapidOrderExampleSelected>(_onExampleSelected);
|
on<RapidOrderExampleSelected>(_onExampleSelected);
|
||||||
}
|
}
|
||||||
final CreateRapidOrderUseCase _createRapidOrderUseCase;
|
|
||||||
final TranscribeRapidOrderUseCase _transcribeRapidOrderUseCase;
|
final TranscribeRapidOrderUseCase _transcribeRapidOrderUseCase;
|
||||||
|
final ParseRapidOrderTextToOrderUseCase _parseRapidOrderUseCase;
|
||||||
final AudioRecorderService _audioRecorderService;
|
final AudioRecorderService _audioRecorderService;
|
||||||
|
|
||||||
void _onMessageChanged(
|
void _onMessageChanged(
|
||||||
@@ -47,39 +47,21 @@ class RapidOrderBloc extends Bloc<RapidOrderEvent, RapidOrderState>
|
|||||||
) async {
|
) async {
|
||||||
if (state is RapidOrderInitial) {
|
if (state is RapidOrderInitial) {
|
||||||
final RapidOrderInitial currentState = state as RapidOrderInitial;
|
final RapidOrderInitial currentState = state as RapidOrderInitial;
|
||||||
final bool alreadyListening = currentState.isListening;
|
final bool newListeningState = !currentState.isListening;
|
||||||
|
|
||||||
if (!alreadyListening) {
|
emit(currentState.copyWith(isListening: newListeningState));
|
||||||
// Start recording
|
|
||||||
await handleError(
|
|
||||||
emit: (RapidOrderState s) => emit(s),
|
|
||||||
action: () async {
|
|
||||||
await _audioRecorderService.startRecording();
|
|
||||||
emit(currentState.copyWith(isListening: true));
|
|
||||||
},
|
|
||||||
onError: (String errorKey) => RapidOrderFailure(errorKey),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Stop and transcribe
|
|
||||||
emit(currentState.copyWith(isListening: false));
|
|
||||||
|
|
||||||
await handleError(
|
// Simulate voice recognition
|
||||||
emit: (RapidOrderState s) => emit(s),
|
if (newListeningState) {
|
||||||
action: () async {
|
await Future<void>.delayed(const Duration(seconds: 2));
|
||||||
final String? path = await _audioRecorderService.stopRecording();
|
if (state is RapidOrderInitial) {
|
||||||
if (path != null) {
|
emit(
|
||||||
final String transcript = await _transcribeRapidOrderUseCase(
|
(state as RapidOrderInitial).copyWith(
|
||||||
path,
|
message: 'Need 2 servers for a banquet right now.',
|
||||||
);
|
isListening: false,
|
||||||
if (state is RapidOrderInitial) {
|
),
|
||||||
emit(
|
);
|
||||||
(state as RapidOrderInitial).copyWith(message: transcript),
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onError: (String errorKey) => RapidOrderFailure(errorKey),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,10 +78,8 @@ class RapidOrderBloc extends Bloc<RapidOrderEvent, RapidOrderState>
|
|||||||
await handleError(
|
await handleError(
|
||||||
emit: emit.call,
|
emit: emit.call,
|
||||||
action: () async {
|
action: () async {
|
||||||
await _createRapidOrderUseCase(
|
final OneTimeOrder order = await _parseRapidOrderUseCase(message);
|
||||||
RapidOrderArguments(description: message),
|
emit(RapidOrderParsed(order));
|
||||||
);
|
|
||||||
emit(const RapidOrderSuccess());
|
|
||||||
},
|
},
|
||||||
onError: (String errorKey) => RapidOrderFailure(errorKey),
|
onError: (String errorKey) => RapidOrderFailure(errorKey),
|
||||||
);
|
);
|
||||||
@@ -116,3 +96,4 @@ class RapidOrderBloc extends Bloc<RapidOrderEvent, RapidOrderState>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
|
|
||||||
abstract class RapidOrderState extends Equatable {
|
abstract class RapidOrderState extends Equatable {
|
||||||
const RapidOrderState();
|
const RapidOrderState();
|
||||||
@@ -48,3 +49,11 @@ class RapidOrderFailure extends RapidOrderState {
|
|||||||
@override
|
@override
|
||||||
List<Object?> get props => <Object?>[error];
|
List<Object?> get props => <Object?>[error];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RapidOrderParsed extends RapidOrderState {
|
||||||
|
const RapidOrderParsed(this.order);
|
||||||
|
final OneTimeOrder order;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => <Object?>[order];
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class OneTimeOrderPage extends StatelessWidget {
|
|||||||
: null,
|
: null,
|
||||||
hubManagers: state.managers.map(_mapManager).toList(),
|
hubManagers: state.managers.map(_mapManager).toList(),
|
||||||
isValid: state.isValid,
|
isValid: state.isValid,
|
||||||
|
title: state.isRapidDraft ? 'Rapid Order : Verify the order' : null,
|
||||||
onEventNameChanged: (String val) =>
|
onEventNameChanged: (String val) =>
|
||||||
bloc.add(OneTimeOrderEventNameChanged(val)),
|
bloc.add(OneTimeOrderEventNameChanged(val)),
|
||||||
onVendorChanged: (Vendor val) =>
|
onVendorChanged: (Vendor val) =>
|
||||||
|
|||||||
@@ -72,6 +72,13 @@ class _RapidOrderFormState extends State<_RapidOrderForm> {
|
|||||||
TextPosition(offset: _messageController.text.length),
|
TextPosition(offset: _messageController.text.length),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (state is RapidOrderParsed) {
|
||||||
|
Modular.to.toCreateOrderOneTime(
|
||||||
|
arguments: <String, dynamic>{
|
||||||
|
'order': state.order,
|
||||||
|
'isRapidDraft': true,
|
||||||
|
},
|
||||||
|
);
|
||||||
} else if (state is RapidOrderFailure) {
|
} else if (state is RapidOrderFailure) {
|
||||||
UiSnackbar.show(
|
UiSnackbar.show(
|
||||||
context,
|
context,
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class OneTimeOrderView extends StatelessWidget {
|
|||||||
required this.onSubmit,
|
required this.onSubmit,
|
||||||
required this.onDone,
|
required this.onDone,
|
||||||
required this.onBack,
|
required this.onBack,
|
||||||
|
this.title,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@ class OneTimeOrderView extends StatelessWidget {
|
|||||||
final List<OrderManagerUiModel> hubManagers;
|
final List<OrderManagerUiModel> hubManagers;
|
||||||
final OrderManagerUiModel? selectedHubManager;
|
final OrderManagerUiModel? selectedHubManager;
|
||||||
final bool isValid;
|
final bool isValid;
|
||||||
|
final String? title;
|
||||||
|
|
||||||
final ValueChanged<String> onEventNameChanged;
|
final ValueChanged<String> onEventNameChanged;
|
||||||
final ValueChanged<Vendor> onVendorChanged;
|
final ValueChanged<Vendor> onVendorChanged;
|
||||||
@@ -61,7 +63,8 @@ class OneTimeOrderView extends StatelessWidget {
|
|||||||
final ValueChanged<OrderHubUiModel> onHubChanged;
|
final ValueChanged<OrderHubUiModel> onHubChanged;
|
||||||
final ValueChanged<OrderManagerUiModel?> onHubManagerChanged;
|
final ValueChanged<OrderManagerUiModel?> onHubManagerChanged;
|
||||||
final VoidCallback onPositionAdded;
|
final VoidCallback onPositionAdded;
|
||||||
final void Function(int index, OrderPositionUiModel position) onPositionUpdated;
|
final void Function(int index, OrderPositionUiModel position)
|
||||||
|
onPositionUpdated;
|
||||||
final void Function(int index) onPositionRemoved;
|
final void Function(int index) onPositionRemoved;
|
||||||
final VoidCallback onSubmit;
|
final VoidCallback onSubmit;
|
||||||
final VoidCallback onDone;
|
final VoidCallback onDone;
|
||||||
@@ -98,7 +101,7 @@ class OneTimeOrderView extends StatelessWidget {
|
|||||||
body: Column(
|
body: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
OneTimeOrderHeader(
|
OneTimeOrderHeader(
|
||||||
title: labels.title,
|
title: title ?? labels.title,
|
||||||
subtitle: labels.subtitle,
|
subtitle: labels.subtitle,
|
||||||
onBack: onBack,
|
onBack: onBack,
|
||||||
),
|
),
|
||||||
@@ -136,7 +139,7 @@ class OneTimeOrderView extends StatelessWidget {
|
|||||||
body: Column(
|
body: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
OneTimeOrderHeader(
|
OneTimeOrderHeader(
|
||||||
title: labels.title,
|
title: title ?? labels.title,
|
||||||
subtitle: labels.subtitle,
|
subtitle: labels.subtitle,
|
||||||
onBack: onBack,
|
onBack: onBack,
|
||||||
),
|
),
|
||||||
@@ -220,7 +223,8 @@ class _OneTimeOrderForm extends StatelessWidget {
|
|||||||
final ValueChanged<OrderHubUiModel> onHubChanged;
|
final ValueChanged<OrderHubUiModel> onHubChanged;
|
||||||
final ValueChanged<OrderManagerUiModel?> onHubManagerChanged;
|
final ValueChanged<OrderManagerUiModel?> onHubManagerChanged;
|
||||||
final VoidCallback onPositionAdded;
|
final VoidCallback onPositionAdded;
|
||||||
final void Function(int index, OrderPositionUiModel position) onPositionUpdated;
|
final void Function(int index, OrderPositionUiModel position)
|
||||||
|
onPositionUpdated;
|
||||||
final void Function(int index) onPositionRemoved;
|
final void Function(int index) onPositionRemoved;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -317,10 +321,7 @@ class _OneTimeOrderForm extends StatelessWidget {
|
|||||||
items: hubs.map((OrderHubUiModel hub) {
|
items: hubs.map((OrderHubUiModel hub) {
|
||||||
return DropdownMenuItem<OrderHubUiModel>(
|
return DropdownMenuItem<OrderHubUiModel>(
|
||||||
value: hub,
|
value: hub,
|
||||||
child: Text(
|
child: Text(hub.name, style: UiTypography.body2m.textPrimary),
|
||||||
hub.name,
|
|
||||||
style: UiTypography.body2m.textPrimary,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import file_selector_macos
|
|||||||
import firebase_app_check
|
import firebase_app_check
|
||||||
import firebase_auth
|
import firebase_auth
|
||||||
import firebase_core
|
import firebase_core
|
||||||
import record_darwin
|
import record_macos
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
@@ -19,6 +19,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin"))
|
FLTFirebaseAppCheckPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAppCheckPlugin"))
|
||||||
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
|
FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin"))
|
||||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||||
RecordPlugin.register(with: registry.registrar(forPlugin: "RecordPlugin"))
|
RecordMacOsPlugin.register(with: registry.registrar(forPlugin: "RecordMacOsPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,8 @@ client.createInvoice();
|
|||||||
| dataconnect-deploy | Deploy schemas |
|
| dataconnect-deploy | Deploy schemas |
|
||||||
| dataconnect-sql-migrate | Apply DB migrations |
|
| dataconnect-sql-migrate | Apply DB migrations |
|
||||||
| dataconnect-generate-sdk | Generate SDK |
|
| dataconnect-generate-sdk | Generate SDK |
|
||||||
| dataconnect-sync | Full backend update |
|
| dataconnect-sync | Fast connector + SDK sync |
|
||||||
|
| dataconnect-sync-full | Full backend update |
|
||||||
| dataconnect-test | Test without breaking |
|
| dataconnect-test | Test without breaking |
|
||||||
| dataconnect-seed | Insert seed data |
|
| dataconnect-seed | Insert seed data |
|
||||||
| dataconnect-bootstrap-db | Create Cloud SQL |
|
| dataconnect-bootstrap-db | Create Cloud SQL |
|
||||||
@@ -195,7 +196,7 @@ client.createInvoice();
|
|||||||
|
|
||||||
## 9. Correct Backend Workflow
|
## 9. Correct Backend Workflow
|
||||||
|
|
||||||
### Production Flow
|
### Query/Connector Flow
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make dataconnect-sync
|
make dataconnect-sync
|
||||||
@@ -203,9 +204,22 @@ make dataconnect-sync
|
|||||||
|
|
||||||
Steps:
|
Steps:
|
||||||
|
|
||||||
1. Deploy schema
|
1. Deploy connector
|
||||||
2. Run SQL migrations
|
2. Generate SDK
|
||||||
3. Generate SDK
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Full Schema Flow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make dataconnect-sync-full
|
||||||
|
```
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
|
||||||
|
1. Deploy schema
|
||||||
|
2. Run SQL migrations
|
||||||
|
3. Generate SDK
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,8 @@ client.createInvoice();
|
|||||||
| dataconnect-deploy | Deploy schemas |
|
| dataconnect-deploy | Deploy schemas |
|
||||||
| dataconnect-sql-migrate | Apply DB migrations |
|
| dataconnect-sql-migrate | Apply DB migrations |
|
||||||
| dataconnect-generate-sdk | Generate SDK |
|
| dataconnect-generate-sdk | Generate SDK |
|
||||||
| dataconnect-sync | Full backend update |
|
| dataconnect-sync | Fast connector + SDK sync |
|
||||||
|
| dataconnect-sync-full | Full backend update |
|
||||||
| dataconnect-test | Test without breaking |
|
| dataconnect-test | Test without breaking |
|
||||||
| dataconnect-seed | Insert seed data |
|
| dataconnect-seed | Insert seed data |
|
||||||
| dataconnect-bootstrap-db | Create Cloud SQL |
|
| dataconnect-bootstrap-db | Create Cloud SQL |
|
||||||
@@ -195,7 +196,7 @@ client.createInvoice();
|
|||||||
|
|
||||||
## 9. Correct Backend Workflow
|
## 9. Correct Backend Workflow
|
||||||
|
|
||||||
### Production Flow
|
### Query/Connector Flow
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make dataconnect-sync
|
make dataconnect-sync
|
||||||
@@ -203,9 +204,22 @@ make dataconnect-sync
|
|||||||
|
|
||||||
Steps:
|
Steps:
|
||||||
|
|
||||||
1. Deploy schema
|
1. Deploy connector
|
||||||
2. Run SQL migrations
|
2. Generate SDK
|
||||||
3. Generate SDK
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Full Schema Flow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make dataconnect-sync-full
|
||||||
|
```
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
|
||||||
|
1. Deploy schema
|
||||||
|
2. Run SQL migrations
|
||||||
|
3. Generate SDK
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
# Usage examples:
|
# Usage examples:
|
||||||
# make dataconnect-sync DC_ENV=dev
|
# make dataconnect-sync DC_ENV=dev
|
||||||
|
# make dataconnect-sync-full DC_ENV=dev
|
||||||
# make dataconnect-seed DC_ENV=validation
|
# make dataconnect-seed DC_ENV=validation
|
||||||
# make dataconnect-clean DC_ENV=validation
|
# make dataconnect-clean DC_ENV=validation
|
||||||
# make dataconnect-generate-sdk DC_ENV=dev
|
# make dataconnect-generate-sdk DC_ENV=dev
|
||||||
#
|
#
|
||||||
DC_ENV ?= dev
|
DC_ENV ?= dev
|
||||||
|
DC_LOCATION ?= us-central1
|
||||||
|
DC_CONNECTOR_ID ?= example
|
||||||
|
|
||||||
DC_SERVICE_DEV := krow-workforce-db
|
DC_SERVICE_DEV := krow-workforce-db
|
||||||
DC_SERVICE_VALIDATION := krow-workforce-db-validation
|
DC_SERVICE_VALIDATION := krow-workforce-db-validation
|
||||||
@@ -19,7 +22,7 @@ else
|
|||||||
$(error Invalid DC_ENV '$(DC_ENV)'. Use DC_ENV=dev or DC_ENV=validation)
|
$(error Invalid DC_ENV '$(DC_ENV)'. Use DC_ENV=dev or DC_ENV=validation)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: dataconnect-enable-apis dataconnect-init dataconnect-deploy dataconnect-sql-migrate dataconnect-generate-sdk dataconnect-sync dataconnect-bootstrap-db check-gcloud-beta dataconnect-clean dataconnect-bootstrap-validation-db dataconnect-file dataconnect-file-validation dataconnect-file-dev dataconnect-seed dataconnect-test
|
.PHONY: dataconnect-enable-apis dataconnect-init dataconnect-deploy dataconnect-sql-migrate dataconnect-generate-sdk dataconnect-sync dataconnect-sync-full dataconnect-bootstrap-db check-gcloud-beta dataconnect-clean dataconnect-bootstrap-validation-db dataconnect-file dataconnect-file-validation dataconnect-file-dev dataconnect-seed dataconnect-test
|
||||||
|
|
||||||
#creation dataconnect file
|
#creation dataconnect file
|
||||||
dataconnect-file:
|
dataconnect-file:
|
||||||
@@ -79,15 +82,23 @@ dataconnect-generate-sdk: dataconnect-file
|
|||||||
@firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS)
|
@firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS)
|
||||||
@echo "✅ Data Connect SDK generation completed for [$(DC_ENV)]."
|
@echo "✅ Data Connect SDK generation completed for [$(DC_ENV)]."
|
||||||
|
|
||||||
# Unified backend schema update workflow (schema -> deploy -> SDK)
|
# Fast sync workflow for connector/query changes (deploy connector -> SDK)
|
||||||
dataconnect-sync: dataconnect-file
|
dataconnect-sync: dataconnect-file
|
||||||
@echo "--> [1/3] Deploying Data Connect [$(DC_SERVICE)]..."
|
@echo "--> [1/2] Deploying Data Connect connector [$(DC_SERVICE):$(DC_CONNECTOR_ID)]..."
|
||||||
@firebase deploy --only dataconnect:$(DC_SERVICE) --project=$(FIREBASE_ALIAS)
|
@firebase deploy --only dataconnect:$(DC_SERVICE):$(DC_CONNECTOR_ID) --project=$(FIREBASE_ALIAS) --force
|
||||||
|
@echo "--> [2/2] Regenerating SDK [$(DC_SERVICE)]..."
|
||||||
|
@firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS)
|
||||||
|
@echo "✅ Data Connect connector + SDK sync completed for [$(DC_ENV)]."
|
||||||
|
|
||||||
|
# Full backend schema update workflow (schema -> migrate -> SDK)
|
||||||
|
dataconnect-sync-full: dataconnect-file
|
||||||
|
@echo "--> [1/3] Deploying full Data Connect service [$(DC_SERVICE)]..."
|
||||||
|
@firebase deploy --only dataconnect:$(DC_SERVICE) --project=$(FIREBASE_ALIAS) --force
|
||||||
@echo "--> [2/3] Applying SQL migrations [$(DC_SERVICE)]..."
|
@echo "--> [2/3] Applying SQL migrations [$(DC_SERVICE)]..."
|
||||||
@firebase dataconnect:sql:migrate --project=$(FIREBASE_ALIAS)
|
@firebase dataconnect:sql:migrate --project=$(FIREBASE_ALIAS) --service $(DC_SERVICE) --location $(DC_LOCATION) --force
|
||||||
@echo "--> [3/3] Regenerating SDK [$(DC_SERVICE)]..."
|
@echo "--> [3/3] Regenerating SDK [$(DC_SERVICE)]..."
|
||||||
@firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS)
|
@firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS)
|
||||||
@echo "✅ Data Connect SQL, deploy, and SDK generation [$(ENV)]."
|
@echo "✅ Data Connect full schema sync completed for [$(DC_ENV)]."
|
||||||
|
|
||||||
# Execute seed in Firebase Data Connect
|
# Execute seed in Firebase Data Connect
|
||||||
dataconnect-seed: dataconnect-file
|
dataconnect-seed: dataconnect-file
|
||||||
@@ -268,4 +279,4 @@ dataconnect-bootstrap-validation-database: dataconnect-file-validation
|
|||||||
@echo "⚠️ Generating Data Connect SDK ($(DC_SERVICE))..."
|
@echo "⚠️ Generating Data Connect SDK ($(DC_SERVICE))..."
|
||||||
@firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS)
|
@firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS)
|
||||||
|
|
||||||
@echo "🎉 Validation Cloud SQL + Data Connect bootstrap completed successfully!"
|
@echo "🎉 Validation Cloud SQL + Data Connect bootstrap completed successfully!"
|
||||||
|
|||||||
Reference in New Issue
Block a user