diff --git a/apps/mobile/packages/features/client/hubs/lib/src/presentation/pages/client_hubs_page.dart b/apps/mobile/packages/features/client/hubs/lib/src/presentation/pages/client_hubs_page.dart index aa3de3e2..85f60930 100644 --- a/apps/mobile/packages/features/client/hubs/lib/src/presentation/pages/client_hubs_page.dart +++ b/apps/mobile/packages/features/client/hubs/lib/src/presentation/pages/client_hubs_page.dart @@ -95,10 +95,10 @@ class ClientHubsPage extends StatelessWidget { ).add( ClientHubsIdentifyDialogToggled(hub: hub), ), - onDeletePressed: () => _confirmDeleteHub( - context, - hub, - ), + onDeletePressed: () => + BlocProvider.of( + context, + ).add(ClientHubsDeleteRequested(hub.id)), ), ), ], @@ -221,51 +221,4 @@ class ClientHubsPage extends StatelessWidget { ), ); } - - Future _confirmDeleteHub(BuildContext context, Hub hub) async { - final String hubName = hub.name.isEmpty ? 'this hub' : hub.name; - return showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext dialogContext) { - return AlertDialog( - title: const Text('Confirm Hub Deletion'), - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text('Are you sure you want to delete "$hubName"?'), - const SizedBox(height: UiConstants.space2), - const Text('This action cannot be undone.'), - const SizedBox(height: UiConstants.space2), - Text( - 'Note that if there are any shifts/orders assigned to this hub we shouldn\'t be able to delete the hub.', - style: UiTypography.footnote1r.copyWith( - color: UiColors.textSecondary, - ), - ), - ], - ), - actions: [ - TextButton( - onPressed: () => Modular.to.pop(), - child: const Text('Cancel'), - ), - TextButton( - onPressed: () { - BlocProvider.of( - context, - ).add(ClientHubsDeleteRequested(hub.id)); - Modular.to.pop(); - }, - style: TextButton.styleFrom( - foregroundColor: UiColors.destructive, - ), - child: const Text('Delete'), - ), - ], - ); - }, - ); - } } diff --git a/apps/mobile/packages/features/client/settings/lib/src/presentation/widgets/client_settings_page/settings_actions.dart b/apps/mobile/packages/features/client/settings/lib/src/presentation/widgets/client_settings_page/settings_actions.dart index e044d1ec..e3e99090 100644 --- a/apps/mobile/packages/features/client/settings/lib/src/presentation/widgets/client_settings_page/settings_actions.dart +++ b/apps/mobile/packages/features/client/settings/lib/src/presentation/widgets/client_settings_page/settings_actions.dart @@ -83,7 +83,7 @@ class SettingsActions extends StatelessWidget { // Cancel button UiButton.secondary( text: t.common.cancel, - onPressed: () => Modular.to.pop(), + onPressed: () => Navigator.of(dialogContext).pop(), ), ], ), diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/navigation/home_navigator.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/navigation/home_navigator.dart index cd9da6f6..9774cb07 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/navigation/home_navigator.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/navigation/home_navigator.dart @@ -31,11 +31,9 @@ extension HomeNavigator on IModularNavigator { /// Optionally provide a [tab] query param (e.g. `find`). void pushShifts({String? tab}) { if (tab == null) { - navigate('/worker-main/shifts'); + pushNamed('/worker-main/shifts'); } else { - navigate('/worker-main/shifts', arguments: { - 'initialTab': tab, - }); + pushNamed('/worker-main/shifts?tab=$tab'); } } diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/pages/worker_home_page.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/pages/worker_home_page.dart index 777cbf14..a9b3f169 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/pages/worker_home_page.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/pages/worker_home_page.dart @@ -132,7 +132,8 @@ class WorkerHomePage extends StatelessWidget { EmptyStateWidget( message: emptyI18n.no_shifts_today, actionLink: emptyI18n.find_shifts_cta, - onAction: () => Modular.to.pushShifts(tab: 'find'), + onAction: () => + Modular.to.pushShifts(tab: 'find'), ) else Column( diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_bloc.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_bloc.dart index ff8dd4fd..40ab4f4d 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_bloc.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_bloc.dart @@ -31,7 +31,6 @@ class ShiftsBloc extends Bloc { on(_onLoadShifts); on(_onLoadHistoryShifts); on(_onLoadAvailableShifts); - on(_onLoadFindFirst); on(_onLoadShiftsForRange); on(_onFilterAvailableShifts); } @@ -63,7 +62,6 @@ class ShiftsBloc extends Bloc { availableLoaded: false, historyLoading: false, historyLoaded: false, - myShiftsLoaded: true, searchQuery: '', jobType: 'all', )); @@ -84,7 +82,6 @@ class ShiftsBloc extends Bloc { try { final historyResult = await getHistoryShifts(); emit(currentState.copyWith( - myShiftsLoaded: true, historyShifts: historyResult, historyLoading: false, historyLoaded: true, @@ -116,67 +113,6 @@ class ShiftsBloc extends Bloc { } } - Future _onLoadFindFirst( - LoadFindFirstEvent event, - Emitter emit, - ) async { - if (state is! ShiftsLoaded) { - emit(const ShiftsLoaded( - myShifts: [], - pendingShifts: [], - cancelledShifts: [], - availableShifts: [], - historyShifts: [], - availableLoading: false, - availableLoaded: false, - historyLoading: false, - historyLoaded: false, - myShiftsLoaded: false, - searchQuery: '', - jobType: 'all', - )); - } - - final currentState = - state is ShiftsLoaded ? state as ShiftsLoaded : null; - if (currentState != null && currentState.availableLoaded) return; - - if (currentState != null) { - emit(currentState.copyWith(availableLoading: true)); - } - - try { - final availableResult = - await getAvailableShifts(const GetAvailableShiftsArguments()); - final loadedState = state is ShiftsLoaded - ? state as ShiftsLoaded - : const ShiftsLoaded( - myShifts: [], - pendingShifts: [], - cancelledShifts: [], - availableShifts: [], - historyShifts: [], - availableLoading: true, - availableLoaded: false, - historyLoading: false, - historyLoaded: false, - myShiftsLoaded: false, - searchQuery: '', - jobType: 'all', - ); - emit(loadedState.copyWith( - availableShifts: _filterPastShifts(availableResult), - availableLoading: false, - availableLoaded: true, - )); - } catch (_) { - if (state is ShiftsLoaded) { - final current = state as ShiftsLoaded; - emit(current.copyWith(availableLoading: false)); - } - } - } - Future _onLoadShiftsForRange( LoadShiftsForRangeEvent event, Emitter emit, @@ -188,10 +124,7 @@ class ShiftsBloc extends Bloc { if (state is ShiftsLoaded) { final currentState = state as ShiftsLoaded; - emit(currentState.copyWith( - myShifts: myShiftsResult, - myShiftsLoaded: true, - )); + emit(currentState.copyWith(myShifts: myShiftsResult)); return; } @@ -205,7 +138,6 @@ class ShiftsBloc extends Bloc { availableLoaded: false, historyLoading: false, historyLoaded: false, - myShiftsLoaded: true, searchQuery: '', jobType: 'all', )); diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_event.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_event.dart index d25866e0..7822a249 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_event.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_event.dart @@ -14,8 +14,6 @@ class LoadHistoryShiftsEvent extends ShiftsEvent {} class LoadAvailableShiftsEvent extends ShiftsEvent {} -class LoadFindFirstEvent extends ShiftsEvent {} - class LoadShiftsForRangeEvent extends ShiftsEvent { final DateTime start; final DateTime end; diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_state.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_state.dart index d32e3fba..dc670b52 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_state.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/blocs/shifts/shifts_state.dart @@ -22,7 +22,6 @@ class ShiftsLoaded extends ShiftsState { final bool availableLoaded; final bool historyLoading; final bool historyLoaded; - final bool myShiftsLoaded; final String searchQuery; final String jobType; @@ -36,7 +35,6 @@ class ShiftsLoaded extends ShiftsState { required this.availableLoaded, required this.historyLoading, required this.historyLoaded, - required this.myShiftsLoaded, required this.searchQuery, required this.jobType, }); @@ -51,7 +49,6 @@ class ShiftsLoaded extends ShiftsState { bool? availableLoaded, bool? historyLoading, bool? historyLoaded, - bool? myShiftsLoaded, String? searchQuery, String? jobType, }) { @@ -65,7 +62,6 @@ class ShiftsLoaded extends ShiftsState { availableLoaded: availableLoaded ?? this.availableLoaded, historyLoading: historyLoading ?? this.historyLoading, historyLoaded: historyLoaded ?? this.historyLoaded, - myShiftsLoaded: myShiftsLoaded ?? this.myShiftsLoaded, searchQuery: searchQuery ?? this.searchQuery, jobType: jobType ?? this.jobType, ); @@ -82,7 +78,6 @@ class ShiftsLoaded extends ShiftsState { availableLoaded, historyLoading, historyLoaded, - myShiftsLoaded, searchQuery, jobType, ]; diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shifts_page.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shifts_page.dart index 3d86039d..f42e6d65 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shifts_page.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/pages/shifts_page.dart @@ -21,7 +21,6 @@ class ShiftsPage extends StatefulWidget { class _ShiftsPageState extends State { late String _activeTab; DateTime? _selectedDate; - bool _prioritizeFind = false; final ShiftsBloc _bloc = Modular.get(); @override @@ -29,22 +28,12 @@ class _ShiftsPageState extends State { super.initState(); _activeTab = widget.initialTab ?? 'myshifts'; _selectedDate = widget.selectedDate; - print('ShiftsPage init: initialTab=$_activeTab'); - _prioritizeFind = widget.initialTab == 'find'; - if (_prioritizeFind) { - _bloc.add(LoadFindFirstEvent()); - } else { - _bloc.add(LoadShiftsEvent()); - } + _bloc.add(LoadShiftsEvent()); if (_activeTab == 'history') { - print('ShiftsPage init: loading history tab'); _bloc.add(LoadHistoryShiftsEvent()); } if (_activeTab == 'find') { - print('ShiftsPage init: entering find tab (not loaded yet)'); - if (!_prioritizeFind) { - _bloc.add(LoadAvailableShiftsEvent()); - } + _bloc.add(LoadAvailableShiftsEvent()); } } @@ -54,7 +43,6 @@ class _ShiftsPageState extends State { if (widget.initialTab != null && widget.initialTab != _activeTab) { setState(() { _activeTab = widget.initialTab!; - _prioritizeFind = widget.initialTab == 'find'; }); } if (widget.selectedDate != null && widget.selectedDate != _selectedDate) { @@ -98,10 +86,6 @@ class _ShiftsPageState extends State { final bool historyLoaded = (state is ShiftsLoaded) ? state.historyLoaded : false; - final bool myShiftsLoaded = (state is ShiftsLoaded) - ? state.myShiftsLoaded - : false; - final bool blockTabsForFind = _prioritizeFind && !availableLoaded; // Note: "filteredJobs" logic moved to FindShiftsTab // Note: Calendar logic moved to MyShiftsTab @@ -140,8 +124,7 @@ class _ShiftsPageState extends State { "My Shifts", UiIcons.calendar, myShifts.length, - showCount: myShiftsLoaded, - enabled: !blockTabsForFind, + enabled: true, ), const SizedBox(width: 8), _buildTab( @@ -160,7 +143,7 @@ class _ShiftsPageState extends State { UiIcons.clock, historyShifts.length, showCount: historyLoaded, - enabled: !blockTabsForFind && baseLoaded, + enabled: baseLoaded, ), ], ), diff --git a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/tabs/find_shifts_tab.dart b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/tabs/find_shifts_tab.dart index 4e914b84..3bb8c278 100644 --- a/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/tabs/find_shifts_tab.dart +++ b/apps/mobile/packages/features/staff/shifts/lib/src/presentation/widgets/tabs/find_shifts_tab.dart @@ -22,12 +22,6 @@ class _FindShiftsTabState extends State { String _searchQuery = ''; String _jobType = 'all'; - @override - void initState() { - super.initState(); - print('FindShiftsTab init: tab entered, data pending'); - } - Widget _buildFilterTab(String id, String label) { final isSelected = _jobType == id; return GestureDetector( diff --git a/backend/dataconnect/dataconnect.dev.yaml b/backend/dataconnect/dataconnect.dev.yaml deleted file mode 100644 index 39e01fdb..00000000 --- a/backend/dataconnect/dataconnect.dev.yaml +++ /dev/null @@ -1,13 +0,0 @@ -specVersion: "v1" -serviceId: "krow-workforce-db" -location: "us-central1" -schema: - source: "./schema" - datasource: - postgresql: - database: "krow_db" - cloudSql: - instanceId: "krow-sql" - # schemaValidation: "STRICT" # STRICT mode makes Postgres schema match Data Connect exactly. - # schemaValidation: "COMPATIBLE" # COMPATIBLE mode makes Postgres schema compatible with Data Connect. -connectorDirs: ["./connector"] diff --git a/backend/dataconnect/dataconnect.validation.yaml b/backend/dataconnect/dataconnect.validation.yaml deleted file mode 100644 index 9e1775d6..00000000 --- a/backend/dataconnect/dataconnect.validation.yaml +++ /dev/null @@ -1,13 +0,0 @@ -specVersion: "v1" -serviceId: "krow-workforce-db-validation" -location: "us-central1" -schema: - source: "./schema" - datasource: - postgresql: - database: "krow_db" - cloudSql: - instanceId: "krow-sql-validation" - # schemaValidation: "STRICT" # STRICT mode makes Postgres schema match Data Connect exactly. - # schemaValidation: "COMPATIBLE" # COMPATIBLE mode makes Postgres schema compatible with Data Connect. -connectorDirs: ["./connector"] diff --git a/backend/dataconnect/functions/seed.gql b/backend/dataconnect/functions/seed.gql index 073861ae..f59eda6f 100644 --- a/backend/dataconnect/functions/seed.gql +++ b/backend/dataconnect/functions/seed.gql @@ -5,7 +5,7 @@ mutation seedAll @transaction { data: { id: "dvpWnaBjT6UksS5lo04hfMTyq1q1" email: "legendary@krowd.com" - fullName: "Krow Payements" + fullName: "Krow" role: USER userRole: "BUSINESS" } @@ -26,7 +26,7 @@ mutation seedAll @transaction { id: "ef69e942-d6e5-48e5-a8bc-69d3faa63b2f" businessName: "Krow" userId: "dvpWnaBjT6UksS5lo04hfMTyq1q1" - contactName: "Krow Payements" + contactName: "Krow Ops" email: "legendary@krowd.com" phone: "+1-818-555-0148" address: "5000 San Jose Street, Granada Hills, CA, USA" diff --git a/makefiles/dataconnect.mk b/makefiles/dataconnect.mk index c2db1fd6..ba7298ef 100644 --- a/makefiles/dataconnect.mk +++ b/makefiles/dataconnect.mk @@ -1,47 +1,6 @@ # --- Data Connect / Backend --- -# Usage examples: -# make dataconnect-sync DC_ENV=dev -# make dataconnect-seed DC_ENV=validation -# make dataconnect-clean DC_ENV=validation -# make dataconnect-generate-sdk DC_ENV=dev -# -DC_ENV ?= dev - -DC_SERVICE_DEV := krow-workforce-db -DC_SERVICE_VALIDATION := krow-workforce-db-validation - -ifeq ($(DC_ENV),dev) - DC_SERVICE := $(DC_SERVICE_DEV) -else ifeq ($(DC_ENV),validation) - DC_SERVICE := $(DC_SERVICE_VALIDATION) -else - $(error Invalid DC_ENV '$(DC_ENV)'. Use DC_ENV=dev or DC_ENV=validation) -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 - -#creation dataconnect file -dataconnect-file: - @echo "--> Starting creation Firebase Data Connect schema file for service [$(DC_SERVICE)]..." - @test -f backend/dataconnect/dataconnect.$(DC_ENV).yaml || (echo "❌ Missing backend/dataconnect/dataconnect.$(DC_ENV).yaml" && exit 1) - @cp backend/dataconnect/dataconnect.$(DC_ENV).yaml backend/dataconnect/dataconnect.yaml - @echo "✅ Creation Data Connect file completed." - -#creation dev dataconnect file -dataconnect-file-dev: - @echo "--> Starting creation Firebase Data Connect schema file for service [$(DC_SERVICE)]..." - @test -f backend/dataconnect/dataconnect.dev.yaml || (echo "❌ Missing backend/dataconnect/dataconnect.dev.yaml" && exit 1) - @cp backend/dataconnect/dataconnect.dev.yaml backend/dataconnect/dataconnect.yaml - @echo "✅ Creation Data Connect file completed." - - -#creation validation dataconnect file -dataconnect-file-validation: - @echo "--> Starting creation Firebase Data Connect schema file for service [$(DC_SERVICE)]..." - @test -f backend/dataconnect/dataconnect.validation.yaml || (echo "❌ Missing backend/dataconnect/dataconnect.validation.yaml" && exit 1) - @cp backend/dataconnect/dataconnect.validation.yaml backend/dataconnect/dataconnect.yaml - @echo "✅ Creation Data Connect file completed." +.PHONY: dataconnect-enable-apis dataconnect-init dataconnect-deploy dataconnect-sql-migrate dataconnect-generate-sdk dataconnect-sync dataconnect-bootstrap-db check-gcloud-beta dataconnect-clean # Enable all required APIs for Firebase Data Connect + Cloud SQL dataconnect-enable-apis: @@ -55,94 +14,63 @@ dataconnect-enable-apis: @echo "✅ APIs enabled for project [$(GCP_PROJECT_ID)]." # Initialize Firebase Data Connect (interactive wizard). -# use only once per project dataconnect-init: @echo "--> Initializing Firebase Data Connect for alias [$(FIREBASE_ALIAS)] (project: $(GCP_PROJECT_ID))..." @firebase init dataconnect --project $(FIREBASE_ALIAS) @echo "✅ Data Connect initialization command executed. Follow the interactive steps in the CLI." # Deploy Data Connect schemas (GraphQL → Cloud SQL) -dataconnect-deploy: dataconnect-file - @echo "--> Deploying Firebase Data Connect schemas to [$(ENV)] (service: $(DC_SERVICE)) (project: $(FIREBASE_ALIAS))..." - @firebase deploy --only dataconnect:$(DC_SERVICE) --project=$(FIREBASE_ALIAS) +dataconnect-deploy: + @echo "--> Deploying Firebase Data Connect schemas to [$(ENV)] (project: $(FIREBASE_ALIAS))..." + @firebase deploy --only dataconnect --project=$(FIREBASE_ALIAS) @echo "✅ Data Connect deployment completed for [$(ENV)]." # Apply pending SQL migrations for Firebase Data Connect -dataconnect-sql-migrate: dataconnect-file - @echo "--> Applying Firebase Data Connect SQL migrations to [$(ENV)] (service: $(DC_SERVICE)) (project: $(FIREBASE_ALIAS))..." +dataconnect-sql-migrate: + @echo "--> Applying Firebase Data Connect SQL migrations to [$(ENV)] (project: $(FIREBASE_ALIAS))..." @firebase dataconnect:sql:migrate --project=$(FIREBASE_ALIAS) @echo "✅ Data Connect SQL migration completed for [$(ENV)]." # Generate Data Connect client SDK for frontend-web and internal-api-harness -dataconnect-generate-sdk: dataconnect-file +dataconnect-generate-sdk: @echo "--> Generating Firebase Data Connect SDK for web frontend and API harness..." - @firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS) + @firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS) @echo "✅ Data Connect SDK generation completed for [$(ENV)]." # Unified backend schema update workflow (schema -> deploy -> SDK) -dataconnect-sync: dataconnect-file - @echo "--> [1/3] Deploying Data Connect [$(DC_SERVICE)]..." - @firebase deploy --only dataconnect:$(DC_SERVICE) --project=$(FIREBASE_ALIAS) - @echo "--> [2/3] Applying SQL migrations [$(DC_SERVICE)]..." - @firebase dataconnect:sql:migrate $(DC_SERVICE) --project=$(FIREBASE_ALIAS) - @echo "--> [3/3] Regenerating SDK [$(DC_SERVICE)]..." +dataconnect-sync: + @echo "--> [1/3] Deploying Data Connect..." + @firebase deploy --only dataconnect --project=$(FIREBASE_ALIAS) + @echo "--> [2/3] Applying SQL migrations..." + @firebase dataconnect:sql:migrate --project=$(FIREBASE_ALIAS) + @echo "--> [3/3] Regenerating SDK..." @firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS) - @echo "✅ Data Connect SQL, deploy, and SDK generation [$(ENV)]." + @echo "✅ Data Connect SQL, deploy, and SDK generation completed for [$(ENV)]." # Execute seed in Firebase Data Connect -dataconnect-seed: dataconnect-file - @echo "--> Exec seed in Firebase Data Connect (service: $(DC_SERVICE))..." - @firebase dataconnect:execute backend/dataconnect/functions/seed.gql --project=$(FIREBASE_ALIAS) +dataconnect-seed: + @echo "--> Exec seed in Firebase Data Connect..." + @firebase dataconnect:execute backend/dataconnect/functions/seed.gql --project=$(FIREBASE_ALIAS) @echo "✅ Seed executed successfully." # Execute clean, to delete all the data in Firebase Data Connect -dataconnect-clean: dataconnect-file - @echo "--> Exec clean all the data in Firebase Data Connect (service: $(DC_SERVICE))..." - @firebase dataconnect:execute backend/dataconnect/functions/clean.gql --project=$(FIREBASE_ALIAS) +dataconnect-clean: + @echo "--> Exec clean all the data in Firebase Data Connect..." + @firebase dataconnect:execute backend/dataconnect/functions/clean.gql --project=$(FIREBASE_ALIAS) @echo "✅ Clean information executed successfully." # Run tests for Data Connect deployment and migrations -dataconnect-test: dataconnect-file - @echo "--> Running Data Connect tests (service: $(DC_SERVICE))..." - @echo "--> [1/2] Deploying Data Connect..." - @firebase deploy --only dataconnect:$(DC_SERVICE) --project=$(FIREBASE_ALIAS) --dry-run - @echo "--> [2/2] Applying SQL migrations..." +dataconnect-test: + @echo "--> Running Data Connect tests..." + @echo "--> [1/3] Deploying Data Connect..." + @firebase deploy --only dataconnect --project=$(FIREBASE_ALIAS) --dry-run + @echo "--> [2/3] Applying SQL migrations..." @firebase dataconnect:sql:diff --project=$(FIREBASE_ALIAS) @echo "✅ Data Connect tests completed." -dataconnect-backup-dev-to-validation: - @echo "🔍 Validating instances exist in [$(GCP_PROJECT_ID)]..." - @if ! gcloud sql instances describe krow-sql --project=$(GCP_PROJECT_ID) >/dev/null 2>&1; then \ - echo "❌ Dev instance 'krow-sql' not found in project $(GCP_PROJECT_ID)."; \ - exit 1; \ - fi - @if ! gcloud sql instances describe krow-sql-validation --project=$(GCP_PROJECT_ID) >/dev/null 2>&1; then \ - echo "❌ Validation instance 'krow-sql-validation' not found in project $(GCP_PROJECT_ID)."; \ - exit 1; \ - fi - @echo "✅ Instances found." - - @echo "🧰 Creating a backup on dev (krow-sql)..." - @gcloud sql backups create --instance=krow-sql --project=$(GCP_PROJECT_ID) >/dev/null - - @echo "🔎 Fetching latest backup ID..." - @LATEST_BACKUP_ID="$$(gcloud sql backups list --instance=krow-sql --project=$(GCP_PROJECT_ID) --sort-by=~endTime --limit=1 --format='value(id)')"; \ - if [ -z "$$LATEST_BACKUP_ID" ]; then \ - echo "❌ Could not find any backup ID for krow-sql."; \ - exit 1; \ - fi; \ - echo "✅ Latest backup ID: $$LATEST_BACKUP_ID"; \ - echo "⚠️ Restoring into validation..."; \ - gcloud sql backups restore $$LATEST_BACKUP_ID \ - --restore-instance=krow-sql-validation \ - --backup-instance=krow-sql \ - --project=$(GCP_PROJECT_ID) - - @echo "🎉 Done." - # ------------------------------------------------------------------- -# ONE-TIME FULL SETUP FOR CLOUD SQL + DATA CONNECT DEV +# ONE-TIME FULL SETUP FOR CLOUD SQL + DATA CONNECT # ------------------------------------------------------------------- # Check if gcloud and beta group are available @@ -157,7 +85,7 @@ check-gcloud-beta: } @echo "✅ gcloud CLI and 'gcloud beta' are available." -dataconnect-bootstrap-db: dataconnect-file-dev check-gcloud-beta +dataconnect-bootstrap-db: check-gcloud-beta @echo "🔍 Checking if Cloud SQL instance krow-sql already exists in [$(GCP_PROJECT_ID)]..." @if gcloud sql instances describe krow-sql --project=$(GCP_PROJECT_ID) >/dev/null 2>&1; then \ echo "⚠️ Cloud SQL instance 'krow-sql' already exists in project $(GCP_PROJECT_ID)."; \ @@ -184,7 +112,7 @@ dataconnect-bootstrap-db: dataconnect-file-dev check-gcloud-beta @echo "⚠️ Creating Firebase Data Connect service identity..." gcloud beta services identity create \ --service=firebasedataconnect.googleapis.com \ - --project=$(GCP_PROJECT_ID) + --project=$(GCP_PROJECT_ID) @echo "⚠️ Enabling IAM authentication on Cloud SQL instance krow-sql..." gcloud sql instances patch krow-sql \ @@ -196,77 +124,9 @@ dataconnect-bootstrap-db: dataconnect-file-dev check-gcloud-beta firebase dataconnect:sql:setup krow-workforce-db --project=$(FIREBASE_ALIAS) @echo "⚠️ Deploying initial Data Connect configuration..." - @firebase deploy --only dataconnect:$(DC_SERVICE_DEV) --project=$(FIREBASE_ALIAS) + @firebase deploy --only dataconnect --project=$(FIREBASE_ALIAS) @echo "⚠️ Generating initial Data Connect SDK..." - @firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS) - - @echo "🎉 Cloud SQL + Data Connect bootstrap completed successfully!" - - -# ------------------------------------------------------------------- -# ONE-TIME FULL SETUP FOR CLOUD SQL + DATA CONNECT VALIDATEION -# ------------------------------------------------------------------- - -# Creates: krow-sql-validation + krow_db (inside it) + links service krow-workforce-db-validation -# Then clones data from krow-sql -> krow-sql-validation via backup/restore - -dataconnect-bootstrap-validation-database: dataconnect-file-validation - @echo "🔍 Checking if Cloud SQL instance krow-sql-validation already exists in [$(GCP_PROJECT_ID)]..." - @if gcloud sql instances describe krow-sql-validation --project=$(GCP_PROJECT_ID) >/dev/null 2>&1; then \ - echo "⚠️ Cloud SQL instance 'krow-sql-validation' already exists in project $(GCP_PROJECT_ID)."; \ - echo " If you need to recreate it, delete the instance manually first."; \ - exit 1; \ - fi - - @echo "⚠️ Creating Cloud SQL instance krow-sql-validation (tier: $(SQL_TIER))..." - gcloud sql instances create krow-sql-validation \ - --database-version=POSTGRES_15 \ - --tier=$(SQL_TIER) \ - --region=us-central1 \ - --storage-size=10 \ - --storage-auto-increase \ - --availability-type=zonal \ - --backup-start-time=03:00 \ - --project=$(GCP_PROJECT_ID) - - @echo "⚠️ Creating Cloud SQL database krow_db on krow-sql-validation..." - gcloud sql databases create krow_db \ - --instance=krow-sql-validation \ - --project=$(GCP_PROJECT_ID) - - @echo "⚠️ Enabling IAM authentication on Cloud SQL instance krow-sql-validation..." - gcloud sql instances patch krow-sql-validation \ - --project=$(GCP_PROJECT_ID) \ - --database-flags=cloudsql.iam_authentication=on \ - --quiet - - @echo "🔁 Creating a backup on dev instance (krow-sql) to clone data into validation..." - @echo " (Prereq: krow-sql must already exist and be stable.)" - gcloud sql backups create --instance=krow-sql --project=$(GCP_PROJECT_ID) - echo "✅ Backup creation started. Operation: $$BACKUP_OP" - - @echo "🔎 Fetching latest backup ID from krow-sql..." - @BACKUP_ID="$$(gcloud sql backups list --instance=krow-sql --project=$(GCP_PROJECT_ID) --limit=1 --sort-by=~endTime --format='value(id)')"; \ - if [ -z "$$BACKUP_ID" ]; then \ - echo "❌ Could not find a backup ID for krow-sql."; \ - exit 1; \ - fi; \ - echo "✅ Latest backup ID: $$BACKUP_ID"; \ - echo "⚠️ Restoring backup into krow-sql-validation..."; \ - gcloud sql backups restore $$BACKUP_ID \ - --restore-instance=krow-sql-validation \ - --backup-instance=krow-sql \ - --project=$(GCP_PROJECT_ID) - - @echo "⚠️ Linking Data Connect service (krow-workforce-db-validation) with Cloud SQL..." - @echo " When prompted, select instance: krow-sql-validation and database: krow_db" - firebase dataconnect:sql:setup krow-workforce-db-validation --project=$(FIREBASE_ALIAS) - - @echo "⚠️ Deploying Data Connect configuration ($(DC_SERVICE_VALIDATION))..." - @firebase deploy --only dataconnect:$(DC_SERVICE_VALIDATION) --project=$(FIREBASE_ALIAS) - - @echo "⚠️ Generating Data Connect SDK ($(DC_SERVICE))..." @firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS) - @echo "🎉 Validation Cloud SQL + Data Connect bootstrap completed successfully!" + @echo "🎉 Cloud SQL + Data Connect bootstrap completed successfully!" diff --git a/makefiles/launchpad.mk b/makefiles/launchpad.mk index 87050e19..8dbe860f 100644 --- a/makefiles/launchpad.mk +++ b/makefiles/launchpad.mk @@ -2,13 +2,13 @@ .PHONY: launchpad-dev deploy-launchpad-hosting -launchpad-dev: sync-prototypes +launchpad-dev: @echo "--> Starting local Launchpad server using Firebase Hosting emulator..." @echo " - Generating secure email hashes..." @node scripts/generate-allowed-hashes.js @firebase serve --only hosting:launchpad --project=$(FIREBASE_ALIAS) -deploy-launchpad-hosting: sync-prototypes +deploy-launchpad-hosting: @echo "--> Deploying Internal Launchpad to Firebase Hosting..." @echo " - Generating secure email hashes..." @node scripts/generate-allowed-hashes.js