Merge pull request #194 from Oloodi/cleanup_for_sprint3
Cleanup for sprint3
This commit is contained in:
85
.geminiignore
Normal file
85
.geminiignore
Normal file
@@ -0,0 +1,85 @@
|
||||
# =============================================================================
|
||||
# KROW Workforce - .geminiignore
|
||||
#
|
||||
# Indicates to Gemini which files/folders to ignore during analysis
|
||||
# to maintain relevant context and save tokens.
|
||||
# =============================================================================
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Standard Ignores (Same as .gitignore)
|
||||
# -----------------------------------------------------------------------------
|
||||
node_modules/
|
||||
dist/
|
||||
build/
|
||||
coverage/
|
||||
.git/
|
||||
.idea/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
secrets/
|
||||
.env*
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Package Manager Locks (Too large / No semantic value)
|
||||
# -----------------------------------------------------------------------------
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
pubspec.lock
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build Artifacts & Caches
|
||||
# -----------------------------------------------------------------------------
|
||||
.firebase/
|
||||
.vite/
|
||||
.dart_tool/
|
||||
.pub-cache/
|
||||
.gradle/
|
||||
__pycache__/
|
||||
*.tsbuildinfo
|
||||
*.cache
|
||||
*.log
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Large Binary / Media Files
|
||||
# -----------------------------------------------------------------------------
|
||||
*.png
|
||||
*.jpg
|
||||
*.jpeg
|
||||
*.gif
|
||||
*.ico
|
||||
*.svg
|
||||
*.mp4
|
||||
*.mov
|
||||
*.pdf
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.apk
|
||||
*.aab
|
||||
*.ipa
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Generated Code (Reduce noise unless specifically debugging)
|
||||
# -----------------------------------------------------------------------------
|
||||
# Data Connect generated SDKs are useful for reference, but can be verbose.
|
||||
# Uncomment if you want Gemini to ignore them completely.
|
||||
# **/dataconnect-generated/
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Documentation to KEEP (Force Include)
|
||||
# -----------------------------------------------------------------------------
|
||||
# Ensure these are never ignored even if a broad rule matches
|
||||
!README.md
|
||||
!CONTRIBUTING.md
|
||||
!docs/*.md
|
||||
!docs/**/*.md
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Specific Directories
|
||||
# -----------------------------------------------------------------------------
|
||||
# Prototypes: We WANT Gemini to see these for context if they are synced locally,
|
||||
# even if they are ignored by Git. So we do NOT ignore them here.
|
||||
|
||||
# Temporary migration folders
|
||||
_legacy/
|
||||
krow-workforce-export-latest/
|
||||
@@ -1,29 +0,0 @@
|
||||
---
|
||||
name: 'API Validation and Backend Update from Base44'
|
||||
about: 'Use this template to analyze Base44 API changes and update our backend.'
|
||||
title: '[Base44] API Changes Validation and Backend Update'
|
||||
labels: 'enhancement, platform:backend, sred-eligible'
|
||||
---
|
||||
|
||||
### 🎯 Objective
|
||||
Analyze API and event changes from the latest Base44 export, validate their impact on our system, and update our backend (Data Connect, Cloud Functions) to ensure compatibility and integrate new functionalities.
|
||||
|
||||
---
|
||||
|
||||
### 🔬 SR&ED Justification
|
||||
* **Technological Uncertainty:** What is the impact of Base44 API schema changes (deprecated fields, new types, modified logic) on our Data Connect GraphQL schemas and Cloud Functions logic? Is there a risk of data corruption or contract breakage with client applications?
|
||||
* **Systematic Investigation:** We will perform a differential analysis ("diff") of the API schemas, update our GraphQL schema accordingly, adapt business logic in connectors and functions, and then deploy to a test environment to validate end-to-end integration.
|
||||
|
||||
---
|
||||
|
||||
### 💻 Technical Implementation Notes
|
||||
Refer to the [API Documentation Maintenance Guide](docs/06-maintenance-guide.md) for detailed steps on how to update the backend from a Base44 export.
|
||||
|
||||
---
|
||||
|
||||
### ✅ Acceptance Criteria
|
||||
- [ ] The impact analysis of API changes is documented.
|
||||
- [ ] Data Connect schemas and connectors are updated.
|
||||
- [ ] Affected Cloud Functions are updated.
|
||||
- [ ] Changes are deployed and validated in the `dev` environment.
|
||||
- [ ] **Given** an operation (query or mutation) affected by the changes is executed, **when** the API is called, **then** it should return a correct and consistent response with the new schema, without errors.
|
||||
29
.github/ISSUE_TEMPLATE/base44_frontend_update.md
vendored
29
.github/ISSUE_TEMPLATE/base44_frontend_update.md
vendored
@@ -1,29 +0,0 @@
|
||||
---
|
||||
name: 'Frontend Update from Base44'
|
||||
about: 'Use this template to integrate the latest frontend changes from a Base44 export.'
|
||||
title: '[Base44] Frontend Update from Export'
|
||||
labels: 'enhancement, platform:web, sred-eligible'
|
||||
---
|
||||
|
||||
### 🎯 Objective
|
||||
Integrate the latest UI changes (components, queries, mutations) generated from the most recent Base44 export to keep our application up-to-date with the platform schema.
|
||||
|
||||
---
|
||||
|
||||
### 🔬 SR&ED Justification
|
||||
* **Technological Uncertainty:** How will the newly generated queries and mutations integrate with our existing state management and caching logic (e.g., TanStack Query) without introducing regressions or performance issues?
|
||||
* **Systematic Investigation:** We will implement the new generated hooks, refactor affected components, and perform performance and non-regression tests to validate that the integration is robust and performant.
|
||||
|
||||
---
|
||||
|
||||
### 💻 Technical Implementation Notes
|
||||
Refer to the [API Documentation Maintenance Guide](docs/06-maintenance-guide.md) for detailed steps on how to update the frontend from a Base44 export.
|
||||
|
||||
---
|
||||
|
||||
### ✅ Acceptance Criteria
|
||||
- [ ] The Data Connect generated code is updated to the latest version.
|
||||
- [ ] All components and pages affected by the changes are updated and function as expected.
|
||||
- [ ] The code is linted and formatted correctly.
|
||||
- [ ] The functionality is manually tested and works in the `dev` environment.
|
||||
- [ ] **Given** I navigate to a page affected by the update, **when** data is loaded, **then** I should see the new data structured correctly with no console errors.
|
||||
31
.github/ISSUE_TEMPLATE/sred_task.md
vendored
31
.github/ISSUE_TEMPLATE/sred_task.md
vendored
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: SR&ED Task
|
||||
about: Use this template for a new development task that may be eligible for SR&ED.
|
||||
title: '[Category] Short description of the task'
|
||||
labels: 'sred-eligible'
|
||||
---
|
||||
|
||||
### 🎯 Objective
|
||||
*(A concise, one-sentence summary of what this issue aims to accomplish. Ex: "Connect the Events page to the development backend.")*
|
||||
|
||||
---
|
||||
|
||||
### 🔬 SR&ED Justification
|
||||
* **Technological Uncertainty:** What is the technical challenge or unknown we are trying to solve? *(Ex: "Can the Data Connect generated SDK be performantly integrated with TanStack Query in our existing React architecture?")*
|
||||
* **Systematic Investigation:** What is our planned approach to resolve this uncertainty? *(Ex: "We will build a PoC on the Events page, measure load times, and document the optimal integration pattern.")*
|
||||
|
||||
---
|
||||
|
||||
### 💻 Technical Implementation Notes
|
||||
* **Key Files to Modify:** `file1.js`, `file2.gql`, etc.
|
||||
* **Suggested Approach:** A brief description of the technical steps. *(Ex: "1. Define `listEvents` query in GraphQL. 2. Generate the SDK. 3. Create a `useEvents` hook that uses `useQuery`...")*
|
||||
* **Considerations:** Potential pitfalls or points to watch out for. *(Ex: "Ensure loading and error states are handled correctly.")*
|
||||
|
||||
---
|
||||
|
||||
### ✅ Acceptance Criteria
|
||||
*A checklist of what must be true for the task to be considered "done."*
|
||||
- [ ] The code is implemented following the technical notes.
|
||||
- [ ] All new code is linted and formatted.
|
||||
- [ ] The functionality is tested and works as expected in the `dev` environment.
|
||||
- [ ] *(Example for a UI task)* **Given** I am on the Events page, **when** the page loads, **then** I should see a list of events coming from the `dev` backend.
|
||||
199
.gitignore
vendored
199
.gitignore
vendored
@@ -1,85 +1,170 @@
|
||||
# General
|
||||
# ----------------------------------------------------------------
|
||||
# macOS generated files
|
||||
# ==============================================================================
|
||||
# GLOBAL & OS
|
||||
# ==============================================================================
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
.Trash-*
|
||||
|
||||
# IDE configuration files
|
||||
# IDE & Editors
|
||||
.idea/
|
||||
.vscode/
|
||||
*.iml
|
||||
*.iws
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
\#*\#
|
||||
.\#*
|
||||
|
||||
# Log and cache files
|
||||
# Logs & Cache
|
||||
*.log
|
||||
*.cache
|
||||
*.pyc
|
||||
__pycache__/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Secrets (never commit these)
|
||||
# The secrets/ directory is handled by its own .gitignore, but this is an extra layer of safety.
|
||||
# Temporary Files
|
||||
*.tmp
|
||||
*.temp
|
||||
tmp/
|
||||
temp/
|
||||
|
||||
# ==============================================================================
|
||||
# SECURITY (CRITICAL)
|
||||
# ==============================================================================
|
||||
# Secrets directory (contains API keys, service accounts)
|
||||
secrets/
|
||||
*.env
|
||||
.env.*
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.env.development
|
||||
.env.production
|
||||
.env.test
|
||||
!.env.example
|
||||
|
||||
# OS-specific files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
# Certificates & Keys
|
||||
*.pem
|
||||
*.key
|
||||
*.jks
|
||||
*.keystore
|
||||
*.p12
|
||||
*.cer
|
||||
|
||||
# GCP Service Account Keys
|
||||
gcp_keys/
|
||||
**/*.service-account.json
|
||||
**/sa.json
|
||||
|
||||
# Frontend Web (Vite / React)
|
||||
# ----------------------------------------------------------------
|
||||
frontend-web/node_modules/
|
||||
frontend-web/dist/
|
||||
frontend-web/.env.local
|
||||
frontend-web/coverage/
|
||||
frontend-web/.vite/
|
||||
/frontend-web/src/dataconnect-generated/
|
||||
/internal-api-harness/src/dataconnect-generated/
|
||||
frontend-web-free/src/dataconnect-generated/
|
||||
# NPM Auth
|
||||
.npmrc
|
||||
**/.npmrc
|
||||
!**/.npmrc.template
|
||||
|
||||
# ==============================================================================
|
||||
# NODE.JS / WEB (React, Vite, Functions)
|
||||
# ==============================================================================
|
||||
node_modules/
|
||||
dist/
|
||||
dist-ssr/
|
||||
coverage/
|
||||
.nyc_output/
|
||||
.vite/
|
||||
.temp/
|
||||
*.local
|
||||
.eslintcache
|
||||
.stylelintcache
|
||||
.npm
|
||||
.turbo
|
||||
.vercel
|
||||
|
||||
# Vite timestamps
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
# Generated Data Connect SDKs in web projects
|
||||
# Generally ignored as they are regenerated on build
|
||||
**/dataconnect-generated/
|
||||
|
||||
# ==============================================================================
|
||||
# FLUTTER / MOBILE
|
||||
# ==============================================================================
|
||||
# Flutter/Dart
|
||||
.dart_tool/
|
||||
.pub-cache/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
|
||||
# Mobile (Flutter)
|
||||
# ----------------------------------------------------------------
|
||||
# Android
|
||||
.gradle/
|
||||
**/android/app/libs/
|
||||
**/android/key.properties
|
||||
**/android/local.properties
|
||||
|
||||
mobile-apps/*/.dart_tool/
|
||||
mobile-apps/*/.pub-cache/
|
||||
mobile-apps/*/build/
|
||||
mobile-apps/*/.flutter-plugins
|
||||
mobile-apps/*/.flutter-plugins-dependencies
|
||||
# Build outputs
|
||||
build/
|
||||
|
||||
# iOS
|
||||
**/ios/Flutter/Generated.xcconfig
|
||||
**/ios/Flutter/flutter_export_environment.sh
|
||||
**/ios/Podfile.lock
|
||||
**/ios/Pods/
|
||||
**/ios/.symlinks/
|
||||
|
||||
# Firebase / Backend
|
||||
# ----------------------------------------------------------------
|
||||
# Python virtual environments
|
||||
firebase/functions/venv/
|
||||
firebase/dataconnect/venv/
|
||||
# ==============================================================================
|
||||
# FIREBASE & BACKEND
|
||||
# ==============================================================================
|
||||
# Firebase Cache & Emulators
|
||||
.firebase/
|
||||
dataconnect/.dataconnect/
|
||||
backend/dataconnect/.dataconnect/
|
||||
|
||||
# Firebase emulator logs
|
||||
*.log
|
||||
firebase-debug.log
|
||||
firebase-debug.*.log
|
||||
firestore-debug.log
|
||||
ui-debug.log
|
||||
# Debug Logs (Recursive)
|
||||
**/firebase-debug.log
|
||||
**/firebase-debug.*.log
|
||||
**/firestore-debug.log
|
||||
**/ui-debug.log
|
||||
**/database-debug.log
|
||||
**/pubsub-debug.log
|
||||
|
||||
# Generated SDKs (can be regenerated, so often ignored)
|
||||
# Decide with your team if you want to commit these or not.
|
||||
# For now, we will commit them to simplify setup for new developers.
|
||||
# @dataconnect/
|
||||
# Python Virtual Envs (if used)
|
||||
venv/
|
||||
env/
|
||||
ENV/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
|
||||
# ==============================================================================
|
||||
# PROJECT SPECIFIC
|
||||
# ==============================================================================
|
||||
# Secure hashes are committed, but the raw user list is usually kept for reference
|
||||
# unless it contains sensitive info. Here we explicitly ignore the raw file.
|
||||
internal/launchpad/iap-users.txt
|
||||
|
||||
# Temporary files from this project
|
||||
# ----------------------------------------------------------------
|
||||
# The Base44 export directory should not be committed
|
||||
/krow-workforce-export-latest/
|
||||
# Generated Prototypes (must be synced locally via 'make sync-prototypes')
|
||||
internal/launchpad/prototypes/web/*
|
||||
!internal/launchpad/prototypes/web/.keep
|
||||
internal/launchpad/prototypes/mobile/**/*
|
||||
!internal/launchpad/prototypes/mobile/**/.keep
|
||||
|
||||
# The legacy Laravel project should not be committed
|
||||
/legacy-web/
|
||||
|
||||
# The temporary mobile app folders should not be committed
|
||||
/flutter-mobile-client-app/
|
||||
/flutter-mobile-staff-app/
|
||||
/inspiration/
|
||||
# Temporary migration artifacts
|
||||
_legacy/
|
||||
krow-workforce-export-latest/
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
# Base44 Entity Schemas Reference
|
||||
|
||||
This document serves as a developer reference for the original data schemas from the Base44 backend. It is used to ensure feature parity and data integrity during the migration to the new GCP/Firebase backend.
|
||||
|
||||
---
|
||||
|
||||
## User Schema
|
||||
|
||||
```
|
||||
role (text, required)
|
||||
- The role of the user in the app
|
||||
- Options: admin, user
|
||||
|
||||
email (text, required)
|
||||
- The email of the user
|
||||
|
||||
full_name (text, required)
|
||||
- Full name of the user
|
||||
|
||||
user_role (text)
|
||||
- User's role in the system
|
||||
- Options: admin, procurement, operator, sector, client, vendor, workforce
|
||||
|
||||
company_name (text)
|
||||
- Company or organization name
|
||||
|
||||
profile_picture (text)
|
||||
- URL to profile picture
|
||||
|
||||
phone (text)
|
||||
- Phone number
|
||||
|
||||
address (text)
|
||||
- Address
|
||||
|
||||
preferred_vendor_id (text)
|
||||
- ID of the client's preferred/default vendor
|
||||
|
||||
preferred_vendor_name (text)
|
||||
- Name of the client's preferred vendor
|
||||
|
||||
backup_vendor_ids (array)
|
||||
- List of backup vendor IDs
|
||||
|
||||
dashboard_layout (object)
|
||||
- User's customized dashboard layout preferences (legacy, kept for backward compatibility)
|
||||
- widgets (array): Ordered list of visible widgets
|
||||
- hidden_widgets (array): List of hidden widgets
|
||||
- layout_version (text): Layout version for migration
|
||||
|
||||
dashboard_layout_client (object)
|
||||
- Client dashboard layout
|
||||
- widgets (array)
|
||||
- hidden_widgets (array)
|
||||
- layout_version (text)
|
||||
|
||||
dashboard_layout_vendor (object)
|
||||
- Vendor dashboard layout
|
||||
- widgets (array)
|
||||
- hidden_widgets (array)
|
||||
- layout_version (text)
|
||||
|
||||
dashboard_layout_operator (object)
|
||||
- Operator dashboard layout
|
||||
- widgets (array)
|
||||
- hidden_widgets (array)
|
||||
- layout_version (text)
|
||||
|
||||
dashboard_layout_workforce (object)
|
||||
- Workforce dashboard layout
|
||||
- widgets (array)
|
||||
- hidden_widgets (array)
|
||||
- layout_version (text)
|
||||
|
||||
preferences (object)
|
||||
- User preferences and settings
|
||||
- theme (text): Default: "light", Options: light, dark
|
||||
- notifications_enabled (boolean): Default: true
|
||||
- email_notifications (boolean): Default: true
|
||||
```
|
||||
540
Makefile
540
Makefile
@@ -1,60 +1,21 @@
|
||||
# KROW Workforce Project Makefile
|
||||
# -------------------------------
|
||||
# This Makefile provides a central place for common project commands.
|
||||
# It is designed to be the main entry point for developers.
|
||||
# This is the main entry point. It includes modular Makefiles from the 'makefiles/' directory.
|
||||
|
||||
# Use .PHONY to declare targets that are not files, to avoid conflicts.
|
||||
.PHONY: help install dev build integrate-export prepare-export deploy-launchpad deploy-launchpad-full deploy-app admin-install admin-dev admin-build deploy-admin deploy-admin-full configure-iap-launchpad configure-iap-admin list-iap-users remove-iap-user setup-labels export-issues create-issues-from-file install-git-hooks mobile-client-install mobile-client-dev mobile-client-build mobile-staff-install mobile-staff-dev mobile-staff-build dataconnect-enable-apis dataconnect-init dataconnect-deploy dataconnect-sql-migrate dataconnect-generate-sdk dataconnect-sync dataconnect-bootstrap-db
|
||||
|
||||
# The default command to run if no target is specified (e.g., just 'make').
|
||||
# The default command to run if no target is specified.
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# --- Flutter check ---
|
||||
FLUTTER := $(shell which flutter)
|
||||
ifeq ($(FLUTTER),)
|
||||
#$(error "flutter not found in PATH. Please install Flutter and add it to your PATH.")
|
||||
endif
|
||||
# --- Include Modules ---
|
||||
include makefiles/common.mk
|
||||
include makefiles/web.mk
|
||||
include makefiles/launchpad.mk
|
||||
include makefiles/mobile.mk
|
||||
include makefiles/dataconnect.mk
|
||||
include makefiles/tools.mk
|
||||
|
||||
# --- Firebase & GCP Configuration ---
|
||||
GCP_DEV_PROJECT_ID := krow-workforce-dev
|
||||
GCP_STAGING_PROJECT_ID := krow-workforce-staging
|
||||
IAP_SERVICE_ACCOUNT := service-933560802882@gcp-sa-iap.iam.gserviceaccount.com
|
||||
# --- Main Help Command ---
|
||||
.PHONY: help
|
||||
|
||||
# --- Cloud Run Configuration ---
|
||||
CR_ADMIN_SERVICE_NAME := admin-console
|
||||
CR_ADMIN_REGION := us-central1
|
||||
CR_ADMIN_IMAGE_URI = us-docker.pkg.dev/$(GCP_PROJECT_ID)/gcr-io/$(CR_ADMIN_SERVICE_NAME)
|
||||
|
||||
# --- Environment Detection ---
|
||||
ENV ?= dev
|
||||
SERVICE ?= launchpad # Default service for IAP commands: 'launchpad' or 'admin'
|
||||
|
||||
# --- Conditional Variables by Environment ---
|
||||
ifeq ($(ENV),staging)
|
||||
GCP_PROJECT_ID := $(GCP_STAGING_PROJECT_ID)
|
||||
FIREBASE_ALIAS := staging
|
||||
HOSTING_TARGET := app-staging
|
||||
SQL_TIER := db-n1-standard-1
|
||||
else
|
||||
GCP_PROJECT_ID := $(GCP_DEV_PROJECT_ID)
|
||||
FIREBASE_ALIAS := dev
|
||||
HOSTING_TARGET := app-dev
|
||||
SQL_TIER := db-g1-small
|
||||
endif
|
||||
|
||||
# --- Conditional Variables by Service for IAP commands ---
|
||||
ifeq ($(SERVICE),admin)
|
||||
IAP_SERVICE_NAME := $(CR_ADMIN_SERVICE_NAME)
|
||||
IAP_SERVICE_REGION := $(CR_ADMIN_REGION)
|
||||
IAP_PROJECT_ID := $(GCP_PROJECT_ID) # Admin console is env-specific
|
||||
else
|
||||
IAP_SERVICE_NAME := $(CR_LAUNCHPAD_SERVICE_NAME)
|
||||
IAP_SERVICE_REGION := $(CR_LAUNCHPAD_REGION)
|
||||
IAP_PROJECT_ID := $(GCP_DEV_PROJECT_ID) # Launchpad is dev-only
|
||||
endif
|
||||
|
||||
|
||||
# Shows this help message.
|
||||
help:
|
||||
@echo "--------------------------------------------------"
|
||||
@echo " KROW Workforce - Available Makefile Commands"
|
||||
@@ -69,479 +30,26 @@ help:
|
||||
@echo " --- MOBILE APP DEVELOPMENT ---"
|
||||
@echo " make mobile-client-install - Install dependencies for client app"
|
||||
@echo " make mobile-client-dev - Run client app in dev mode"
|
||||
@echo " make mobile-client-build - Build client app (requires ENV & PLATFORM, optional BUILD_TYPE=apk)"
|
||||
@echo ""
|
||||
@echo " make mobile-client-build - Build client app (requires ENV & PLATFORM)"
|
||||
@echo " make mobile-staff-install - Install dependencies for staff app"
|
||||
@echo " make mobile-staff-dev - Run staff app in dev mode"
|
||||
@echo " make mobile-staff-build - Build staff app (requires ENV & PLATFORM, optional BUILD_TYPE=apk)"
|
||||
@echo " make mobile-staff-build - Build staff app (requires ENV & PLATFORM)"
|
||||
@echo ""
|
||||
@echo " --- DEPLOYMENT ---"
|
||||
@echo " make deploy-launchpad-hosting - Deploys internal launchpad to Firebase Hosting (Auth via Firebase)."
|
||||
@echo " make deploy-admin-full [ENV=staging] - Deploys Admin Console to Cloud Run with IAP (default: dev)."
|
||||
@echo " make deploy-app [ENV=staging] - Builds and deploys the main web app via Firebase Hosting (default: dev)."
|
||||
@echo " make deploy-launchpad-hosting - Deploys internal launchpad to Firebase Hosting."
|
||||
@echo " make deploy-app [ENV=staging] - Builds and deploys the main web app (default: dev)."
|
||||
@echo ""
|
||||
@echo " --- CLOUD IAP MANAGEMENT ---"
|
||||
@echo " make list-iap-users [SERVICE=admin] - Lists IAP users for a service (default: launchpad)."
|
||||
@echo " make remove-iap-user USER=... [SERVICE=admin] - Removes an IAP user from a service."
|
||||
@echo ""
|
||||
@echo " --- PROJECT MANAGEMENT & TOOLS ---"
|
||||
@echo " make setup-labels - Creates/updates GitHub labels from labels.yml."
|
||||
@echo " make export-issues [ARGS=\"--state=all --label=bug\"] - Exports GitHub issues to a markdown file. See scripts/export_issues.sh for options."
|
||||
@echo " make create-issues-from-file - Bulk creates GitHub issues from a markdown file."
|
||||
@echo " --- DEVELOPMENT TOOLS ---"
|
||||
@echo " make install-git-hooks - Installs git pre-push hook to protect main/dev branches."
|
||||
@echo " make sync-prototypes - Builds and copies prototypes from adjacent 'client-krow-poc' repo."
|
||||
@echo ""
|
||||
@echo " --- DATA CONNECT MANAGEMENT ---"
|
||||
@echo " make dataconnect-enable-apis - Enables required GCP APIs for Data Connect."
|
||||
@echo " make dataconnect-init - Initializes Firebase Data Connect (interactive wizard)."
|
||||
@echo " make dataconnect-deploy - Deploys Data Connect schemas (GraphQL -> Cloud SQL)."
|
||||
@echo " make dataconnect-sql-migrate - Applies Data Connect SQL migrations to Cloud SQL."
|
||||
@echo " make dataconnect-generate-sdk - Regenerates the Data Connect SDK (frontend-web + internal-api-harness)."
|
||||
@echo " make dataconnect-sync - Runs sql:migrate + deploy + sdk:generate in order."
|
||||
@echo " make dataconnect-bootstrap-db - ONE-TIME: creates krow-sql, krow_db, links Data Connect, deploys, and generates initial SDK."
|
||||
@echo " make check-gcloud-beta - Validates gcloud + gcloud beta group availability."
|
||||
@echo ""
|
||||
@echo " --- BASE44 EXPORT WORKFLOW ---"
|
||||
@echo " make integrate-export - Integrates a new Base44 export from '../krow-workforce-export-latest'."
|
||||
@echo " make prepare-export - Prepares a fresh Base44 export for local use."
|
||||
@echo " make dataconnect-init - Initializes Firebase Data Connect."
|
||||
@echo " make dataconnect-deploy - Deploys Data Connect schemas."
|
||||
@echo " make dataconnect-sql-migrate - Applies SQL migrations."
|
||||
@echo " make dataconnect-generate-sdk - Regenerates the Data Connect SDK."
|
||||
@echo " make dataconnect-sync - Runs migrate + deploy + generate-sdk."
|
||||
@echo " make dataconnect-bootstrap-db - ONE-TIME: Full Cloud SQL + Data Connect setup."
|
||||
@echo ""
|
||||
@echo " make help - Shows this help message."
|
||||
@echo "--------------------------------------------------"
|
||||
|
||||
# --- Core Development ---
|
||||
install:
|
||||
@echo "--> Installing web frontend dependencies..."
|
||||
@cd frontend-web && npm install
|
||||
|
||||
dev:
|
||||
@echo "--> Ensuring web frontend dependencies are installed..."
|
||||
@cd frontend-web && npm install
|
||||
@echo "--> Starting web frontend development server on http://localhost:5173 ..."
|
||||
@cd frontend-web && npm run dev
|
||||
|
||||
build:
|
||||
@echo "--> Building web frontend for production..."
|
||||
@cd frontend-web && VITE_APP_ENV=$(ENV) npm run build
|
||||
|
||||
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)
|
||||
|
||||
# --- Deployment ---
|
||||
deploy-launchpad-hosting:
|
||||
@echo "--> Deploying Internal Launchpad to Firebase Hosting..."
|
||||
@echo " - Generating secure email hashes..."
|
||||
@node scripts/generate-allowed-hashes.js
|
||||
@echo " - Target: hosting:launchpad"
|
||||
@echo " - Project: $(FIREBASE_ALIAS)"
|
||||
@firebase deploy --only hosting:launchpad --project=$(FIREBASE_ALIAS)
|
||||
@echo "--> ✅ Deployment to Firebase Hosting successful."
|
||||
|
||||
deploy-app: build
|
||||
@echo "--> Deploying Frontend Web App to [$(ENV)] environment..."
|
||||
@firebase deploy --only hosting:$(HOSTING_TARGET) --project=$(FIREBASE_ALIAS)
|
||||
|
||||
# --- Admin Console ---
|
||||
admin-install:
|
||||
@echo "--> Installing admin console dependencies..."
|
||||
@cd admin-web && npm install
|
||||
|
||||
admin-dev:
|
||||
@echo "--> Starting admin console development server on http://localhost:5174 ..."
|
||||
@cd admin-web && npm run dev -- --port 5174
|
||||
|
||||
admin-build:
|
||||
@echo "--> Building admin console for production..."
|
||||
@node scripts/patch-admin-layout-for-env-label.js
|
||||
@cd admin-web && VITE_APP_ENV=$(ENV) npm run build
|
||||
|
||||
# --- API Test Harness ---
|
||||
harness-install:
|
||||
@echo "--> Installing API Test Harness dependencies..."
|
||||
@cd internal-api-harness && npm install
|
||||
|
||||
harness-dev: dataconnect-sync
|
||||
@echo "--> Starting API Test Harness development server on http://localhost:5175 ..."
|
||||
@cd internal-api-harness && npm run dev -- --port 5175
|
||||
|
||||
harness-build:
|
||||
@echo "--> Building API Test Harness for production..."
|
||||
@cd internal-api-harness && npm run build -- --mode $(ENV)
|
||||
|
||||
harness-deploy: harness-build
|
||||
@echo "--> Deploying API Test Harness to [$(ENV)] environment..."
|
||||
@firebase deploy --only hosting:api-harness-$(ENV) --project=$(FIREBASE_ALIAS)
|
||||
|
||||
deploy-admin: admin-build
|
||||
@echo "--> Building and deploying Admin Console to Cloud Run [$(ENV)]..."
|
||||
@echo " - Step 1: Building container image..."
|
||||
@cd admin-web && gcloud builds submit \
|
||||
--tag $(CR_ADMIN_IMAGE_URI) \
|
||||
--project=$(GCP_PROJECT_ID)
|
||||
@echo " - Step 2: Deploying to Cloud Run..."
|
||||
@gcloud run deploy $(CR_ADMIN_SERVICE_NAME) \
|
||||
--image $(CR_ADMIN_IMAGE_URI) \
|
||||
--platform managed \
|
||||
--region $(CR_ADMIN_REGION) \
|
||||
--no-allow-unauthenticated \
|
||||
--project=$(GCP_PROJECT_ID)
|
||||
@echo " - Step 3: Enabling IAP on the service..."
|
||||
@gcloud beta run services update $(CR_ADMIN_SERVICE_NAME) \
|
||||
--region=$(CR_ADMIN_REGION) \
|
||||
--project=$(GCP_PROJECT_ID) \
|
||||
--iap
|
||||
@echo "--> ✅ Admin Console deployment to Cloud Run successful."
|
||||
|
||||
deploy-admin-full: deploy-admin configure-iap-admin
|
||||
@echo "✅ Admin Console deployed and IAP configured successfully!"
|
||||
|
||||
|
||||
# --- Frontend Web Free ---
|
||||
free-dev: dataconnect-sync
|
||||
@echo "--> Starting free web development server on http://localhost:5174 ..."
|
||||
@cd frontend-web-free && npm run dev -- --port 5174
|
||||
|
||||
# --- Cloud IAP Configuration ---
|
||||
configure-iap-admin:
|
||||
@echo "--> Configuring IAP for Cloud Run service [$(CR_ADMIN_SERVICE_NAME)] in [$(ENV)]..."
|
||||
@echo " - Granting Cloud Run Invoker role to IAP Service Account..."
|
||||
@gcloud run services add-iam-policy-binding $(CR_ADMIN_SERVICE_NAME) \
|
||||
--region=$(CR_ADMIN_REGION) \
|
||||
--project=$(GCP_PROJECT_ID) \
|
||||
--member=\"serviceAccount:$(IAP_SERVICE_ACCOUNT)\" \
|
||||
--role='roles/run.invoker' \
|
||||
--quiet
|
||||
@echo " - Adding users from iap-users.txt..."
|
||||
@cd admin-web && \
|
||||
grep -v '^#' iap-users.txt | grep -v '^$$' | while read -r member; do \
|
||||
echo " Adding $$member as IAP-secured Web App User..."; \
|
||||
gcloud beta iap web add-iam-policy-binding \
|
||||
--project=$(GCP_PROJECT_ID) \
|
||||
--resource-type=cloud-run \
|
||||
--service=$(CR_ADMIN_SERVICE_NAME) \
|
||||
--region=$(CR_ADMIN_REGION) \
|
||||
--member=\"$$member\" \
|
||||
--role='roles/iap.httpsResourceAccessor' \
|
||||
--quiet; \
|
||||
done
|
||||
@echo "✅ IAP configuration for Admin Console complete."
|
||||
|
||||
list-iap-users:
|
||||
@echo "--> Current IAP users for Cloud Run service [$(IAP_SERVICE_NAME)]:"
|
||||
@gcloud beta iap web get-iam-policy \
|
||||
--project=$(IAP_PROJECT_ID) \
|
||||
--resource-type=cloud-run \
|
||||
--service=$(IAP_SERVICE_NAME) \
|
||||
--region=$(IAP_SERVICE_REGION)
|
||||
|
||||
remove-iap-user:
|
||||
@if [ -z "$(USER)" ]; then \
|
||||
echo "❌ Error: Please specify USER=user:email@example.com"; \
|
||||
exit 1; \
|
||||
fi
|
||||
@echo "--> Removing IAP access for $(USER) from Cloud Run service [$(IAP_SERVICE_NAME)]..."
|
||||
@gcloud beta iap web remove-iam-policy-binding \
|
||||
--project=$(IAP_PROJECT_ID) \
|
||||
--resource-type=cloud-run \
|
||||
--service=$(IAP_SERVICE_NAME) \
|
||||
--region=$(IAP_SERVICE_REGION) \
|
||||
--member=\"$(USER)\" \
|
||||
--role='roles/iap.httpsResourceAccessor' \
|
||||
--quiet
|
||||
@echo "✅ User removed from IAP."
|
||||
|
||||
# --- Project Management ---
|
||||
setup-labels:
|
||||
@echo "--> Setting up GitHub labels..."
|
||||
@./scripts/setup-github-labels.sh
|
||||
|
||||
export-issues:
|
||||
@echo "--> Exporting GitHub issues to documentation..."
|
||||
@./scripts/export_issues.sh $(ARGS)
|
||||
|
||||
create-issues-from-file:
|
||||
@echo "--> Creating GitHub issues from file..."
|
||||
@./scripts/create_issues.py $(ARGS)
|
||||
|
||||
# --- Development Tools ---
|
||||
install-git-hooks:
|
||||
@echo "--> Installing Git hooks..."
|
||||
@ln -sf ../../scripts/git-hooks/pre-push .git/hooks/pre-push
|
||||
@echo "✅ pre-push hook installed successfully. Direct pushes to 'main' and 'dev' are now blocked."
|
||||
|
||||
# --- Base44 Export Workflow ---
|
||||
integrate-export:
|
||||
@echo "--> Integrating new Base44 export into frontend-web/..."
|
||||
@if [ ! -d "../krow-workforce-export-latest" ]; then \
|
||||
echo "❌ Error: Export directory '../krow-workforce-export-latest' not found."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@echo " - Creating frontend-web/.local-preserve to preserve local directories (src/dataconnect-generated, src/lib)..."
|
||||
@mkdir -p frontend-web/.local-preserve
|
||||
@if [ -d "frontend-web/src/dataconnect-generated" ]; then \
|
||||
mv frontend-web/src/dataconnect-generated frontend-web/.local-preserve/dataconnect-generated; \
|
||||
fi
|
||||
@if [ -d "frontend-web/src/lib" ]; then \
|
||||
mv frontend-web/src/lib frontend-web/.local-preserve/lib; \
|
||||
fi
|
||||
|
||||
@if [ -d "frontend-web/src/api" ]; then \
|
||||
mv frontend-web/src/api frontend-web/.local-preserve/api; \
|
||||
fi
|
||||
@if [ -f "frontend-web/src/firebase.js" ]; then \
|
||||
mv frontend-web/src/firebase.js frontend-web/.local-preserve/firebase.js; \
|
||||
fi
|
||||
@if [ -d "frontend-web/src/components/auth" ]; then \
|
||||
mv frontend-web/src/components/auth frontend-web/.local-preserve/components-auth; \
|
||||
fi
|
||||
@if [ -f "frontend-web/src/hooks/useAuth.js" ]; then \
|
||||
mv frontend-web/src/hooks/useAuth.js frontend-web/.local-preserve/useAuth.js; \
|
||||
fi
|
||||
@if [ -f "frontend-web/src/pages/Login.jsx" ]; then \
|
||||
mv frontend-web/src/pages/Login.jsx frontend-web/.local-preserve/Login.jsx; \
|
||||
fi
|
||||
@if [ -f "frontend-web/src/pages/Register.jsx" ]; then \
|
||||
mv frontend-web/src/pages/Register.jsx frontend-web/.local-preserve/Register.jsx; \
|
||||
fi
|
||||
|
||||
@echo " - Removing old src directory..."
|
||||
@rm -rf frontend-web/src
|
||||
@echo " - Copying new src directory..."
|
||||
@cp -R ../krow-workforce-export-latest/src ./frontend-web/src
|
||||
|
||||
@echo " - Restoring preserved directories..."
|
||||
@if [ -d "frontend-web/.local-preserve/dataconnect-generated" ]; then \
|
||||
rm -rf frontend-web/src/dataconnect-generated; \
|
||||
mv frontend-web/.local-preserve/dataconnect-generated frontend-web/src/dataconnect-generated; \
|
||||
fi
|
||||
@if [ -d "frontend-web/.local-preserve/lib" ]; then \
|
||||
rm -rf frontend-web/src/lib; \
|
||||
mv frontend-web/.local-preserve/lib frontend-web/src/lib; \
|
||||
fi
|
||||
@if [ -d "frontend-web/.local-preserve/api" ]; then \
|
||||
rm -rf frontend-web/src/api; \
|
||||
mv frontend-web/.local-preserve/api frontend-web/src/api; \
|
||||
fi
|
||||
@if [ -f "frontend-web/.local-preserve/firebase.js" ]; then \
|
||||
mv frontend-web/.local-preserve/firebase.js frontend-web/src/firebase.js; \
|
||||
fi
|
||||
@if [ -d "frontend-web/.local-preserve/components-auth" ]; then \
|
||||
mkdir -p frontend-web/src/components; \
|
||||
rm -rf frontend-web/src/components/auth; \
|
||||
mv frontend-web/.local-preserve/components-auth frontend-web/src/components/auth; \
|
||||
fi
|
||||
@if [ -f "frontend-web/.local-preserve/useAuth.js" ]; then \
|
||||
mkdir -p frontend-web/src/hooks; \
|
||||
rm -f frontend-web/src/hooks/useAuth.js; \
|
||||
mv frontend-web/.local-preserve/useAuth.js frontend-web/src/hooks/useAuth.js; \
|
||||
fi
|
||||
@if [ -f "frontend-web/.local-preserve/Login.jsx" ]; then \
|
||||
mkdir -p frontend-web/src/pages; \
|
||||
rm -f frontend-web/src/pages/Login.jsx; \
|
||||
mv frontend-web/.local-preserve/Login.jsx frontend-web/src/pages/Login.jsx; \
|
||||
fi
|
||||
@if [ -f "frontend-web/.local-preserve/Register.jsx" ]; then \
|
||||
mkdir -p frontend-web/src/pages; \
|
||||
rm -f frontend-web/src/pages/Register.jsx; \
|
||||
mv frontend-web/.local-preserve/Register.jsx frontend-web/src/pages/Register.jsx; \
|
||||
fi
|
||||
|
||||
@echo " - Deleting frontend-web/.local-preserve..."
|
||||
@rm -rf frontend-web/.local-preserve
|
||||
|
||||
@echo " - Copying new index.html..."
|
||||
@cp ../krow-workforce-export-latest/index.html ./frontend-web/index.html
|
||||
@echo " - Patching base44Client.js for local development..."
|
||||
@node scripts/patch-base44-client.js
|
||||
@echo " - Patching queryKey in Layout.jsx for local development..."
|
||||
@node scripts/patch-layout-query-key.js
|
||||
@echo " - Patching Dashboard.jsx for environment label..."
|
||||
@node scripts/patch-dashboard-for-env-label.js
|
||||
@echo " - Patching index.html for title..."
|
||||
@node scripts/patch-index-html.js
|
||||
@echo "--> Integration complete. Next step: 'make prepare-export'."
|
||||
|
||||
prepare-export:
|
||||
@echo "--> Preparing fresh Base44 export for local development..."
|
||||
@node scripts/prepare-export.js
|
||||
@echo "--> Preparation complete. You can now run 'make dev'."
|
||||
|
||||
# --- Data Connect / Backend ---
|
||||
|
||||
# Enable all required APIs for Firebase Data Connect + Cloud SQL
|
||||
dataconnect-enable-apis:
|
||||
@echo "--> Enabling Firebase & Data Connect APIs on project [$(GCP_PROJECT_ID)]..."
|
||||
@gcloud services enable firebase.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||
@gcloud services enable firebasedataconnect.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||
@gcloud services enable sqladmin.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||
@gcloud services enable iam.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||
@gcloud services enable cloudresourcemanager.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||
@gcloud services enable secretmanager.googleapis.com --project=$(GCP_PROJECT_ID)
|
||||
@echo "✅ APIs enabled for project [$(GCP_PROJECT_ID)]."
|
||||
|
||||
# Initialize Firebase Data Connect (interactive wizard).
|
||||
# This wraps the command so we remember how to run it for dev/staging/prod.
|
||||
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:
|
||||
@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:
|
||||
@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:
|
||||
@echo "--> Generating Firebase Data Connect SDK for web frontend and API harness..."
|
||||
@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:
|
||||
@echo "--> [1/3] Applying SQL migrations..."
|
||||
@firebase dataconnect:sql:migrate --project=$(FIREBASE_ALIAS)
|
||||
@echo "--> [2/3] Deploying Data Connect..."
|
||||
@firebase deploy --only dataconnect --project=$(FIREBASE_ALIAS)
|
||||
@echo "--> [3/3] Regenerating SDK..."
|
||||
@firebase dataconnect:sdk:generate --project=$(FIREBASE_ALIAS)
|
||||
@echo "✅ Data Connect SQL, deploy, and SDK generation completed for [$(ENV)]."
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# ONE-TIME FULL SETUP FOR CLOUD SQL + DATA CONNECT
|
||||
# -------------------------------------------------------------------
|
||||
# ⚠️ WARNING:
|
||||
# This should only be executed when setting up a brand new environment
|
||||
# (e.g., first-time dev setup or new GCP project).
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# Comprueba que gcloud y el grupo beta están disponibles
|
||||
check-gcloud-beta:
|
||||
@command -v gcloud >/dev/null 2>&1 || { \
|
||||
echo "❌ gcloud CLI not found. Please install it: https://cloud.google.com/sdk/docs/install"; \
|
||||
exit 1; \
|
||||
}
|
||||
@gcloud beta --help >/dev/null 2>&1 || { \
|
||||
echo "❌ 'gcloud beta' is not available. Run 'gcloud components update' or reinstall the SDK."; \
|
||||
exit 1; \
|
||||
}
|
||||
@echo "✅ gcloud CLI and 'gcloud beta' are available."
|
||||
|
||||
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)."; \
|
||||
echo " If you really need to recreate it, delete the instance manually first."; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
@echo "⚠️ Creating Cloud SQL instance krow-sql (tier: $(SQL_TIER)) (ONLY RUN THIS ONCE PER PROJECT)..."
|
||||
gcloud sql instances create krow-sql \
|
||||
--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..."
|
||||
gcloud sql databases create krow_db \
|
||||
--instance=krow-sql \
|
||||
--project=$(GCP_PROJECT_ID)
|
||||
|
||||
@echo "⚠️ Creating Firebase Data Connect service identity..."
|
||||
gcloud beta services identity create \
|
||||
--service=firebasedataconnect.googleapis.com \
|
||||
--project=$(GCP_PROJECT_ID)
|
||||
|
||||
@echo "⚠️ Enabling IAM authentication on Cloud SQL instance krow-sql..."
|
||||
gcloud sql instances patch krow-sql \
|
||||
--project=$(GCP_PROJECT_ID) \
|
||||
--database-flags=cloudsql.iam_authentication=on \
|
||||
--quiet
|
||||
|
||||
@echo "⚠️ Linking Data Connect service (krow-workforce-db) with Cloud SQL..."
|
||||
firebase dataconnect:sql:setup krow-workforce-db --project=$(FIREBASE_ALIAS)
|
||||
|
||||
@echo "⚠️ Deploying initial Data Connect configuration..."
|
||||
@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!"
|
||||
|
||||
# --- Mobile App Development ---
|
||||
FLAVOR :=
|
||||
ifeq ($(ENV),dev)
|
||||
FLAVOR := dev
|
||||
else ifeq ($(ENV),staging)
|
||||
FLAVOR := staging
|
||||
else ifeq ($(ENV),prod)
|
||||
FLAVOR := production
|
||||
endif
|
||||
|
||||
BUILD_TYPE ?= appbundle
|
||||
|
||||
mobile-client-install:
|
||||
@echo "--> Installing Flutter dependencies for client app..."
|
||||
@cd mobile-apps/client-app && $(FLUTTER) pub get
|
||||
|
||||
mobile-client-dev:
|
||||
@echo "--> Running client app in dev mode..."
|
||||
@echo "--> If using VS code, use the debug configurations"
|
||||
@cd mobile-apps/client-app && $(FLUTTER) run --flavor dev -t lib/main_dev.dart
|
||||
|
||||
mobile-client-build:
|
||||
@if [ "$(ENV)" != "dev" ] && [ "$(ENV)" != "staging" ] && [ "$(ENV)" != "prod" ]; then \
|
||||
echo "ERROR: ENV must be one of dev, staging, or prod."; exit 1; \
|
||||
fi
|
||||
@if [ "$(PLATFORM)" != "android" ] && [ "$(PLATFORM)" != "ios" ]; then \
|
||||
echo "ERROR: PLATFORM must be either android or ios."; exit 1; \
|
||||
fi
|
||||
@echo "--> Building client app for $(PLATFORM) with flavor $(FLAVOR)..."
|
||||
@cd mobile-apps/client-app && \
|
||||
$(FLUTTER) pub get && \
|
||||
$(FLUTTER) pub run build_runner build --delete-conflicting-outputs && \
|
||||
if [ "$(PLATFORM)" = "android" ]; then \
|
||||
$(FLUTTER) build $(BUILD_TYPE) --flavor $(FLAVOR); \
|
||||
elif [ "$(PLATFORM)" = "ios" ]; then \
|
||||
$(FLUTTER) build ipa --flavor $(FLAVOR); \
|
||||
fi
|
||||
|
||||
mobile-staff-install:
|
||||
@echo "--> Installing Flutter dependencies for staff app..."
|
||||
@cd mobile-apps/staff-app && $(FLUTTER) pub get
|
||||
|
||||
mobile-staff-dev:
|
||||
@echo "--> Running staff app in dev mode..."
|
||||
@echo "--> If using VS code, use the debug configurations"
|
||||
@cd mobile-apps/staff-app && $(FLUTTER) run --flavor dev -t lib/main_dev.dart
|
||||
|
||||
mobile-staff-build:
|
||||
@if [ "$(ENV)" != "dev" ] && [ "$(ENV)" != "staging" ] && [ "$(ENV)" != "prod" ]; then \
|
||||
echo "ERROR: ENV must be one of dev, staging, or prod."; exit 1; \
|
||||
fi
|
||||
@if [ "$(PLATFORM)" != "android" ] && [ "$(PLATFORM)" != "ios" ]; then \
|
||||
echo "ERROR: PLATFORM must be either android or ios."; exit 1; \
|
||||
fi
|
||||
@echo "--> Building staff app for $(PLATFORM) with flavor $(FLAVOR)..."
|
||||
@cd mobile-apps/staff-app && \
|
||||
$(FLUTTER) pub get && \
|
||||
$(FLUTTER) pub run build_runner build --delete-conflicting-outputs && \
|
||||
if [ "$(PLATFORM)" = "android" ]; then \
|
||||
$(FLUTTER) build $(BUILD_TYPE) --flavor $(FLAVOR); \
|
||||
elif [ "$(PLATFORM)" = "ios" ]; then \
|
||||
$(FLUTTER) build ipa --flavor $(FLAVOR); \
|
||||
fi
|
||||
@echo "--------------------------------------------------"
|
||||
112
README.md
112
README.md
@@ -1,81 +1,71 @@
|
||||
# Krow Workforce Management Platform
|
||||
# KROW Workforce Monorepo
|
||||
|
||||
Krow is a comprehensive monorepo platform designed to streamline workforce management for events, hospitality, and large-scale enterprise operations. It connects clients, operators, vendors, and staff in a unified ecosystem, leveraging modern technology to optimize every step from procurement to payroll.
|
||||
KROW is a comprehensive workforce management platform designed to streamline operations for events, hospitality, and enterprise staffing. This monorepo contains all components of the ecosystem, from the data layer to the user-facing applications.
|
||||
|
||||
## 🚀 What's in this Monorepo?
|
||||
## 🚀 Repository Structure
|
||||
|
||||
- **/firebase/**: This directory is the backbone of our backend infrastructure. It contains:
|
||||
- **Firestore Rules (`firestore.rules`):** Defines the security and access control logic for our NoSQL database, ensuring that users can only read and write data they are authorized to access.
|
||||
- **Cloud Storage Rules (`storage.rules`):** Secures file uploads and downloads (like compliance documents and user avatars).
|
||||
- **Data Connect (`dataconnect/`):** Houses the configuration for Firebase Data Connect, including the GraphQL schema, connectors, queries, and mutations that define our API layer.
|
||||
### 📦 Apps (`/apps`)
|
||||
These are the production-ready applications for our users:
|
||||
- **`web-dashboard/`**: The primary React/Vite dashboard for Admin, Vendors, and Clients.
|
||||
- **`mobile-client/`**: Flutter application for final clients to manage orders and billing.
|
||||
- **`mobile-staff/`**: Flutter application for staff members (scheduling, clock-in/out, earnings).
|
||||
|
||||
- **/admin-web/**: The central "mission control" for platform administrators. This React/Vite web application provides a secure interface for:
|
||||
- **User Management:** Inviting new users (the very first client or operator) and managing roles/permissions across the entire ecosystem.
|
||||
- **Platform Analytics:** Monitoring application usage, top pages, and user activity.
|
||||
- **System Logs:** A log explorer for diagnosing issues and monitoring the platform's health.
|
||||
### ⚙️ Backend (`/backend`)
|
||||
The core data engine powering all applications:
|
||||
- **`dataconnect/`**: Firebase Data Connect configuration, GraphQL schemas (PostgreSQL), and auto-generated SDKs.
|
||||
|
||||
- **/frontend-web/**: The primary web application for core business operations, used by procurement managers, operators, and clients. This React/Vite application includes modules for:
|
||||
- **Vendor Management:** Onboarding, compliance tracking, and performance scorecards.
|
||||
- **Event & Order Management:** Creating and managing staffing orders.
|
||||
- **Invoicing & Payroll:** Financial workflows for clients and staff.
|
||||
- **Dashboards:** Role-specific dashboards for different user types.
|
||||
### 🛠️ Internal (`/internal`)
|
||||
Tools and resources for the development and operations team:
|
||||
- **`launchpad/`**: A secure portal (DevOps Launchpad) to access internal resources, documentation, and infrastructure links.
|
||||
- **`api-harness/`**: A technical tool for testing and validating the Data Connect API and Cloud Functions.
|
||||
- **`prototypes/`**: Reference code and visual prototypes (synchronized from external sources).
|
||||
|
||||
- **/mobile-apps/**: This directory is planned for our future mobile applications. It is structured to contain two distinct apps:
|
||||
- `client-app`: A dedicated application for clients to create orders, track events, and manage billing on the go.
|
||||
- `staff-app`: An essential tool for workforce members to view schedules, clock in/out, manage their profiles, and track earnings.
|
||||
|
||||
- **/docs/**: The single source of truth for all project documentation. This includes:
|
||||
- **Vision & Roadmaps:** High-level strategy, product goals, and technical direction.
|
||||
- **Architecture:** Detailed diagrams and explanations of the system architecture.
|
||||
- **API Specifications:** Documentation for our GraphQL API.
|
||||
- **Development Guides:** Conventions, setup instructions, and maintenance procedures.
|
||||
|
||||
- **/scripts/**: A collection of automation scripts to streamline development and operational tasks. These scripts are primarily executed via the `Makefile` and handle tasks like database patching, environment setup, and code generation.
|
||||
|
||||
- **/secrets/**: A Git-ignored directory for storing sensitive credentials, API keys, and environment-specific configuration files. This ensures that no confidential information is ever committed to the repository.
|
||||
|
||||
## 📚 Documentation Overview
|
||||
|
||||
This section provides a quick guide to the most important documentation files in this monorepo, ordered by logical reading flow:
|
||||
|
||||
- **[00-vision.md](./docs/00-vision.md)**: The "Why" behind the KROW platform, outlining our core objectives and guiding principles.
|
||||
- **[01-product-functional-roadmap.md](./docs/01-product-functional-roadmap.md)**: The "What" we are building, from a user-facing features perspective.
|
||||
- **[02-architecture-overview.md](./docs/02-architecture-overview.md)**: Visual diagrams explaining the technical architecture of our web and mobile applications.
|
||||
- **[03-backend-api-specification.md](./docs/03-backend-api-specification.md)**: The detailed technical specification for our custom backend API.
|
||||
- **[04-strategy-technical-roadmap.md](./docs/04-strategy-technical-roadmap.md)**: Our strategic plan for building the platform, outlining phases and milestones.
|
||||
- **[05-project-plan.md](./docs/05-project-plan.md)**: A detailed breakdown of tasks by milestone, ready for GitHub Issues.
|
||||
- **[06-maintenance-guide.md](./docs/06-maintenance-guide.md)**: The operational manual for integrating updates from the Base44 visual builder.
|
||||
- **[07-reference-base44-api-export.md](./docs/07-reference-base44-api-export.md)**: The raw API documentation exported from Base44, used as a reference.
|
||||
- **[08-reference-base44-prompts.md](./docs/08-reference-base44-prompts.md)**: A collection of standardized prompts for interacting with the Base44 AI.
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
New to the KROW team? Start here to set up your environment and understand our development practices: **[CONTRIBUTING.md](./CONTRIBUTING.md)**
|
||||
### 📂 Support Directories
|
||||
- **`/docs`**: Project vision, technical specifications, and guides.
|
||||
- **`/makefiles`**: Modularized `Makefile` logic for project automation.
|
||||
- **`/scripts`**: Automation scripts (security, hachage, environment setup).
|
||||
- **`/firebase`**: Global Firebase configuration (Firestore/Storage rules).
|
||||
|
||||
## 🛠️ Tech Stack
|
||||
|
||||
- **Frontend:** React with Vite (JavaScript)
|
||||
- **Styling:** Tailwind CSS
|
||||
- **Backend:** Firebase (Firestore, Cloud Storage, Authentication, Data Connect)
|
||||
- **Mobile:** Flutter (planned)
|
||||
- **Frontend:** React (Vite)
|
||||
- **Mobile:** Flutter
|
||||
- **Backend:** Firebase (Data Connect, Auth, Hosting, Functions)
|
||||
- **Database:** PostgreSQL (managed via Cloud SQL & Data Connect)
|
||||
- **Infrastructure:** Google Cloud Platform (GCP)
|
||||
|
||||
## 📦 Getting Started
|
||||
|
||||
1. **Clone the repository:**
|
||||
This project uses a modular `Makefile` for all common tasks.
|
||||
|
||||
1. **View available commands:**
|
||||
```bash
|
||||
git clone https://github.com/Oloodi/krow.git
|
||||
cd krow
|
||||
make help
|
||||
```
|
||||
|
||||
2. **Install dependencies for the main web app:**
|
||||
2. **Install dependencies (Web):**
|
||||
```bash
|
||||
cd frontend-web
|
||||
npm install
|
||||
make install
|
||||
```
|
||||
|
||||
3. **Run the development server:**
|
||||
3. **Run the Web Dashboard locally:**
|
||||
```bash
|
||||
npm run dev
|
||||
make dev
|
||||
```
|
||||
|
||||
The main application will be available at `http://localhost:5173`. For other packages, refer to their respective `README.md` files.
|
||||
4. **Run the DevOps Launchpad locally:**
|
||||
```bash
|
||||
make launchpad-dev
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
- **[00-vision.md](./docs/00-vision.md)**: Project objectives and guiding principles.
|
||||
- **[01-backend-api-specification.md](./docs/01-backend-api-specification.md)**: (Legacy) Reference for data schemas.
|
||||
- **[02-codemagic-env-vars.md](./docs/02-codemagic-env-vars.md)**: Guide for CI/CD environment variables.
|
||||
- **[03-contributing.md](./docs/03-contributing.md)**: Guidelines for new developers and setup checklist.
|
||||
- **[04-sync-prototypes.md](./docs/04-sync-prototypes.md)**: How to sync prototypes for local dev and AI context.
|
||||
|
||||
## 🤝 Contributing
|
||||
New to the team? Please read our **[Contributing Guide](./docs/03-contributing.md)** to get your environment set up and understand our workflow.
|
||||
|
||||
---
|
||||
© 2026 KROW Workforce / Oloodi Technologies Inc.
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# This file specifies files that are *not* uploaded to Google Cloud
|
||||
# using gcloud. It follows the same syntax as .gitignore, with the addition of
|
||||
# "#!include" directives (which insert the entries of the given .gitignore-style
|
||||
# file at that point).
|
||||
#
|
||||
# For more information, run:
|
||||
# $ gcloud topic gcloudignore
|
||||
#
|
||||
.gcloudignore
|
||||
# If you would like to upload your .git directory, .gitignore file or files
|
||||
# from your .gitignore file, remove the corresponding line
|
||||
# below:
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# Node.js dependencies:
|
||||
node_modules/
|
||||
24
admin-web/.gitignore
vendored
24
admin-web/.gitignore
vendored
@@ -1,24 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
@@ -1,29 +0,0 @@
|
||||
# STAGE 1: Build the React application
|
||||
FROM node:20-alpine AS build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files and install dependencies
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm install
|
||||
|
||||
# Copy the rest of the application source code
|
||||
COPY . .
|
||||
|
||||
# Build the application for production
|
||||
RUN npm run build
|
||||
|
||||
# STAGE 2: Serve the static files with Nginx
|
||||
FROM nginx:alpine
|
||||
|
||||
# Copy the built files from the build stage
|
||||
COPY --from=build /app/dist /usr/share/nginx/html
|
||||
|
||||
# Copy the custom Nginx configuration
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
# Expose the port Nginx is listening on
|
||||
EXPOSE 8080
|
||||
|
||||
# Command to run Nginx in the foreground
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -1,35 +0,0 @@
|
||||
# Krow Admin Console
|
||||
|
||||
This is the central administration web application for the Krow platform, built with React and Vite.
|
||||
|
||||
## Overview
|
||||
|
||||
The Krow Admin Console provides a secure and centralized interface for platform administrators to perform high-level management tasks. Its primary functions are:
|
||||
|
||||
- **User Ecosystem Management:** Invite, view, and manage access for all users across the platform (Clients, Operators, Vendors, etc.).
|
||||
- **Platform Health Monitoring:** Get a high-level overview of system activity, usage, and performance.
|
||||
- **Diagnostics and Troubleshooting:** Access system logs for maintenance and issue resolution.
|
||||
|
||||
## Features
|
||||
|
||||
- **Dashboard:** A central hub displaying key platform metrics like total users, active vendors, and pending invitations.
|
||||
- **User Management:** A complete interface to invite new users and manage existing ones, including role assignments.
|
||||
- **Analytics:** A view of application usage statistics, such as top users and most visited pages.
|
||||
- **Logs Explorer:** A simple tool to monitor and filter system logs for diagnostics.
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Navigate to the `admin-web` directory:
|
||||
```bash
|
||||
cd admin-web
|
||||
```
|
||||
2. Install the dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
3. Start the development server:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The application will be available at `http://localhost:5173/admin-web/`.
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": false,
|
||||
"tsx": false,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.js",
|
||||
"css": "src/index.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
# List of authorized users for the Admin Console
|
||||
# Format: one email per line, lines starting with # are comments
|
||||
#
|
||||
# IMPORTANT: These users must belong to the 'krowwithus.com' organization.
|
||||
# This is a known limitation of enabling IAP directly on Cloud Run.
|
||||
# See: https://docs.cloud.google.com/run/docs/securing/identity-aware-proxy-cloud-run#known_limitations
|
||||
|
||||
user:admin@krowwithus.com
|
||||
@@ -1,13 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>KROW Admin Console</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
},
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src/**/*.js", "src/**/*.jsx"]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name _;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
# First attempt to serve request as file, then
|
||||
# as directory, then fall back to displaying a 404.
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
}
|
||||
4967
admin-web/package-lock.json
generated
4967
admin-web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
||||
{
|
||||
"name": "admin-web",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-slot": "^1.2.4",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.553.0",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-router-dom": "^7.9.6",
|
||||
"tailwind-merge": "^3.4.0",
|
||||
"tailwindcss-animate": "^1.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@types/react": "^19.2.2",
|
||||
"@types/react-dom": "^19.2.2",
|
||||
"@vitejs/plugin-react": "^5.1.0",
|
||||
"autoprefixer": "^10.4.22",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-react-hooks": "^7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.24",
|
||||
"globals": "^16.5.0",
|
||||
"postcss": "^8.5.6",
|
||||
"tailwindcss": "^3.4.18",
|
||||
"vite": "^7.2.2"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import React from "react";
|
||||
import Layout from "./pages/Layout";
|
||||
import Dashboard from "./pages/Dashboard";
|
||||
import UserManagement from "./pages/UserManagement";
|
||||
import Analytics from "./pages/Analytics";
|
||||
import Logs from "./pages/Logs";
|
||||
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Router>
|
||||
<Layout>
|
||||
<Routes>
|
||||
<Route path="/admin-web/" element={<Dashboard />} />
|
||||
<Route path="/admin-web/user-management" element={<UserManagement />} />
|
||||
<Route path="/admin-web/analytics" element={<Analytics />} />
|
||||
<Route path="/admin-web/logs" element={<Logs />} />
|
||||
</Routes>
|
||||
</Layout>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
@@ -1,58 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 0 0% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 0 0% 3.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 0 0% 3.9%;
|
||||
--primary: 0 0% 9%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
--secondary: 0 0% 96.1%;
|
||||
--secondary-foreground: 0 0% 9%;
|
||||
--muted: 0 0% 96.1%;
|
||||
--muted-foreground: 0 0% 45.1%;
|
||||
--accent: 0 0% 96.1%;
|
||||
--accent-foreground: 0 0% 9%;
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 89.8%;
|
||||
--input: 0 0% 89.8%;
|
||||
--ring: 0 0% 3.9%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
.dark {
|
||||
--background: 0 0% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 0 0% 3.9%;
|
||||
--card-foreground: 0 0% 98%;
|
||||
--popover: 0 0% 3.9%;
|
||||
--popover-foreground: 0 0% 98%;
|
||||
--primary: 0 0% 98%;
|
||||
--primary-foreground: 0 0% 9%;
|
||||
--secondary: 0 0% 14.9%;
|
||||
--secondary-foreground: 0 0% 98%;
|
||||
--muted: 0 0% 14.9%;
|
||||
--muted-foreground: 0 0% 63.9%;
|
||||
--accent: 0 0% 14.9%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
--border: 0 0% 14.9%;
|
||||
--input: 0 0% 14.9%;
|
||||
--ring: 0 0% 83.1%;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
import { clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.jsx'
|
||||
import './index.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
@@ -1,61 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
const topUsers = [
|
||||
{ email: "ian.gomez@example.com", visits: 6950 },
|
||||
{ email: "admin@krow.com", visits: 193 },
|
||||
{ email: "paula.orte@example.com", visits: 81 },
|
||||
{ email: "test.user@example.com", visits: 50 },
|
||||
];
|
||||
|
||||
const topPages = [
|
||||
{ name: "VendorManagement", visits: 718 },
|
||||
{ name: "Dashboard", visits: 600 },
|
||||
{ name: "unknown", visits: 587 },
|
||||
{ name: "ClientDashboard", visits: 475 },
|
||||
{ name: "Events", visits: 456 },
|
||||
];
|
||||
|
||||
export default function Analytics() {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-slate-800">Analytics</h1>
|
||||
<p className="mt-2 text-base text-slate-600">
|
||||
An overview of your application's data.
|
||||
</p>
|
||||
|
||||
<div className="mt-8">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<div className="bg-white shadow-lg rounded-2xl p-6">
|
||||
<h3 className="text-lg font-medium text-gray-900">Total Unique Users</h3>
|
||||
<p className="mt-2 text-4xl font-bold text-blue-600">3</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900">Top Users</h3>
|
||||
<ul className="mt-4 space-y-4">
|
||||
{topUsers.map((user) => (
|
||||
<li key={user.email} className="bg-white shadow-lg rounded-2xl p-4">
|
||||
<p className="font-semibold text-slate-800">{user.email}</p>
|
||||
<p className="text-slate-500">{user.visits.toLocaleString()} visits</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold text-gray-900">Top Pages</h3>
|
||||
<ul className="mt-4 space-y-4">
|
||||
{topPages.map((page) => (
|
||||
<li key={page.name} className="bg-white shadow-lg rounded-2xl p-4 flex justify-between items-center">
|
||||
<p className="font-semibold text-slate-800">{page.name}</p>
|
||||
<p className="text-slate-500 font-medium">{page.visits.toLocaleString()}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
import React from "react";
|
||||
import { Users, Building2, Mail, FileText } from "lucide-react";
|
||||
|
||||
const stats = [
|
||||
{ name: "Total Users", stat: "15", icon: Users, color: "bg-blue-500" },
|
||||
{ name: "Active Vendors", stat: "8", icon: Building2, color: "bg-green-500" },
|
||||
{ name: "Pending Invitations", stat: "3", icon: Mail, color: "bg-yellow-500" },
|
||||
{ name: "Open Orders", stat: "12", icon: FileText, color: "bg-purple-500" },
|
||||
];
|
||||
|
||||
export default function Dashboard() {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-slate-800">Admin Dashboard</h1>
|
||||
<p className="mt-2 text-base text-slate-600">
|
||||
Welcome to the Krow Admin Console. Here is a quick overview of the platform.
|
||||
</p>
|
||||
|
||||
<div className="mt-8">
|
||||
<dl className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{stats.map((item) => (
|
||||
<div key={item.name} className="relative overflow-hidden rounded-2xl bg-white px-4 py-5 shadow-lg sm:px-6 sm:py-6">
|
||||
<dt>
|
||||
<div className={`absolute rounded-xl p-3 ${item.color}`}>
|
||||
<item.icon className="h-8 w-8 text-white" aria-hidden="true" />
|
||||
</div>
|
||||
<p className="ml-20 truncate text-sm font-medium text-gray-500">{item.name}</p>
|
||||
</dt>
|
||||
<dd className="ml-20 flex items-baseline">
|
||||
<p className="text-3xl font-semibold text-gray-900">{item.stat}</p>
|
||||
</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
import React from "react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import { Building2, Users, BarChart3, Terminal, LayoutDashboard, LogOut } from "lucide-react";
|
||||
|
||||
const navigation = [
|
||||
{ name: "Dashboard", href: "/admin-web/", icon: LayoutDashboard },
|
||||
{ name: "User Management", href: "/admin-web/user-management", icon: Users },
|
||||
{ name: "Analytics", href: "/admin-web/analytics", icon: BarChart3 },
|
||||
{ name: "Logs Explorer", href: "/admin-web/logs", icon: Terminal },
|
||||
];
|
||||
|
||||
export default function Layout({ children }) {
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-slate-50">
|
||||
{/* Sidebar */}
|
||||
<div className="hidden md:flex md:flex-shrink-0">
|
||||
<div className="flex flex-col w-64">
|
||||
{/* Sidebar header */}
|
||||
<div className="flex items-center h-16 flex-shrink-0 px-4 bg-white border-b border-slate-200">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="w-8 h-8 rounded-lg flex items-center justify-center">
|
||||
<img src="/logo.svg" alt="Krow Logo" className="h-full w-full" />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-lg font-bold text-slate-800">KROW</h1>
|
||||
<p className="text-xs text-slate-500">Admin Console</p>
|
||||
</div>
|
||||
</div>
|
||||
{import.meta.env.VITE_APP_ENV && (
|
||||
<span className={`ml-auto inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
|
||||
import.meta.env.VITE_APP_ENV === 'staging' ? 'bg-amber-100 text-amber-800' : 'bg-blue-100 text-blue-800'
|
||||
}`}>
|
||||
{import.meta.env.VITE_APP_ENV === 'staging' ? 'Staging' : 'Dev'}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{/* Sidebar content */}
|
||||
<div className="flex-1 flex flex-col overflow-y-auto bg-white">
|
||||
<nav className="flex-1 px-4 py-4">
|
||||
{navigation.map((item) => (
|
||||
<Link
|
||||
key={item.name}
|
||||
to={item.href}
|
||||
className={`
|
||||
${
|
||||
location.pathname === item.href
|
||||
? "bg-blue-50 text-blue-600"
|
||||
: "text-slate-600 hover:bg-slate-100 hover:text-slate-900"
|
||||
}
|
||||
group flex items-center px-3 py-3 text-sm font-medium rounded-lg
|
||||
`}
|
||||
>
|
||||
<item.icon
|
||||
className="mr-3 h-6 w-6"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{item.name}
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
<div className="px-4 py-4 border-t border-slate-200">
|
||||
<Link
|
||||
to="#"
|
||||
className="group flex items-center px-3 py-3 text-sm font-medium rounded-lg text-slate-600 hover:bg-slate-100 hover:text-slate-900"
|
||||
>
|
||||
<LogOut className="mr-3 h-6 w-6" />
|
||||
Logout
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main content */}
|
||||
<div className="flex flex-col w-0 flex-1 overflow-hidden">
|
||||
<main className="flex-1 relative z-0 overflow-y-auto focus:outline-none">
|
||||
<div className="py-8">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
const logs = [
|
||||
{ level: "INFO", message: "User admin@krow.com logged in.", timestamp: "2024-05-21T10:00:00Z" },
|
||||
{ level: "WARN", message: "API response time is slow: 2500ms for /api/vendors", timestamp: "2024-05-21T10:01:00Z" },
|
||||
{ level: "ERROR", message: "Failed to process payment for invoice INV-12345.", timestamp: "2024-05-21T10:02:00Z" },
|
||||
{ level: "INFO", message: "New vendor 'New Staffing Co' invited by admin@krow.com.", timestamp: "2024-05-21T10:05:00Z" },
|
||||
];
|
||||
|
||||
export default function Logs() {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-slate-800">Logs Explorer</h1>
|
||||
<p className="mt-2 text-base text-slate-600">
|
||||
Monitor system logs across your application.
|
||||
</p>
|
||||
|
||||
<div className="mt-8 flow-root">
|
||||
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
||||
<div className="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-2xl">
|
||||
<table className="min-w-full divide-y divide-gray-300">
|
||||
<thead className="bg-slate-50">
|
||||
<tr>
|
||||
<th scope="col" className="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Level</th>
|
||||
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Message</th>
|
||||
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Timestamp</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200 bg-white">
|
||||
{logs.map((log, index) => (
|
||||
<tr key={index}>
|
||||
<td className="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6">
|
||||
<span className={`inline-flex items-center px-3 py-1 rounded-full text-xs font-medium ${
|
||||
log.level === 'ERROR' ? 'bg-red-100 text-red-800' :
|
||||
log.level === 'WARN' ? 'bg-yellow-100 text-yellow-800' :
|
||||
'bg-green-100 text-green-800'
|
||||
}`}>
|
||||
{log.level}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-3 py-4 text-sm text-gray-500 font-mono">{log.message}</td>
|
||||
<td className="px-3 py-4 text-sm text-gray-500">{new Date(log.timestamp).toLocaleString()}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { Plus, Send } from "lucide-react";
|
||||
|
||||
const users = [
|
||||
{ name: "Alex Johnson", email: "alex.j@krow.com", role: "Admin", status: "Active", avatar: "https://randomuser.me/api/portraits/men/1.jpg" },
|
||||
{ name: "Samantha Lee", email: "samantha.lee@vendor.com", role: "Vendor", status: "Active", avatar: "https://randomuser.me/api/portraits/women/2.jpg" },
|
||||
{ name: "Michael Chen", email: "michael.chen@client.com", role: "Client", status: "Pending", avatar: "https://randomuser.me/api/portraits/men/3.jpg" },
|
||||
];
|
||||
|
||||
function InviteUserModal({ isOpen, onClose }) {
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity">
|
||||
<div className="fixed inset-0 z-10 w-screen overflow-y-auto">
|
||||
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
||||
<div className="relative transform overflow-hidden rounded-2xl bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg">
|
||||
<div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<h3 className="text-xl font-semibold leading-6 text-slate-900">Send Invitation</h3>
|
||||
<p className="mt-2 text-sm text-slate-500">The user will receive an email with a link to set up their account.</p>
|
||||
<div className="mt-6 space-y-4">
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium text-gray-700">
|
||||
Email address
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
name="email"
|
||||
id="email"
|
||||
className="mt-2 block w-full rounded-lg border-0 py-2.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
placeholder="colleague@company.com"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="role" className="block text-sm font-medium text-gray-700">
|
||||
Access level
|
||||
</label>
|
||||
<select
|
||||
id="role"
|
||||
name="role"
|
||||
className="mt-2 block w-full rounded-lg border-0 py-2.5 pl-3 pr-10 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-blue-600 sm:text-sm sm:leading-6"
|
||||
defaultValue="User"
|
||||
>
|
||||
<option>Admin</option>
|
||||
<option>Vendor</option>
|
||||
<option>Client</option>
|
||||
<option>User</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-slate-50 px-4 py-3 sm:flex sm:flex-row-reverse sm:px-6">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex w-full items-center justify-center rounded-lg bg-blue-600 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 sm:ml-3 sm:w-auto"
|
||||
onClick={onClose}
|
||||
>
|
||||
<Send className="h-5 w-5 mr-2" />
|
||||
Send Invitation
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="mt-3 inline-flex w-full justify-center rounded-lg bg-white px-4 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto"
|
||||
onClick={onClose}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function UserManagement() {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="sm:flex sm:items-center">
|
||||
<div className="sm:flex-auto">
|
||||
<h1 className="text-3xl font-bold text-slate-800">User Management</h1>
|
||||
<p className="mt-2 text-base text-slate-600">
|
||||
A list of all the users in your account including their name, email and role.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center rounded-lg border border-transparent bg-blue-600 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 sm:w-auto"
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
>
|
||||
<Plus className="h-5 w-5 mr-2" />
|
||||
Invite User
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 flow-root">
|
||||
<div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div className="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
||||
<div className="overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:rounded-2xl">
|
||||
<table className="min-w-full divide-y divide-gray-300">
|
||||
<thead className="bg-slate-50">
|
||||
<tr>
|
||||
<th scope="col" className="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Name</th>
|
||||
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Email</th>
|
||||
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Role</th>
|
||||
<th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-gray-200 bg-white">
|
||||
{users.map((user) => (
|
||||
<tr key={user.email}>
|
||||
<td className="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||
<div className="flex items-center">
|
||||
<div className="h-11 w-11 flex-shrink-0">
|
||||
<img className="h-11 w-11 rounded-full" src={user.avatar} alt="" />
|
||||
</div>
|
||||
<div className="ml-4">
|
||||
<div className="font-medium text-gray-900">{user.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{user.email}</td>
|
||||
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{user.role}</td>
|
||||
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${
|
||||
user.status === 'Active' ? 'bg-green-100 text-green-800' : 'bg-yellow-100 text-yellow-800'
|
||||
}`}>
|
||||
{user.status}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<InviteUserModal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
darkMode: ["class"],
|
||||
content: ["./index.html", "./src/**/*.{ts,tsx,js,jsx}"],
|
||||
theme: {
|
||||
extend: {
|
||||
borderRadius: {
|
||||
lg: 'var(--radius)',
|
||||
md: 'calc(var(--radius) - 2px)',
|
||||
sm: 'calc(var(--radius) - 4px)'
|
||||
},
|
||||
colors: {
|
||||
background: 'hsl(var(--background))',
|
||||
foreground: 'hsl(var(--foreground))',
|
||||
card: {
|
||||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))'
|
||||
},
|
||||
popover: {
|
||||
DEFAULT: 'hsl(var(--popover))',
|
||||
foreground: 'hsl(var(--popover-foreground))'
|
||||
},
|
||||
primary: {
|
||||
DEFAULT: 'hsl(var(--primary))',
|
||||
foreground: 'hsl(var(--primary-foreground))'
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: 'hsl(var(--secondary))',
|
||||
foreground: 'hsl(var(--secondary-foreground))'
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: 'hsl(var(--muted))',
|
||||
foreground: 'hsl(var(--muted-foreground))'
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: 'hsl(var(--accent))',
|
||||
foreground: 'hsl(var(--accent-foreground))'
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: 'hsl(var(--destructive))',
|
||||
foreground: 'hsl(var(--destructive-foreground))'
|
||||
},
|
||||
border: 'hsl(var(--border))',
|
||||
input: 'hsl(var(--input))',
|
||||
ring: 'hsl(var(--ring))',
|
||||
chart: {
|
||||
'1': 'hsl(var(--chart-1))',
|
||||
'2': 'hsl(var(--chart-2))',
|
||||
'3': 'hsl(var(--chart-3))',
|
||||
'4': 'hsl(var(--chart-4))',
|
||||
'5': 'hsl(var(--chart-5))'
|
||||
},
|
||||
sidebar: {
|
||||
DEFAULT: 'hsl(var(--sidebar-background))',
|
||||
foreground: 'hsl(var(--sidebar-foreground))',
|
||||
primary: 'hsl(var(--sidebar-primary))',
|
||||
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
|
||||
accent: 'hsl(var(--sidebar-accent))',
|
||||
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
|
||||
border: 'hsl(var(--sidebar-border))',
|
||||
ring: 'hsl(var(--sidebar-ring))'
|
||||
}
|
||||
},
|
||||
keyframes: {
|
||||
'accordion-down': {
|
||||
from: {
|
||||
height: '0'
|
||||
},
|
||||
to: {
|
||||
height: 'var(--radix-accordion-content-height)'
|
||||
}
|
||||
},
|
||||
'accordion-up': {
|
||||
from: {
|
||||
height: 'var(--radix-accordion-content-height)'
|
||||
},
|
||||
to: {
|
||||
height: '0'
|
||||
}
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||
'accordion-up': 'accordion-up 0.2s ease-out'
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [require("tailwindcss-animate")],
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import path from 'path'
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
})
|
||||
1
apps/mobile-staff/.keep
Normal file
1
apps/mobile-staff/.keep
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
141
build.gradle
141
build.gradle
@@ -1,141 +0,0 @@
|
||||
plugins {
|
||||
id "com.android.application"
|
||||
// START: FlutterFire Configuration
|
||||
id 'com.google.gms.google-services'
|
||||
id 'com.google.firebase.crashlytics'
|
||||
// END: FlutterFire Configuration
|
||||
id "kotlin-android"
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id "dev.flutter.flutter-gradle-plugin"
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.example.troywallet"
|
||||
compileSdk = 36
|
||||
ndkVersion = "25.1.8937393"
|
||||
//ndkVersion = flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
coreLibraryDesugaringEnabled true
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.example.troywallet"
|
||||
namespace("com.example.troywallet")
|
||||
minSdk = 29
|
||||
targetSdk = 35
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
multiDexEnabled true
|
||||
|
||||
}
|
||||
|
||||
// KeyStore //////////////////////////////////////////////////
|
||||
// - kast.keystore..alias android..pw=android..pw=android
|
||||
def keystorePropertiesFileNameDev = 'kast_key_dev.properties'
|
||||
def keystorePropertiesDev = new Properties()
|
||||
keystorePropertiesDev.load(new FileInputStream(rootProject.file(keystorePropertiesFileNameDev)))
|
||||
|
||||
def keystorePropertiesFileNameUat = 'kast_key_uat.properties'
|
||||
def keystorePropertiesUat = new Properties()
|
||||
keystorePropertiesUat.load(new FileInputStream(rootProject.file(keystorePropertiesFileNameUat)))
|
||||
|
||||
def keystorePropertiesFileNameStaging = 'kast_key_staging.properties'
|
||||
def keystorePropertiesStaging = new Properties()
|
||||
keystorePropertiesStaging.load(new FileInputStream(rootProject.file(keystorePropertiesFileNameStaging)))
|
||||
|
||||
def keystorePropertiesFileNameProd = 'kast_key_prod.properties'
|
||||
def keystorePropertiesProd = new Properties()
|
||||
keystorePropertiesProd.load(new FileInputStream(rootProject.file(keystorePropertiesFileNameProd)))
|
||||
|
||||
|
||||
signingConfigs {
|
||||
configDev {
|
||||
keyAlias keystorePropertiesDev['keyAlias']
|
||||
keyPassword keystorePropertiesDev['keyPassword']
|
||||
storeFile file('../kast_android_dev.jks') //keystorePropertiesSit['storeFile']
|
||||
storePassword keystorePropertiesDev['storePassword']
|
||||
}
|
||||
configUat {
|
||||
keyAlias keystorePropertiesUat['keyAlias']
|
||||
keyPassword keystorePropertiesUat['keyPassword']
|
||||
storeFile file('../kast_android_uat.jks') //keystorePropertiesPat['storeFile']
|
||||
storePassword keystorePropertiesUat['storePassword']
|
||||
}
|
||||
|
||||
configStaging {
|
||||
keyAlias keystorePropertiesStaging['keyAlias']
|
||||
keyPassword keystorePropertiesStaging['keyPassword']
|
||||
storeFile file('../kast_android_staging.jks') //keystorePropertiesPat['storeFile']
|
||||
storePassword keystorePropertiesStaging['storePassword']
|
||||
}
|
||||
configProd {
|
||||
keyAlias keystorePropertiesProd['keyAlias']
|
||||
keyPassword keystorePropertiesProd['keyPassword']
|
||||
storeFile file('../kast_android_prod.jks')
|
||||
storePassword keystorePropertiesProd['storePassword']
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions "default"
|
||||
productFlavors {
|
||||
dev {
|
||||
dimension "default"
|
||||
applicationId "dev.kastcard.com"
|
||||
resValue "string", "app_name", "KAST DEV"
|
||||
resValue "string", "deeplink_prefix", "/dls"
|
||||
resValue "drawable", "ic_launcher", "@mipmap/ic_launcher_dev"
|
||||
signingConfig signingConfigs.configDev
|
||||
}
|
||||
uat {
|
||||
dimension "default"
|
||||
applicationId "uat.kastcard.com"
|
||||
resValue "string", "app_name", "KAST UAT"
|
||||
resValue "string", "deeplink_prefix", "/dlp"
|
||||
resValue "drawable", "ic_launcher", "@mipmap/ic_launcher_uat"
|
||||
signingConfig signingConfigs.configUat
|
||||
}
|
||||
staging {
|
||||
dimension "default"
|
||||
applicationId "stg.kastcard.com"
|
||||
resValue "string", "app_name", "KAST Staging"
|
||||
resValue "string", "deeplink_prefix", "/dlp"
|
||||
resValue "drawable", "ic_launcher", "@mipmap/ic_launcher_staging"
|
||||
signingConfig signingConfigs.configStaging
|
||||
}
|
||||
prod {
|
||||
dimension "default"
|
||||
applicationId "com.kastfinance.app"
|
||||
resValue "string", "app_name", "KAST"
|
||||
resValue "string", "deeplink_prefix", "/dlp"
|
||||
resValue "drawable", "ic_launcher", "@mipmap/ic_launcher_prod"
|
||||
signingConfig signingConfigs.configProd
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
shrinkResources false
|
||||
minifyEnabled false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "com.sumsub.sns:idensic-mobile-sdk-videoident:1.33.1"
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
|
||||
implementation(files("libs/mdisdk-release-1.2.54.aar"))
|
||||
}
|
||||
@@ -47,7 +47,7 @@ workflows:
|
||||
# =================================================================================
|
||||
client-app-base: &client-app-base
|
||||
name: Client App Base
|
||||
working_directory: mobile-apps/client-app
|
||||
working_directory: apps/mobile-client
|
||||
instance_type: mac_mini_m2
|
||||
max_build_duration: 60
|
||||
environment:
|
||||
@@ -57,15 +57,15 @@ workflows:
|
||||
cache:
|
||||
cache_paths:
|
||||
- $HOME/.pub-cache
|
||||
- $FCI_BUILD_DIR/mobile-apps/client-app/build
|
||||
- $FCI_BUILD_DIR/mobile-apps/client-app/.dart_tool
|
||||
- $FCI_BUILD_DIR/apps/mobile-client/build
|
||||
- $FCI_BUILD_DIR/apps/mobile-client/.dart_tool
|
||||
|
||||
# =================================================================================
|
||||
# Base workflow for staff_app
|
||||
# =================================================================================
|
||||
staff-app-base: &staff-app-base
|
||||
name: Staff App Base
|
||||
working_directory: mobile-apps/staff-app
|
||||
working_directory: apps/mobile-staff
|
||||
instance_type: mac_mini_m2
|
||||
max_build_duration: 60
|
||||
environment:
|
||||
@@ -75,8 +75,8 @@ workflows:
|
||||
cache:
|
||||
cache_paths:
|
||||
- $HOME/.pub-cache
|
||||
- $FCI_BUILD_DIR/mobile-apps/staff-app/build
|
||||
- $FCI_BUILD_DIR/mobile-apps/staff-app/.dart_tool
|
||||
- $FCI_BUILD_DIR/apps/mobile-staff/build
|
||||
- $FCI_BUILD_DIR/apps/mobile-staff/.dart_tool
|
||||
|
||||
# =================================================================================
|
||||
# Client App Workflows - Android
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
# DataConnect – Inconsistencies between the Base44 frontend and the backend (Firebase Data Connect + PostgreSQL)
|
||||
**Author:** José Salazar
|
||||
**Date:** Dec 2025
|
||||
|
||||
---
|
||||
|
||||
## 📌 Purpose of this document
|
||||
|
||||
Document all findings during the integration of the new backend
|
||||
(**Firebase Data Connect + PostgreSQL**) with the frontend generated by **Base44 AI**.
|
||||
|
||||
This document summarizes:
|
||||
|
||||
- Issues found
|
||||
- camelCase vs snake_case inconsistencies
|
||||
- Enum inconsistencies (uppercase/lowercase and dashes)
|
||||
- Differences between what DataConnect returns vs what the frontend expects
|
||||
- Recommended fixes
|
||||
- Suggestions for Base44 AI to update its model
|
||||
- Impact on queries, mutations, and the generated SDK
|
||||
|
||||
---
|
||||
|
||||
## 1️⃣ Enums – Different formats between Front and Backend
|
||||
|
||||
### Observation
|
||||
|
||||
In the frontend, enum values are in mixed formats, for example:
|
||||
|
||||
- UPPERCASE: SKILLED
|
||||
- camelCase: fullTime
|
||||
|
||||
In the backend (DataConnect schema), enums are defined only in UPPERCASE, for example:
|
||||
|
||||
- FULL_TIME
|
||||
- CROSS_TRAINED
|
||||
- NOT_REQUIRED
|
||||
- PENDING
|
||||
|
||||
DataConnect only accepts these exact values.
|
||||
|
||||
### Problem
|
||||
|
||||
When the frontend sends:
|
||||
|
||||
- "crossTrained" instead of CROSS_TRAINED
|
||||
- "fluent" instead of FLUENT
|
||||
|
||||
### Impact
|
||||
|
||||
- Mutations can fail or return enum validation errors.
|
||||
- Filters using enums return no results.
|
||||
- Behavior changes depending on how Base44 AI generated the object.
|
||||
|
||||
### Recommendation
|
||||
|
||||
- Define a single standard: **ALL enums must be UPPERCASE** on the frontend and backend.
|
||||
- Before sending to the backend, normalize enum values to uppercase.
|
||||
|
||||
### Suggestion for Base44 AI
|
||||
|
||||
- Adjust models so they always generate enums in UPPERCASE.
|
||||
|
||||
---
|
||||
|
||||
## 2️⃣ Enums with dashes (“-”) – Not valid in GraphQL
|
||||
|
||||
### Observation
|
||||
|
||||
In the legacy frontend, some enum values contain dashes, for example:
|
||||
|
||||
- CUSTOMER-SERVICE
|
||||
- CROSS-TRAINED
|
||||
- PART-TIME
|
||||
|
||||
But in GraphQL enums only allow letters, numbers, and underscores.
|
||||
The backend had to define them as:
|
||||
|
||||
- CUSTOMER_SERVICE
|
||||
- CROSS_TRAINED
|
||||
- PART_TIME
|
||||
|
||||
### Problem
|
||||
|
||||
When the frontend sends "CUSTOMER-SERVICE" or "CROSS-TRAINED":
|
||||
|
||||
- The backend expects CUSTOMER_SERVICE or CROSS_TRAINED.
|
||||
- There is no match between the frontend value and the DataConnect enum.
|
||||
|
||||
### Impact
|
||||
|
||||
- Enum filters return nothing.
|
||||
- Mutations fail when trying to save invalid enum values.
|
||||
- Compatibility between the Base44 model and the DataConnect schema breaks.
|
||||
|
||||
### Recommendation
|
||||
|
||||
- Standardize all enums to UPPERCASE SNAKE_CASE (e.g., CUSTOMER_SERVICE).
|
||||
- Never use dashes “-” in enum values.
|
||||
|
||||
### Suggestion for Base44 AI
|
||||
|
||||
- Update models so enum values are always generated as
|
||||
UPPERCASE_WITH_UNDERSCORE (e.g., CUSTOMER_SERVICE), without dashes.
|
||||
|
||||
---
|
||||
|
||||
## 3️⃣ Field names – Front in snake_case vs DataConnect in camelCase
|
||||
|
||||
### Observation
|
||||
|
||||
The original Base44 frontend uses snake_case field names, for example:
|
||||
|
||||
- contact_number
|
||||
- vendor_id
|
||||
- background_check_status
|
||||
- hub_location
|
||||
|
||||
In DataConnect the schema is camelCase, and although you can map to the actual PostgreSQL column using @col, the GraphQL type remains camelCase, for example:
|
||||
|
||||
- contactNumber (mapped to "contact_number" in Postgres)
|
||||
- vendorId (mapped to "vendor_id")
|
||||
- backgroundCheckStatus (mapped to "background_check_status")
|
||||
- hubLocation (mapped to "hub_location")
|
||||
|
||||
Meaning:
|
||||
|
||||
- In the database (PostgreSQL) names remain snake_case.
|
||||
- In DataConnect and the SDK they are exposed as camelCase.
|
||||
|
||||
### Problem
|
||||
|
||||
The frontend still expects/reads fields like contact_number, but the SDK returns contactNumber.
|
||||
A similar issue happens when the frontend sends payloads in snake_case:
|
||||
|
||||
- The GraphQL schema does not recognize contact_number.
|
||||
- It only accepts contactNumber.
|
||||
|
||||
### Impact
|
||||
|
||||
- UI fails to show data because it reads keys that don’t exist (snake_case).
|
||||
- Mutations fail or ignore fields due to mismatched names.
|
||||
- Filters with snake_case are invalid in GraphQL.
|
||||
|
||||
### Recommendation
|
||||
|
||||
- Agree that **all communication with DataConnect (frontend + SDK) uses camelCase**.
|
||||
- Keep snake_case only at PostgreSQL level using @col, for example:
|
||||
|
||||
employeeName: String @col(name: "employee_name")
|
||||
|
||||
Thus:
|
||||
|
||||
- Frontend / SDK / GraphQL → camelCase (employeeName)
|
||||
- PostgreSQL → snake_case (employee_name)
|
||||
|
||||
### Suggestion for Base44 AI
|
||||
|
||||
- Adjust generated frontend code so it uses camelCase when consuming the new backend.
|
||||
- If Supabase or another backend is still used, document all mappings clearly.
|
||||
|
||||
---
|
||||
|
||||
## 4️⃣ Fields used by the frontend but not listed in API Spec v3
|
||||
|
||||
### Observation
|
||||
|
||||
During integration we found that Base44 frontend uses fields not defined in the official document:
|
||||
|
||||
Reference file:
|
||||
docs/03-backend-api-specification-v3.md
|
||||
|
||||
Examples in the Staff entity:
|
||||
|
||||
The frontend sends and displays fields like:
|
||||
|
||||
- notes
|
||||
- rate
|
||||
|
||||
But these fields were not defined in the original v3 specification for Staff.
|
||||
|
||||
### Problem
|
||||
|
||||
- The frontend assumes these fields exist because the old database had them.
|
||||
- The DataConnect schema does not include them.
|
||||
- Sending these values in mutations causes validation errors.
|
||||
|
||||
### Impact
|
||||
|
||||
- Inconsistency between what the UI shows/edits and what is actually persisted.
|
||||
- Risk of losing data the user believes is being saved.
|
||||
- Hard to maintain a 1:1 mapping between the previous Base44 model and the new backend.
|
||||
|
||||
### Recommendation
|
||||
|
||||
- Validate which fields should truly exist for each entity (e.g., Staff).
|
||||
- Align these three items:
|
||||
1. API Spec v3
|
||||
2. DataConnect Schema
|
||||
3. Base44 Frontend
|
||||
|
||||
- If a field is no longer needed, remove it from the frontend.
|
||||
- If important, add it formally to the API Spec and to the DataConnect schema.
|
||||
|
||||
---
|
||||
|
||||
## 5️⃣ DataConnect vs Front – Observed behavior
|
||||
|
||||
1. DataConnect:
|
||||
- Always exposes fields in camelCase.
|
||||
- Enforces enum restrictions exactly as defined (UPPERCASE, no dashes).
|
||||
- Allows mapping to Postgres column names using @col, but GraphQL names remain camelCase.
|
||||
|
||||
2. Base44 Frontend:
|
||||
- Uses snake_case in many areas.
|
||||
- Uses enums in mixed formats (uppercase, camelCase, with dashes).
|
||||
- Contains extra fields not included in API Spec v3.
|
||||
|
||||
---
|
||||
|
||||
## 6️⃣ Suggested fixes (personal criteria)
|
||||
|
||||
1. Enums
|
||||
- Standardize to UPPERCASE_SNAKE_CASE for all enum values.
|
||||
- Apply a normalization layer in the frontend to convert any format into the official one before hitting the backend.
|
||||
|
||||
2. Field names
|
||||
- Migrate the frontend to camelCase for any interaction with DataConnect.
|
||||
- Keep snake_case only at the database layer using @col.
|
||||
|
||||
3. Extra fields
|
||||
- Review all fields the frontend sends and compare with API Spec v3.
|
||||
- Remove or add fields depending on what becomes the “source of truth” (Spec v3).
|
||||
|
||||
4. Documentation
|
||||
- Keep this file updated as the Base44 → DataConnect migration reference.
|
||||
- Add valid payload examples for each entity (Staff, Vendor, Invoice, etc.).
|
||||
|
||||
---
|
||||
|
||||
## 7️⃣ Summary
|
||||
|
||||
- Always generate:
|
||||
- Enums: UPPERCASE_SNAKE_CASE (e.g., FULL_TIME, CUSTOMER_SERVICE).
|
||||
- Fields: camelCase (e.g., contactNumber, hubLocation, backgroundCheckStatus).
|
||||
|
||||
- Avoid:
|
||||
- Dashes “-” in enum values.
|
||||
- Spaces in enum values.
|
||||
|
||||
---
|
||||
|
||||
This document captures the current findings and serves as a guide to fully align the Base44 frontend with the backend based on Firebase Data Connect + PostgreSQL.
|
||||
@@ -1,51 +0,0 @@
|
||||
mutation CreateActivityLog(
|
||||
$title: String!,
|
||||
$description: String!,
|
||||
$activityType: ActivityType!,
|
||||
$userId: String!,
|
||||
$isRead: Boolean,
|
||||
$iconType: String,
|
||||
$iconColor: String
|
||||
) @auth(level: USER) {
|
||||
activityLog_insert(
|
||||
data: {
|
||||
title: $title
|
||||
description: $description
|
||||
activityType: $activityType
|
||||
userId: $userId
|
||||
isRead: $isRead
|
||||
iconType: $iconType
|
||||
iconColor: $iconColor
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateActivityLog(
|
||||
$id: UUID!,
|
||||
$title: String,
|
||||
$description: String,
|
||||
$activityType: ActivityType,
|
||||
$userId: String,
|
||||
$isRead: Boolean,
|
||||
$iconType: String,
|
||||
$iconColor: String
|
||||
) @auth(level: USER) {
|
||||
activityLog_update(
|
||||
id: $id,
|
||||
data: {
|
||||
title: $title
|
||||
description: $description
|
||||
activityType: $activityType
|
||||
userId: $userId
|
||||
isRead: $isRead
|
||||
iconType: $iconType
|
||||
iconColor: $iconColor
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteActivityLog(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
activityLog_delete(id: $id)
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
query listActivityLog @auth(level: USER) {
|
||||
activityLogs {
|
||||
id
|
||||
title
|
||||
description
|
||||
activityType
|
||||
userId
|
||||
isRead
|
||||
iconType
|
||||
iconColor
|
||||
}
|
||||
}
|
||||
|
||||
query getActivityLogById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
activityLog(id: $id) {
|
||||
id
|
||||
title
|
||||
description
|
||||
activityType
|
||||
userId
|
||||
isRead
|
||||
iconType
|
||||
iconColor
|
||||
}
|
||||
}
|
||||
|
||||
query filterActivityLog(
|
||||
$userId: String,
|
||||
$activityType: ActivityType,
|
||||
$isRead: Boolean
|
||||
) @auth(level: USER) {
|
||||
activityLogs(
|
||||
where: {
|
||||
userId: { eq: $userId }
|
||||
activityType: { eq: $activityType }
|
||||
isRead: { eq: $isRead }
|
||||
}
|
||||
) {
|
||||
id
|
||||
title
|
||||
description
|
||||
activityType
|
||||
userId
|
||||
isRead
|
||||
iconType
|
||||
iconColor
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
mutation CreateAssignment(
|
||||
$assignmentNumber: String,
|
||||
$orderId: UUID!,
|
||||
$workforceId: UUID!,
|
||||
$vendorId: UUID!,
|
||||
$role: String!,
|
||||
$assignmentStatus: AssignmentStatus!,
|
||||
$scheduledStart: Timestamp!
|
||||
) @auth(level: USER) {
|
||||
assignment_insert(
|
||||
data: {
|
||||
assignmentNumber: $assignmentNumber
|
||||
orderId: $orderId
|
||||
workforceId: $workforceId
|
||||
vendorId: $vendorId
|
||||
role: $role
|
||||
assignmentStatus: $assignmentStatus
|
||||
scheduledStart: $scheduledStart
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateAssignment(
|
||||
$id: UUID!,
|
||||
$assignmentNumber: String,
|
||||
$orderId: UUID,
|
||||
$workforceId: UUID,
|
||||
$vendorId: UUID,
|
||||
$role: String,
|
||||
$assignmentStatus: AssignmentStatus,
|
||||
$scheduledStart: Timestamp
|
||||
) @auth(level: USER) {
|
||||
assignment_update(
|
||||
id: $id,
|
||||
data: {
|
||||
assignmentNumber: $assignmentNumber
|
||||
orderId: $orderId
|
||||
workforceId: $workforceId
|
||||
vendorId: $vendorId
|
||||
role: $role
|
||||
assignmentStatus: $assignmentStatus
|
||||
scheduledStart: $scheduledStart
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteAssignment(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
assignment_delete(id: $id)
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
# dataconnect/connector/assignment/queries.gql
|
||||
|
||||
query listAssignment @auth(level: USER) {
|
||||
assignments {
|
||||
id
|
||||
assignmentNumber
|
||||
orderId
|
||||
workforceId
|
||||
vendorId
|
||||
role
|
||||
assignmentStatus
|
||||
scheduledStart
|
||||
}
|
||||
}
|
||||
|
||||
query getAssignmentById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
assignment(id: $id) {
|
||||
id
|
||||
assignmentNumber
|
||||
orderId
|
||||
workforceId
|
||||
vendorId
|
||||
role
|
||||
assignmentStatus
|
||||
scheduledStart
|
||||
}
|
||||
}
|
||||
|
||||
query filterAssignment(
|
||||
$assignmentNumber: String,
|
||||
$orderId: UUID,
|
||||
$workforceId: UUID,
|
||||
$vendorId: UUID,
|
||||
$assignmentStatus: AssignmentStatus
|
||||
) @auth(level: USER) {
|
||||
assignments(
|
||||
where: {
|
||||
assignmentNumber: { eq: $assignmentNumber }
|
||||
orderId: { eq: $orderId }
|
||||
workforceId: { eq: $workforceId }
|
||||
vendorId: { eq: $vendorId }
|
||||
assignmentStatus: { eq: $assignmentStatus }
|
||||
}
|
||||
) {
|
||||
id
|
||||
assignmentNumber
|
||||
orderId
|
||||
workforceId
|
||||
vendorId
|
||||
role
|
||||
assignmentStatus
|
||||
scheduledStart
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
mutation CreateBusiness(
|
||||
$businessName: String!,
|
||||
$contactName: String!,
|
||||
$email: String,
|
||||
$sector: BusinessSector,
|
||||
$rateGroup: BusinessRateGroup!,
|
||||
$status: BusinessStatus
|
||||
) @auth(level: USER) {
|
||||
business_insert(
|
||||
data: {
|
||||
businessName: $businessName
|
||||
contactName: $contactName
|
||||
email: $email
|
||||
sector: $sector
|
||||
rateGroup: $rateGroup
|
||||
status: $status
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateBusiness(
|
||||
$id: UUID!,
|
||||
$businessName: String,
|
||||
$contactName: String,
|
||||
$email: String,
|
||||
$sector: BusinessSector,
|
||||
$rateGroup: BusinessRateGroup,
|
||||
$status: BusinessStatus
|
||||
) @auth(level: USER) {
|
||||
business_update(
|
||||
id: $id,
|
||||
data: {
|
||||
businessName: $businessName
|
||||
contactName: $contactName
|
||||
email: $email
|
||||
sector: $sector
|
||||
rateGroup: $rateGroup
|
||||
status: $status
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteBusiness(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
business_delete(id: $id)
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
query listBusiness @auth(level: USER) {
|
||||
businesses {
|
||||
id
|
||||
businessName
|
||||
contactName
|
||||
email
|
||||
sector
|
||||
rateGroup
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
query getBusinessById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
business(id: $id) {
|
||||
id
|
||||
businessName
|
||||
contactName
|
||||
email
|
||||
sector
|
||||
rateGroup
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
query filterBusiness(
|
||||
$businessName: String,
|
||||
$contactName: String,
|
||||
$sector: BusinessSector,
|
||||
$rateGroup: BusinessRateGroup,
|
||||
$status: BusinessStatus
|
||||
) @auth(level: USER) {
|
||||
businesses(
|
||||
where: {
|
||||
businessName: { eq: $businessName }
|
||||
contactName: { eq: $contactName }
|
||||
sector: { eq: $sector }
|
||||
rateGroup: { eq: $rateGroup }
|
||||
status: { eq: $status }
|
||||
}
|
||||
) {
|
||||
id
|
||||
businessName
|
||||
contactName
|
||||
email
|
||||
sector
|
||||
rateGroup
|
||||
status
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
mutation CreateCertification(
|
||||
$employeeName: String!,
|
||||
$certificationName: String!,
|
||||
$certificationType: CertificationType,
|
||||
$status: CertificationStatus,
|
||||
$expiryDate: String!,
|
||||
$validationStatus: CertificationValidationStatus
|
||||
) @auth(level: USER) {
|
||||
certification_insert(
|
||||
data: {
|
||||
employeeName: $employeeName
|
||||
certificationName: $certificationName
|
||||
certificationType: $certificationType
|
||||
status: $status
|
||||
expiryDate: $expiryDate
|
||||
validationStatus: $validationStatus
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateCertification(
|
||||
$id: UUID!,
|
||||
$employeeName: String,
|
||||
$certificationName: String,
|
||||
$certificationType: CertificationType,
|
||||
$status: CertificationStatus,
|
||||
$expiryDate: String,
|
||||
$validationStatus: CertificationValidationStatus
|
||||
) @auth(level: USER) {
|
||||
certification_update(
|
||||
id: $id,
|
||||
data: {
|
||||
employeeName: $employeeName
|
||||
certificationName: $certificationName
|
||||
certificationType: $certificationType
|
||||
status: $status
|
||||
expiryDate: $expiryDate
|
||||
validationStatus: $validationStatus
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteCertification(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
certification_delete(id: $id)
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
query listCertification @auth(level: USER) {
|
||||
certifications {
|
||||
id
|
||||
employeeName
|
||||
certificationName
|
||||
certificationType
|
||||
status
|
||||
expiryDate
|
||||
validationStatus
|
||||
}
|
||||
}
|
||||
|
||||
query getCertificationById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
certification(id: $id) {
|
||||
id
|
||||
employeeName
|
||||
certificationName
|
||||
certificationType
|
||||
status
|
||||
expiryDate
|
||||
validationStatus
|
||||
createdDate
|
||||
updatedDate
|
||||
createdBy
|
||||
}
|
||||
}
|
||||
|
||||
query filterCertification(
|
||||
$employeeName: String,
|
||||
$certificationName: String,
|
||||
$certificationType: CertificationType,
|
||||
$status: CertificationStatus,
|
||||
$validationStatus: CertificationValidationStatus
|
||||
) @auth(level: USER) {
|
||||
certifications(
|
||||
where: {
|
||||
employeeName: { eq: $employeeName }
|
||||
certificationName: { eq: $certificationName }
|
||||
certificationType: { eq: $certificationType }
|
||||
status: { eq: $status }
|
||||
validationStatus: { eq: $validationStatus }
|
||||
}
|
||||
) {
|
||||
id
|
||||
employeeName
|
||||
certificationName
|
||||
certificationType
|
||||
status
|
||||
expiryDate
|
||||
validationStatus
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
connectorId: krow-connector
|
||||
generate:
|
||||
javascriptSdk:
|
||||
- outputDir: ../../frontend-web/src/dataconnect-generated
|
||||
package: "@dataconnect/generated"
|
||||
packageJsonDir: ../../frontend-web
|
||||
react: true
|
||||
angular: false
|
||||
- outputDir: ../../internal-api-harness/src/dataconnect-generated
|
||||
package: "@dataconnect/generated"
|
||||
packageJsonDir: ../../internal-api-harness
|
||||
react: true
|
||||
angular: false
|
||||
- outputDir: ../../frontend-web-free/src/dataconnect-generated
|
||||
package: "@dataconnect/generated"
|
||||
packageJsonDir: ../../frontend-web-free
|
||||
react: true
|
||||
angular: false
|
||||
@@ -1,39 +0,0 @@
|
||||
mutation CreateConversation(
|
||||
$participants: String!,
|
||||
$conversationType: ConversationType!,
|
||||
$relatedTo: UUID!,
|
||||
$status: ConversationStatus
|
||||
) @auth(level: USER) {
|
||||
conversation_insert(
|
||||
data: {
|
||||
participants: $participants
|
||||
conversationType: $conversationType
|
||||
relatedTo: $relatedTo
|
||||
status: $status
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateConversation(
|
||||
$id: UUID!,
|
||||
$participants: String,
|
||||
$conversationType: ConversationType,
|
||||
$relatedTo: UUID,
|
||||
$status: ConversationStatus
|
||||
) @auth(level: USER) {
|
||||
conversation_update(
|
||||
id: $id,
|
||||
data: {
|
||||
participants: $participants
|
||||
conversationType: $conversationType
|
||||
relatedTo: $relatedTo
|
||||
status: $status
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteConversation(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
conversation_delete(id: $id)
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
# dataconnect/connector/conversation/queries.gql
|
||||
|
||||
query listConversation @auth(level: USER) {
|
||||
conversations {
|
||||
id
|
||||
participants
|
||||
conversationType
|
||||
relatedTo
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
query getConversationById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
conversation(id: $id) {
|
||||
id
|
||||
participants
|
||||
conversationType
|
||||
relatedTo
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
query filterConversation(
|
||||
$conversationType: ConversationType,
|
||||
$status: ConversationStatus,
|
||||
$relatedTo: UUID
|
||||
) @auth(level: USER) {
|
||||
conversations(
|
||||
where: {
|
||||
conversationType: { eq: $conversationType }
|
||||
status: { eq: $status }
|
||||
relatedTo: { eq: $relatedTo }
|
||||
}
|
||||
) {
|
||||
id
|
||||
participants
|
||||
conversationType
|
||||
relatedTo
|
||||
status
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
mutation CreateEnterprise(
|
||||
$enterpriseNumber: String!,
|
||||
$enterpriseName: String!,
|
||||
$enterpriseCode: String!
|
||||
) @auth(level: USER) {
|
||||
enterprise_insert(
|
||||
data: {
|
||||
enterpriseNumber: $enterpriseNumber
|
||||
enterpriseName: $enterpriseName
|
||||
enterpriseCode: $enterpriseCode
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateEnterprise(
|
||||
$id: UUID!,
|
||||
$enterpriseNumber: String,
|
||||
$enterpriseName: String,
|
||||
$enterpriseCode: String
|
||||
) @auth(level: USER) {
|
||||
enterprise_update(
|
||||
id: $id,
|
||||
data: {
|
||||
enterpriseNumber: $enterpriseNumber
|
||||
enterpriseName: $enterpriseName
|
||||
enterpriseCode: $enterpriseCode
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteEnterprise(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
enterprise_delete(id: $id)
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
query listEnterprise @auth(level: USER) {
|
||||
enterprises {
|
||||
id
|
||||
enterpriseNumber
|
||||
enterpriseName
|
||||
enterpriseCode
|
||||
}
|
||||
}
|
||||
|
||||
query getEnterpriseById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
enterprise(id: $id) {
|
||||
id
|
||||
enterpriseNumber
|
||||
enterpriseName
|
||||
enterpriseCode
|
||||
}
|
||||
}
|
||||
|
||||
query filterEnterprise(
|
||||
$enterpriseNumber: String,
|
||||
$enterpriseName: String,
|
||||
$enterpriseCode: String
|
||||
) @auth(level: USER) {
|
||||
enterprises(
|
||||
where: {
|
||||
enterpriseNumber: { eq: $enterpriseNumber }
|
||||
enterpriseName: { eq: $enterpriseName }
|
||||
enterpriseCode: { eq: $enterpriseCode }
|
||||
}
|
||||
) {
|
||||
id
|
||||
enterpriseNumber
|
||||
enterpriseName
|
||||
enterpriseCode
|
||||
}
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
mutation CreateEvent(
|
||||
$eventName: String!,
|
||||
$isRapid: Boolean,
|
||||
$isRecurring: Boolean,
|
||||
$isMultiDay: Boolean,
|
||||
$recurrenceType: RecurrenceType,
|
||||
$recurrenceStartDate: Timestamp,
|
||||
$recurrenceEndDate: Timestamp,
|
||||
$scatterDates: Any,
|
||||
$multiDayStartDate: Timestamp,
|
||||
$multiDayEndDate: Timestamp,
|
||||
$bufferTimeBefore: Float,
|
||||
$bufferTimeAfter: Float,
|
||||
$conflictDetectionEnabled: Boolean,
|
||||
$detectedConflicts: Any,
|
||||
$businessId: UUID!,
|
||||
$businessName: String,
|
||||
$vendorId: String,
|
||||
$vendorName: String,
|
||||
$hub: String,
|
||||
$eventLocation: String,
|
||||
$contractType: ContractType,
|
||||
$poReference: String,
|
||||
$status: EventStatus!,
|
||||
$date: String!,
|
||||
$shifts: Any,
|
||||
$addons: Any,
|
||||
$total: Float,
|
||||
$clientName: String,
|
||||
$clientEmail: String,
|
||||
$clientPhone: String,
|
||||
$invoiceId: UUID,
|
||||
$notes: String,
|
||||
$requested: Int,
|
||||
$assignedStaff: Any,
|
||||
$department: String,
|
||||
$createdBy: String,
|
||||
$orderType: String,
|
||||
$recurringStartDate: String,
|
||||
$recurringEndDate: String,
|
||||
$recurringDays: Any,
|
||||
$permanentStartDate: String,
|
||||
$permanentDays: Any,
|
||||
$includeBackup: Boolean,
|
||||
$backupStaffCount: Int,
|
||||
$recurringTime: String,
|
||||
$permanentTime: String
|
||||
) @auth(level: USER) {
|
||||
event_insert(
|
||||
data: {
|
||||
eventName: $eventName
|
||||
isRapid: $isRapid
|
||||
isRecurring: $isRecurring
|
||||
isMultiDay: $isMultiDay
|
||||
recurrenceType: $recurrenceType
|
||||
recurrenceStartDate: $recurrenceStartDate
|
||||
recurrenceEndDate: $recurrenceEndDate
|
||||
scatterDates: $scatterDates
|
||||
multiDayStartDate: $multiDayStartDate
|
||||
multiDayEndDate: $multiDayEndDate
|
||||
bufferTimeBefore: $bufferTimeBefore
|
||||
bufferTimeAfter: $bufferTimeAfter
|
||||
conflictDetectionEnabled: $conflictDetectionEnabled
|
||||
detectedConflicts: $detectedConflicts
|
||||
businessId: $businessId
|
||||
businessName: $businessName
|
||||
vendorId: $vendorId
|
||||
vendorName: $vendorName
|
||||
hub: $hub
|
||||
eventLocation: $eventLocation
|
||||
contractType: $contractType
|
||||
poReference: $poReference
|
||||
status: $status
|
||||
date: $date
|
||||
shifts: $shifts
|
||||
addons: $addons
|
||||
total: $total
|
||||
clientName: $clientName
|
||||
clientEmail: $clientEmail
|
||||
clientPhone: $clientPhone
|
||||
invoiceId: $invoiceId
|
||||
notes: $notes
|
||||
orderType: $orderType
|
||||
requested: $requested
|
||||
assignedStaff: $assignedStaff
|
||||
department: $department
|
||||
createdBy: $createdBy
|
||||
recurringStartDate: $recurringStartDate
|
||||
recurringEndDate: $recurringEndDate
|
||||
recurringDays: $recurringDays
|
||||
permanentStartDate: $permanentStartDate
|
||||
permanentDays: $permanentDays
|
||||
includeBackup: $includeBackup
|
||||
backupStaffCount: $backupStaffCount
|
||||
recurringTime: $recurringTime
|
||||
permanentTime: $permanentTime
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
mutation UpdateEvent(
|
||||
$id: UUID!,
|
||||
$eventName: String,
|
||||
$isRapid: Boolean,
|
||||
$isRecurring: Boolean,
|
||||
$isMultiDay: Boolean,
|
||||
$recurrenceType: RecurrenceType,
|
||||
$recurrenceStartDate: Timestamp,
|
||||
$recurrenceEndDate: Timestamp,
|
||||
$scatterDates: Any,
|
||||
$multiDayStartDate: Timestamp,
|
||||
$multiDayEndDate: Timestamp,
|
||||
$bufferTimeBefore: Float,
|
||||
$bufferTimeAfter: Float,
|
||||
$conflictDetectionEnabled: Boolean,
|
||||
$detectedConflicts: Any,
|
||||
$businessId: UUID,
|
||||
$businessName: String,
|
||||
$vendorId: String,
|
||||
$vendorName: String,
|
||||
$hub: String,
|
||||
$eventLocation: String,
|
||||
$contractType: ContractType,
|
||||
$poReference: String,
|
||||
$status: EventStatus,
|
||||
$date: String,
|
||||
$shifts: Any,
|
||||
$addons: Any,
|
||||
$total: Float,
|
||||
$clientName: String,
|
||||
$clientEmail: String,
|
||||
$clientPhone: String,
|
||||
$invoiceId: UUID,
|
||||
$notes: String,
|
||||
$requested: Int,
|
||||
$orderType: String,
|
||||
$department: String,
|
||||
$assignedStaff: Any,
|
||||
$createdBy: String,
|
||||
$recurringStartDate: String,
|
||||
$recurringEndDate: String,
|
||||
$recurringDays: Any,
|
||||
$permanentStartDate: String,
|
||||
$permanentDays: Any,
|
||||
$includeBackup: Boolean,
|
||||
$backupStaffCount: Int,
|
||||
$recurringTime: String,
|
||||
$permanentTime: String
|
||||
) @auth(level: USER) {
|
||||
event_update(
|
||||
id: $id,
|
||||
data: {
|
||||
eventName: $eventName
|
||||
isRapid: $isRapid
|
||||
isRecurring: $isRecurring
|
||||
isMultiDay: $isMultiDay
|
||||
recurrenceType: $recurrenceType
|
||||
recurrenceStartDate: $recurrenceStartDate
|
||||
recurrenceEndDate: $recurrenceEndDate
|
||||
scatterDates: $scatterDates
|
||||
multiDayStartDate: $multiDayStartDate
|
||||
multiDayEndDate: $multiDayEndDate
|
||||
bufferTimeBefore: $bufferTimeBefore
|
||||
bufferTimeAfter: $bufferTimeAfter
|
||||
conflictDetectionEnabled: $conflictDetectionEnabled
|
||||
detectedConflicts: $detectedConflicts
|
||||
businessId: $businessId
|
||||
businessName: $businessName
|
||||
vendorId: $vendorId
|
||||
vendorName: $vendorName
|
||||
hub: $hub
|
||||
eventLocation: $eventLocation
|
||||
contractType: $contractType
|
||||
poReference: $poReference
|
||||
status: $status
|
||||
date: $date
|
||||
shifts: $shifts
|
||||
addons: $addons
|
||||
total: $total
|
||||
clientName: $clientName
|
||||
clientEmail: $clientEmail
|
||||
clientPhone: $clientPhone
|
||||
invoiceId: $invoiceId
|
||||
notes: $notes
|
||||
orderType: $orderType
|
||||
requested: $requested
|
||||
assignedStaff: $assignedStaff
|
||||
department: $department
|
||||
createdBy: $createdBy
|
||||
recurringStartDate: $recurringStartDate
|
||||
recurringEndDate: $recurringEndDate
|
||||
recurringDays: $recurringDays
|
||||
permanentStartDate: $permanentStartDate
|
||||
permanentDays: $permanentDays
|
||||
includeBackup: $includeBackup
|
||||
backupStaffCount: $backupStaffCount
|
||||
recurringTime: $recurringTime
|
||||
permanentTime: $permanentTime
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteEvent(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
event_delete(id: $id)
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
query listEvents (
|
||||
$orderByDate: OrderDirection
|
||||
$orderByCreatedDate: OrderDirection,
|
||||
$limit: Int
|
||||
) @auth(level: USER) {
|
||||
events(
|
||||
orderBy: [
|
||||
{ date: $orderByDate }
|
||||
{ createdDate: $orderByCreatedDate }
|
||||
]
|
||||
limit: $limit
|
||||
) {
|
||||
id
|
||||
eventName
|
||||
status
|
||||
date
|
||||
isRapid
|
||||
isRecurring
|
||||
isMultiDay
|
||||
recurrenceType
|
||||
recurrenceStartDate
|
||||
recurrenceEndDate
|
||||
scatterDates
|
||||
multiDayStartDate
|
||||
multiDayEndDate
|
||||
bufferTimeBefore
|
||||
bufferTimeAfter
|
||||
conflictDetectionEnabled
|
||||
detectedConflicts
|
||||
businessId
|
||||
businessName
|
||||
vendorId
|
||||
vendorName
|
||||
hub
|
||||
eventLocation
|
||||
contractType
|
||||
poReference
|
||||
shifts
|
||||
addons
|
||||
total
|
||||
clientName
|
||||
clientEmail
|
||||
clientPhone
|
||||
invoiceId
|
||||
notes
|
||||
requested
|
||||
assignedStaff
|
||||
orderType
|
||||
department
|
||||
createdBy
|
||||
recurringStartDate
|
||||
recurringEndDate
|
||||
recurringDays
|
||||
permanentStartDate
|
||||
permanentDays
|
||||
includeBackup
|
||||
backupStaffCount
|
||||
recurringTime
|
||||
permanentTime
|
||||
}
|
||||
}
|
||||
|
||||
query getEventById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
event(id: $id) {
|
||||
id
|
||||
eventName
|
||||
status
|
||||
date
|
||||
isRapid
|
||||
isRecurring
|
||||
isMultiDay
|
||||
recurrenceType
|
||||
recurrenceStartDate
|
||||
recurrenceEndDate
|
||||
scatterDates
|
||||
multiDayStartDate
|
||||
multiDayEndDate
|
||||
bufferTimeBefore
|
||||
bufferTimeAfter
|
||||
conflictDetectionEnabled
|
||||
detectedConflicts
|
||||
businessId
|
||||
businessName
|
||||
vendorId
|
||||
vendorName
|
||||
hub
|
||||
eventLocation
|
||||
contractType
|
||||
poReference
|
||||
shifts
|
||||
addons
|
||||
total
|
||||
clientName
|
||||
clientEmail
|
||||
clientPhone
|
||||
invoiceId
|
||||
notes
|
||||
requested
|
||||
orderType
|
||||
department
|
||||
assignedStaff
|
||||
recurringStartDate
|
||||
recurringEndDate
|
||||
recurringDays
|
||||
permanentStartDate
|
||||
permanentDays
|
||||
includeBackup
|
||||
backupStaffCount
|
||||
recurringTime
|
||||
permanentTime
|
||||
}
|
||||
}
|
||||
|
||||
query filterEvents(
|
||||
$status: EventStatus,
|
||||
$businessId: UUID,
|
||||
$vendorId: String,
|
||||
$isRecurring: Boolean,
|
||||
$isRapid: Boolean,
|
||||
$isMultiDay: Boolean,
|
||||
$recurrenceType: RecurrenceType,
|
||||
$date: String,
|
||||
$hub: String,
|
||||
$eventLocation: String,
|
||||
$contractType: ContractType,
|
||||
$clientEmail: String
|
||||
) @auth(level: USER) {
|
||||
events(
|
||||
where: {
|
||||
status: { eq: $status }
|
||||
businessId: { eq: $businessId }
|
||||
vendorId: { eq: $vendorId }
|
||||
isRecurring: { eq: $isRecurring }
|
||||
isRapid: { eq: $isRapid }
|
||||
isMultiDay: { eq: $isMultiDay }
|
||||
recurrenceType: { eq: $recurrenceType }
|
||||
date: { eq: $date }
|
||||
hub: { eq: $hub }
|
||||
eventLocation: { eq: $eventLocation }
|
||||
contractType: { eq: $contractType }
|
||||
clientEmail: { eq: $clientEmail }
|
||||
}) {
|
||||
id
|
||||
eventName
|
||||
status
|
||||
date
|
||||
isRapid
|
||||
isRecurring
|
||||
isMultiDay
|
||||
recurrenceType
|
||||
recurrenceStartDate
|
||||
recurrenceEndDate
|
||||
scatterDates
|
||||
multiDayStartDate
|
||||
multiDayEndDate
|
||||
bufferTimeBefore
|
||||
bufferTimeAfter
|
||||
conflictDetectionEnabled
|
||||
detectedConflicts
|
||||
businessId
|
||||
businessName
|
||||
vendorId
|
||||
vendorName
|
||||
hub
|
||||
eventLocation
|
||||
contractType
|
||||
poReference
|
||||
shifts
|
||||
addons
|
||||
total
|
||||
clientName
|
||||
clientEmail
|
||||
clientPhone
|
||||
invoiceId
|
||||
notes
|
||||
requested
|
||||
assignedStaff
|
||||
orderType
|
||||
department
|
||||
createdBy
|
||||
recurringStartDate
|
||||
recurringEndDate
|
||||
recurringDays
|
||||
permanentStartDate
|
||||
permanentDays
|
||||
includeBackup
|
||||
backupStaffCount
|
||||
recurringTime
|
||||
permanentTime
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
mutation CreateInvoice(
|
||||
$invoiceNumber: String!,
|
||||
$amount: Float!,
|
||||
$status: InvoiceStatus!,
|
||||
$issueDate: Timestamp!,
|
||||
$dueDate: Timestamp!,
|
||||
$disputedItems: String,
|
||||
$isAutoGenerated: Boolean
|
||||
) @auth(level: USER) {
|
||||
invoice_insert(
|
||||
data: {
|
||||
invoiceNumber: $invoiceNumber
|
||||
amount: $amount
|
||||
status: $status
|
||||
issueDate: $issueDate
|
||||
dueDate: $dueDate
|
||||
disputedItems: $disputedItems
|
||||
isAutoGenerated: $isAutoGenerated
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateInvoice(
|
||||
$id: UUID!,
|
||||
$invoiceNumber: String,
|
||||
$amount: Float,
|
||||
$status: InvoiceStatus,
|
||||
$issueDate: Timestamp,
|
||||
$dueDate: Timestamp,
|
||||
$disputedItems: String,
|
||||
$isAutoGenerated: Boolean
|
||||
) @auth(level: USER) {
|
||||
invoice_update(
|
||||
id: $id,
|
||||
data: {
|
||||
invoiceNumber: $invoiceNumber
|
||||
amount: $amount
|
||||
status: $status
|
||||
issueDate: $issueDate
|
||||
dueDate: $dueDate
|
||||
disputedItems: $disputedItems
|
||||
isAutoGenerated: $isAutoGenerated
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteInvoice(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
invoice_delete(id: $id)
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
query listInvoice @auth(level: USER) {
|
||||
invoices {
|
||||
id
|
||||
invoiceNumber
|
||||
amount
|
||||
status
|
||||
issueDate
|
||||
dueDate
|
||||
disputedItems
|
||||
isAutoGenerated
|
||||
}
|
||||
}
|
||||
|
||||
query getInvoiceById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
invoice(id: $id) {
|
||||
id
|
||||
invoiceNumber
|
||||
amount
|
||||
status
|
||||
issueDate
|
||||
dueDate
|
||||
disputedItems
|
||||
isAutoGenerated
|
||||
}
|
||||
}
|
||||
|
||||
query filterInvoices(
|
||||
$invoiceNumber: String,
|
||||
$status: InvoiceStatus,
|
||||
$isAutoGenerated: Boolean,
|
||||
$amount: Float
|
||||
) @auth(level: USER) {
|
||||
invoices(
|
||||
where: {
|
||||
invoiceNumber: { eq: $invoiceNumber }
|
||||
status: { eq: $status }
|
||||
isAutoGenerated: { eq: $isAutoGenerated }
|
||||
amount: { eq: $amount }
|
||||
}
|
||||
) {
|
||||
id
|
||||
invoiceNumber
|
||||
amount
|
||||
status
|
||||
issueDate
|
||||
dueDate
|
||||
isAutoGenerated
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
mutation CreateMessage(
|
||||
$conversationId: UUID!,
|
||||
$senderName: String!,
|
||||
$content: String!,
|
||||
$readBy: String
|
||||
) @auth(level: USER) {
|
||||
message_insert(
|
||||
data: {
|
||||
conversationId: $conversationId
|
||||
senderName: $senderName
|
||||
content: $content
|
||||
readBy: $readBy
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateMessage(
|
||||
$id: UUID!,
|
||||
$conversationId: UUID,
|
||||
$senderName: String,
|
||||
$content: String,
|
||||
$readBy: String
|
||||
) @auth(level: USER) {
|
||||
message_update(
|
||||
id: $id,
|
||||
data: {
|
||||
conversationId: $conversationId
|
||||
senderName: $senderName
|
||||
content: $content
|
||||
readBy: $readBy
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteMessage(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
message_delete(id: $id)
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
query listMessage @auth(level: USER) {
|
||||
messages {
|
||||
id
|
||||
conversationId
|
||||
senderName
|
||||
content
|
||||
readBy
|
||||
}
|
||||
}
|
||||
|
||||
query getMessageById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
message(id: $id) {
|
||||
id
|
||||
conversationId
|
||||
senderName
|
||||
content
|
||||
readBy
|
||||
}
|
||||
}
|
||||
|
||||
query filterMessage(
|
||||
$conversationId: UUID,
|
||||
$senderName: String
|
||||
) @auth(level: USER) {
|
||||
messages(
|
||||
where: {
|
||||
conversationId: { eq: $conversationId }
|
||||
senderName: { eq: $senderName }
|
||||
}
|
||||
) {
|
||||
id
|
||||
conversationId
|
||||
senderName
|
||||
content
|
||||
readBy
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
mutation CreateOrder(
|
||||
$orderNumber: String!,
|
||||
$partnerId: UUID!,
|
||||
$orderType: OrderType,
|
||||
$orderStatus: OrderStatus
|
||||
) @auth(level: USER) {
|
||||
order_insert(
|
||||
data: {
|
||||
orderNumber: $orderNumber
|
||||
partnerId: $partnerId
|
||||
orderType: $orderType
|
||||
orderStatus: $orderStatus
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateOrder(
|
||||
$id: UUID!,
|
||||
$orderNumber: String,
|
||||
$partnerId: UUID,
|
||||
$orderType: OrderType,
|
||||
$orderStatus: OrderStatus
|
||||
) @auth(level: USER) {
|
||||
order_update(
|
||||
id: $id,
|
||||
data: {
|
||||
orderNumber: $orderNumber
|
||||
partnerId: $partnerId
|
||||
orderType: $orderType
|
||||
orderStatus: $orderStatus
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteOrder(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
order_delete(id: $id)
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
query listOrder @auth(level: USER) {
|
||||
orders {
|
||||
id
|
||||
orderNumber
|
||||
partnerId
|
||||
orderType
|
||||
orderStatus
|
||||
}
|
||||
}
|
||||
|
||||
query getOrderById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
order(id: $id) {
|
||||
id
|
||||
orderNumber
|
||||
partnerId
|
||||
orderType
|
||||
orderStatus
|
||||
}
|
||||
}
|
||||
|
||||
query filterOrder(
|
||||
$orderNumber: String,
|
||||
$partnerId: UUID,
|
||||
$orderType: OrderType,
|
||||
$orderStatus: OrderStatus
|
||||
) @auth(level: USER) {
|
||||
orders(
|
||||
where: {
|
||||
orderNumber: { eq: $orderNumber }
|
||||
partnerId: { eq: $partnerId }
|
||||
orderType: { eq: $orderType }
|
||||
orderStatus: { eq: $orderStatus }
|
||||
}
|
||||
) {
|
||||
id
|
||||
orderNumber
|
||||
partnerId
|
||||
orderType
|
||||
orderStatus
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
mutation CreatePartner(
|
||||
$partnerName: String!,
|
||||
$partnerNumber: String!,
|
||||
$partnerType: PartnerType
|
||||
) @auth(level: USER) {
|
||||
partner_insert(
|
||||
data: {
|
||||
partnerName: $partnerName
|
||||
partnerNumber: $partnerNumber
|
||||
partnerType: $partnerType
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdatePartner(
|
||||
$id: UUID!,
|
||||
$partnerName: String,
|
||||
$partnerNumber: String,
|
||||
$partnerType: PartnerType
|
||||
) @auth(level: USER) {
|
||||
partner_update(
|
||||
id: $id,
|
||||
data: {
|
||||
partnerName: $partnerName
|
||||
partnerNumber: $partnerNumber
|
||||
partnerType: $partnerType
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeletePartner(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
partner_delete(id: $id)
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
# dataconnect/connector/partner/queries.gql
|
||||
|
||||
query listPartner @auth(level: USER) {
|
||||
partners {
|
||||
id
|
||||
partnerName
|
||||
partnerNumber
|
||||
partnerType
|
||||
}
|
||||
}
|
||||
|
||||
query getPartnerById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
partner(id: $id) {
|
||||
id
|
||||
partnerName
|
||||
partnerNumber
|
||||
partnerType
|
||||
}
|
||||
}
|
||||
|
||||
query filterPartner(
|
||||
$partnerName: String,
|
||||
$partnerNumber: String,
|
||||
$partnerType: PartnerType
|
||||
) @auth(level: USER) {
|
||||
partners(
|
||||
where: {
|
||||
partnerName: { eq: $partnerName }
|
||||
partnerNumber: { eq: $partnerNumber }
|
||||
partnerType: { eq: $partnerType }
|
||||
}
|
||||
) {
|
||||
id
|
||||
partnerName
|
||||
partnerNumber
|
||||
partnerType
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
mutation CreateSector(
|
||||
$sectorNumber: String!,
|
||||
$sectorName: String!,
|
||||
$sectorType: SectorType
|
||||
) @auth(level: USER) {
|
||||
sector_insert(
|
||||
data: {
|
||||
sectorNumber: $sectorNumber
|
||||
sectorName: $sectorName
|
||||
sectorType: $sectorType
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateSector(
|
||||
$id: UUID!,
|
||||
$sectorNumber: String,
|
||||
$sectorName: String,
|
||||
$sectorType: SectorType
|
||||
) @auth(level: USER) {
|
||||
sector_update(
|
||||
id: $id,
|
||||
data: {
|
||||
sectorNumber: $sectorNumber
|
||||
sectorName: $sectorName
|
||||
sectorType: $sectorType
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteSector(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
sector_delete(id: $id)
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
query listSector @auth(level: USER) {
|
||||
sectors {
|
||||
id
|
||||
sectorNumber
|
||||
sectorName
|
||||
sectorType
|
||||
}
|
||||
}
|
||||
|
||||
query getSectorById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
sector(id: $id) {
|
||||
id
|
||||
sectorNumber
|
||||
sectorName
|
||||
sectorType
|
||||
}
|
||||
}
|
||||
|
||||
query filterSector(
|
||||
$sectorNumber: String,
|
||||
$sectorName: String,
|
||||
$sectorType: SectorType
|
||||
) @auth(level: USER) {
|
||||
sectors(
|
||||
where: {
|
||||
sectorNumber: { eq: $sectorNumber }
|
||||
sectorName: { eq: $sectorName }
|
||||
sectorType: { eq: $sectorType }
|
||||
}
|
||||
) {
|
||||
id
|
||||
sectorNumber
|
||||
sectorName
|
||||
sectorType
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
mutation CreateShift(
|
||||
$shiftName: String!,
|
||||
$startDate: Timestamp!,
|
||||
$endDate: Timestamp,
|
||||
$assignedStaff: String
|
||||
) @auth(level: USER) {
|
||||
shift_insert(
|
||||
data: {
|
||||
shiftName: $shiftName
|
||||
startDate: $startDate
|
||||
endDate: $endDate
|
||||
assignedStaff: $assignedStaff
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateShift(
|
||||
$id: UUID!,
|
||||
$shiftName: String,
|
||||
$startDate: Timestamp,
|
||||
$endDate: Timestamp,
|
||||
$assignedStaff: String
|
||||
) @auth(level: USER) {
|
||||
shift_update(
|
||||
id: $id,
|
||||
data: {
|
||||
shiftName: $shiftName
|
||||
startDate: $startDate
|
||||
endDate: $endDate
|
||||
assignedStaff: $assignedStaff
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteShift(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
shift_delete(id: $id)
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
query listShift @auth(level: USER) {
|
||||
shifts {
|
||||
id
|
||||
shiftName
|
||||
startDate
|
||||
endDate
|
||||
assignedStaff
|
||||
}
|
||||
}
|
||||
|
||||
query getShiftById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
shift(id: $id) {
|
||||
id
|
||||
shiftName
|
||||
startDate
|
||||
endDate
|
||||
assignedStaff
|
||||
createdDate
|
||||
updatedDate
|
||||
createdBy
|
||||
}
|
||||
}
|
||||
|
||||
query filterShift(
|
||||
$shiftName: String,
|
||||
$startDate: Timestamp,
|
||||
$endDate: Timestamp
|
||||
) @auth(level: USER) {
|
||||
shifts(
|
||||
where: {
|
||||
shiftName: { eq: $shiftName }
|
||||
startDate: { eq: $startDate }
|
||||
endDate: { eq: $endDate }
|
||||
}
|
||||
) {
|
||||
id
|
||||
shiftName
|
||||
startDate
|
||||
endDate
|
||||
assignedStaff
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
mutation CreateStaff(
|
||||
$employeeName: String!,
|
||||
$vendorId: String,
|
||||
$vendorName: String,
|
||||
$manager: String,
|
||||
$contactNumber: String,
|
||||
$phone:String # nuevo,
|
||||
$email: String,
|
||||
$department: StaffDepartment,
|
||||
$hubLocation: String,
|
||||
$eventLocation:String, # nuevo
|
||||
$address:String, # nuevo
|
||||
$city:String, # nuevo
|
||||
$track: String,
|
||||
$position: String,
|
||||
$position2:String, # nuevo
|
||||
$initial:String, # nuevo
|
||||
$profileType: ProfileType,
|
||||
$employmentType: EmploymentType,
|
||||
$english: EnglishLevel,
|
||||
$rate: Float,
|
||||
$rating: Float,
|
||||
$reliabilityScore: Int,
|
||||
$backgroundCheckStatus: BackgroundCheckStatus,
|
||||
$notes: String,
|
||||
$accountingComments:String, # nuevo
|
||||
$shiftCoveragePercentage:Int, # nuevo
|
||||
$cancellationCount:Int, # nuevo
|
||||
$noShowCount:Int, # nuevo
|
||||
$totalShifts:Int, # nuevo
|
||||
$invoiced:Boolean, # nuevo
|
||||
$englishRequired:Boolean, # nuevo
|
||||
$checkIn:String, # nuevo
|
||||
$scheduleDays:String, # nuevo
|
||||
$replacedBy:String, # nuevo
|
||||
$action:String, # nuevo
|
||||
$ro:String, # nuevo
|
||||
$mon:String, # nuevo
|
||||
) @auth(level: USER) {
|
||||
staff_insert(
|
||||
data: {
|
||||
employeeName: $employeeName
|
||||
vendorId: $vendorId
|
||||
vendorName: $vendorName
|
||||
manager: $manager
|
||||
contactNumber: $contactNumber
|
||||
phone:$phone
|
||||
email: $email
|
||||
department: $department
|
||||
hubLocation: $hubLocation
|
||||
eventLocation:$eventLocation
|
||||
address:$address
|
||||
city:$city
|
||||
track: $track
|
||||
position: $position
|
||||
position2:$position2
|
||||
initial:$initial
|
||||
profileType: $profileType
|
||||
employmentType: $employmentType
|
||||
english: $english
|
||||
rate: $rate
|
||||
rating: $rating
|
||||
reliabilityScore: $reliabilityScore
|
||||
backgroundCheckStatus: $backgroundCheckStatus
|
||||
notes: $notes
|
||||
accountingComments:$accountingComments
|
||||
shiftCoveragePercentage:$shiftCoveragePercentage
|
||||
cancellationCount:$cancellationCount
|
||||
noShowCount:$noShowCount
|
||||
totalShifts:$totalShifts
|
||||
invoiced:$invoiced
|
||||
englishRequired:$englishRequired
|
||||
checkIn:$checkIn
|
||||
scheduleDays:$scheduleDays
|
||||
replacedBy:$replacedBy
|
||||
action:$action
|
||||
ro:$ro
|
||||
mon:$mon
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateStaff(
|
||||
$id: UUID!,
|
||||
$employeeName: String,
|
||||
$vendorId: String,
|
||||
$vendorName: String,
|
||||
$manager: String,
|
||||
$contactNumber: String,
|
||||
$phone: String,
|
||||
$email: String,
|
||||
$department: StaffDepartment,
|
||||
$hubLocation: String,
|
||||
$eventLocation: String,
|
||||
$address: String,
|
||||
$city: String,
|
||||
$track: String,
|
||||
$position: String,
|
||||
$position2:String,
|
||||
$initial:String,
|
||||
$profileType: ProfileType,
|
||||
$employmentType: EmploymentType,
|
||||
$english: EnglishLevel,
|
||||
$englishRequired:Boolean # nuevo
|
||||
$rate: Float,
|
||||
$rating: Float,
|
||||
$reliabilityScore: Int,
|
||||
$backgroundCheckStatus: BackgroundCheckStatus,
|
||||
$notes: String,
|
||||
$accountingComments:String,
|
||||
$shiftCoveragePercentage:Int,
|
||||
$cancellationCount:Int,
|
||||
$noShowCount:Int,
|
||||
$totalShifts:Int,
|
||||
$invoiced:Boolean,
|
||||
$checkIn:String,
|
||||
$scheduleDays:String,
|
||||
$replacedBy:String,
|
||||
$action:String,
|
||||
$ro:String,
|
||||
$mon:String,
|
||||
) @auth(level: USER) {
|
||||
staff_update(
|
||||
id: $id,
|
||||
data: {
|
||||
employeeName: $employeeName
|
||||
vendorId: $vendorId
|
||||
vendorName: $vendorName
|
||||
manager: $manager
|
||||
contactNumber: $contactNumber
|
||||
phone:$phone # nuevo
|
||||
email: $email
|
||||
department: $department
|
||||
hubLocation: $hubLocation
|
||||
eventLocation:$eventLocation # nuevo
|
||||
address:$address # nuevo
|
||||
city:$city # nuevo
|
||||
track: $track
|
||||
position: $position
|
||||
position2:$position2 # nuevo
|
||||
initial:$initial # nuevo
|
||||
profileType: $profileType
|
||||
employmentType: $employmentType
|
||||
english: $english
|
||||
englishRequired:$englishRequired # nuevo
|
||||
rate: $rate
|
||||
rating: $rating
|
||||
reliabilityScore: $reliabilityScore
|
||||
backgroundCheckStatus: $backgroundCheckStatus
|
||||
notes: $notes
|
||||
accountingComments:$accountingComments # nuevo
|
||||
shiftCoveragePercentage:$shiftCoveragePercentage # nuevo
|
||||
cancellationCount:$cancellationCount # nuevo
|
||||
noShowCount:$noShowCount # nuevo
|
||||
totalShifts:$totalShifts # nuevo
|
||||
invoiced:$invoiced # nuevo
|
||||
checkIn:$checkIn # nuevo
|
||||
scheduleDays:$scheduleDays # nuevo
|
||||
replacedBy:$replacedBy # nuevo
|
||||
action:$action # nuevo
|
||||
ro:$ro # nuevo
|
||||
mon:$mon # nuevo
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteStaff(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
staff_delete(id: $id)
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
query listStaff @auth(level: USER) {
|
||||
staffs {
|
||||
id
|
||||
employeeName
|
||||
vendorId
|
||||
vendorName
|
||||
manager
|
||||
contactNumber
|
||||
phone # nuevo
|
||||
email
|
||||
department
|
||||
hubLocation
|
||||
eventLocation # nuevo
|
||||
address # nuevo
|
||||
city # nuevo
|
||||
track
|
||||
position
|
||||
position2
|
||||
initial # nuevo
|
||||
profileType
|
||||
employmentType
|
||||
english
|
||||
englishRequired # nuevo
|
||||
rate
|
||||
rating
|
||||
reliabilityScore
|
||||
backgroundCheckStatus
|
||||
notes
|
||||
accountingComments # nuevo
|
||||
shiftCoveragePercentage # nuevo
|
||||
cancellationCount # nuevo
|
||||
noShowCount # nuevo
|
||||
totalShifts # nuevo
|
||||
invoiced # nuevo
|
||||
checkIn # nuevo
|
||||
scheduleDays # nuevo
|
||||
replacedBy # nuevo
|
||||
action # nuevo
|
||||
ro # nuevo
|
||||
mon # nuevo
|
||||
}
|
||||
}
|
||||
|
||||
query getStaffById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
staff(id: $id) {
|
||||
id
|
||||
employeeName
|
||||
vendorId
|
||||
vendorName
|
||||
manager
|
||||
contactNumber
|
||||
phone # nuevo
|
||||
email
|
||||
department
|
||||
hubLocation
|
||||
eventLocation # nuevo
|
||||
address # nuevo
|
||||
city # nuevo
|
||||
track
|
||||
position
|
||||
position2 # nuevo
|
||||
initial # nuevo
|
||||
profileType
|
||||
employmentType
|
||||
english
|
||||
rate
|
||||
rating
|
||||
reliabilityScore
|
||||
backgroundCheckStatus
|
||||
notes
|
||||
accountingComments # nuevo
|
||||
shiftCoveragePercentage # nuevo
|
||||
cancellationCount # nuevo
|
||||
noShowCount # nuevo
|
||||
totalShifts # nuevo
|
||||
invoiced # nuevo
|
||||
englishRequired # nuevo
|
||||
checkIn # nuevo
|
||||
scheduleDays # nuevo
|
||||
replacedBy # nuevo
|
||||
action # nuevo
|
||||
ro # nuevo
|
||||
mon # nuevo
|
||||
}
|
||||
}
|
||||
|
||||
query filterStaff(
|
||||
$employeeName: String,
|
||||
$vendorId: String,
|
||||
$department: StaffDepartment,
|
||||
$employmentType: EmploymentType,
|
||||
$english: EnglishLevel,
|
||||
$backgroundCheckStatus: BackgroundCheckStatus
|
||||
) @auth(level: USER) {
|
||||
staffs(
|
||||
where: {
|
||||
employeeName: { eq: $employeeName }
|
||||
vendorId: { eq: $vendorId }
|
||||
department: { eq: $department }
|
||||
employmentType: { eq: $employmentType }
|
||||
english: { eq: $english }
|
||||
backgroundCheckStatus: { eq: $backgroundCheckStatus }
|
||||
}
|
||||
) {
|
||||
id
|
||||
employeeName
|
||||
vendorId
|
||||
vendorName
|
||||
department
|
||||
hubLocation
|
||||
eventLocation # nuevo
|
||||
position
|
||||
position2
|
||||
employmentType
|
||||
english
|
||||
rate
|
||||
rating
|
||||
reliabilityScore
|
||||
backgroundCheckStatus
|
||||
notes
|
||||
invoiced # nuevo
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
mutation CreateTeam(
|
||||
$teamName: String!,
|
||||
$ownerId: String!,
|
||||
$ownerName: String!,
|
||||
$ownerRole: TeamOwnerRole!,
|
||||
$favoriteStaff: String,
|
||||
$blockedStaff: String
|
||||
) @auth(level: USER) {
|
||||
team_insert(
|
||||
data: {
|
||||
teamName: $teamName
|
||||
ownerId: $ownerId
|
||||
ownerName: $ownerName
|
||||
ownerRole: $ownerRole
|
||||
favoriteStaff: $favoriteStaff
|
||||
blockedStaff: $blockedStaff
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateTeam(
|
||||
$id: UUID!,
|
||||
$teamName: String,
|
||||
$ownerId: String,
|
||||
$ownerName: String,
|
||||
$ownerRole: TeamOwnerRole,
|
||||
$favoriteStaff: String,
|
||||
$blockedStaff: String
|
||||
) @auth(level: USER) {
|
||||
team_update(
|
||||
id: $id,
|
||||
data: {
|
||||
teamName: $teamName
|
||||
ownerId: $ownerId
|
||||
ownerName: $ownerName
|
||||
ownerRole: $ownerRole
|
||||
favoriteStaff: $favoriteStaff
|
||||
blockedStaff: $blockedStaff
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteTeam(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
team_delete(id: $id)
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
query listTeam (
|
||||
$orderByCreatedDate: OrderDirection
|
||||
$limit: Int
|
||||
) @auth(level: USER) {
|
||||
teams(
|
||||
orderBy: { createdDate: $orderByCreatedDate }
|
||||
limit: $limit
|
||||
) {
|
||||
id
|
||||
teamName
|
||||
ownerId
|
||||
ownerName
|
||||
ownerRole
|
||||
favoriteStaff
|
||||
blockedStaff
|
||||
}
|
||||
}
|
||||
|
||||
query getTeamById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
team(id: $id) {
|
||||
id
|
||||
teamName
|
||||
ownerId
|
||||
ownerName
|
||||
ownerRole
|
||||
favoriteStaff
|
||||
blockedStaff
|
||||
}
|
||||
}
|
||||
|
||||
query filterTeam(
|
||||
$teamName: String,
|
||||
$ownerId: String,
|
||||
$ownerRole: TeamOwnerRole
|
||||
) @auth(level: USER) {
|
||||
teams(
|
||||
where: {
|
||||
teamName: { eq: $teamName }
|
||||
ownerId: { eq: $ownerId }
|
||||
ownerRole: { eq: $ownerRole }
|
||||
}
|
||||
) {
|
||||
id
|
||||
teamName
|
||||
ownerId
|
||||
ownerName
|
||||
ownerRole
|
||||
favoriteStaff
|
||||
blockedStaff
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
mutation CreateTeamHub(
|
||||
$teamId: UUID!,
|
||||
$hubName: String!,
|
||||
$departments: String
|
||||
) @auth(level: USER) {
|
||||
teamHub_insert(
|
||||
data: {
|
||||
teamId: $teamId
|
||||
hubName: $hubName
|
||||
departments: $departments
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateTeamHub(
|
||||
$id: UUID!,
|
||||
$teamId: UUID,
|
||||
$hubName: String,
|
||||
$departments: String
|
||||
) @auth(level: USER) {
|
||||
teamHub_update(
|
||||
id: $id,
|
||||
data: {
|
||||
teamId: $teamId
|
||||
hubName: $hubName
|
||||
departments: $departments
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteTeamHub(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
teamHub_delete(id: $id)
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
query listTeamHub @auth(level: USER) {
|
||||
teamHubs {
|
||||
id
|
||||
teamId
|
||||
hubName
|
||||
departments
|
||||
}
|
||||
}
|
||||
|
||||
query getTeamHubById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
teamHub(id: $id) {
|
||||
id
|
||||
teamId
|
||||
hubName
|
||||
departments
|
||||
}
|
||||
}
|
||||
|
||||
query filterTeamHub(
|
||||
$teamId: UUID,
|
||||
$hubName: String
|
||||
) @auth(level: USER) {
|
||||
teamHubs(
|
||||
where: {
|
||||
teamId: { eq: $teamId }
|
||||
hubName: { eq: $hubName }
|
||||
}
|
||||
) {
|
||||
id
|
||||
teamId
|
||||
hubName
|
||||
departments
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
mutation CreateTeamMember(
|
||||
$teamId: UUID!,
|
||||
$memberName: String!,
|
||||
$email: String!,
|
||||
$role: TeamMemberRole,
|
||||
$isActive: Boolean
|
||||
) @auth(level: USER) {
|
||||
teamMember_insert(
|
||||
data: {
|
||||
teamId: $teamId
|
||||
memberName: $memberName
|
||||
email: $email
|
||||
role: $role
|
||||
isActive: $isActive
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateTeamMember(
|
||||
$id: UUID!,
|
||||
$teamId: UUID,
|
||||
$memberName: String,
|
||||
$email: String,
|
||||
$role: TeamMemberRole,
|
||||
$isActive: Boolean
|
||||
) @auth(level: USER) {
|
||||
teamMember_update(
|
||||
id: $id,
|
||||
data: {
|
||||
teamId: $teamId
|
||||
memberName: $memberName
|
||||
email: $email
|
||||
role: $role
|
||||
isActive: $isActive
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteTeamMember(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
teamMember_delete(id: $id)
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
query listTeamMember @auth(level: USER) {
|
||||
teamMembers {
|
||||
id
|
||||
teamId
|
||||
memberName
|
||||
email
|
||||
role
|
||||
isActive
|
||||
}
|
||||
}
|
||||
|
||||
query getTeamMemberById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
teamMember(id: $id) {
|
||||
id
|
||||
teamId
|
||||
memberName
|
||||
email
|
||||
role
|
||||
isActive
|
||||
}
|
||||
}
|
||||
|
||||
query filterTeamMember(
|
||||
$teamId: UUID,
|
||||
$memberName: String,
|
||||
$email: String,
|
||||
$role: TeamMemberRole,
|
||||
$isActive: Boolean
|
||||
) @auth(level: USER) {
|
||||
teamMembers(
|
||||
where: {
|
||||
teamId: { eq: $teamId }
|
||||
memberName: { eq: $memberName }
|
||||
email: { eq: $email }
|
||||
role: { eq: $role }
|
||||
isActive: { eq: $isActive }
|
||||
}
|
||||
) {
|
||||
id
|
||||
teamId
|
||||
memberName
|
||||
email
|
||||
role
|
||||
isActive
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
mutation CreateTeamMemberInvite(
|
||||
$teamId: UUID!,
|
||||
$email: String!,
|
||||
$inviteStatus: TeamMemberInviteStatus!
|
||||
) @auth(level: USER) {
|
||||
teamMemberInvite_insert(
|
||||
data: {
|
||||
teamId: $teamId
|
||||
email: $email
|
||||
inviteStatus: $inviteStatus
|
||||
# inviteCode se genera por default con uuidV4()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateTeamMemberInvite(
|
||||
$id: UUID!,
|
||||
$teamId: UUID,
|
||||
$email: String,
|
||||
$inviteStatus: TeamMemberInviteStatus
|
||||
) @auth(level: USER) {
|
||||
teamMemberInvite_update(
|
||||
id: $id,
|
||||
data: {
|
||||
teamId: $teamId
|
||||
email: $email
|
||||
inviteStatus: $inviteStatus
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteTeamMemberInvite(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
teamMemberInvite_delete(id: $id)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
query listTeamMemberInvite @auth(level: USER) {
|
||||
teamMemberInvites {
|
||||
id
|
||||
teamId
|
||||
inviteCode
|
||||
email
|
||||
inviteStatus
|
||||
}
|
||||
}
|
||||
|
||||
query getTeamMemberInviteById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
teamMemberInvite(id: $id) {
|
||||
id
|
||||
teamId
|
||||
inviteCode
|
||||
email
|
||||
inviteStatus
|
||||
}
|
||||
}
|
||||
|
||||
query filterTeamMemberInvite(
|
||||
$teamId: UUID,
|
||||
$email: String,
|
||||
$inviteStatus: TeamMemberInviteStatus
|
||||
) @auth(level: USER) {
|
||||
teamMemberInvites(
|
||||
where: {
|
||||
teamId: { eq: $teamId }
|
||||
email: { eq: $email }
|
||||
inviteStatus: { eq: $inviteStatus }
|
||||
}
|
||||
) {
|
||||
id
|
||||
teamId
|
||||
inviteCode
|
||||
email
|
||||
inviteStatus
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
mutation CreateUser(
|
||||
$id: String!, # Firebase UID
|
||||
$email: String!,
|
||||
$fullName: String!,
|
||||
$role: UserBaseRole!,
|
||||
$userRole: String,
|
||||
$photoUrl: String
|
||||
) @auth(level: USER) {
|
||||
user_insert(
|
||||
data: {
|
||||
id: $id
|
||||
email: $email
|
||||
fullName: $fullName
|
||||
role: $role
|
||||
userRole: $userRole
|
||||
photoUrl: $photoUrl
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateUser(
|
||||
$id: String!,
|
||||
$email: String,
|
||||
$fullName: String,
|
||||
$role: UserBaseRole,
|
||||
$userRole: String,
|
||||
$photoUrl: String
|
||||
) @auth(level: USER) {
|
||||
user_update(
|
||||
id: $id,
|
||||
data: {
|
||||
email: $email
|
||||
fullName: $fullName
|
||||
role: $role
|
||||
userRole: $userRole
|
||||
photoUrl: $photoUrl
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteUser(
|
||||
$id: String!
|
||||
) @auth(level: USER) {
|
||||
user_delete(id: $id)
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
query listUsers @auth(level: USER) {
|
||||
users {
|
||||
id
|
||||
email
|
||||
fullName
|
||||
role
|
||||
userRole
|
||||
photoUrl
|
||||
createdDate
|
||||
updatedDate
|
||||
}
|
||||
}
|
||||
|
||||
query getUserById(
|
||||
$id: String!
|
||||
) @auth(level: USER) {
|
||||
user(id: $id) {
|
||||
id
|
||||
email
|
||||
fullName
|
||||
role
|
||||
userRole
|
||||
photoUrl
|
||||
}
|
||||
}
|
||||
|
||||
query filterUsers(
|
||||
$id: String,
|
||||
$email: String,
|
||||
$role: UserBaseRole,
|
||||
$userRole: String
|
||||
) @auth(level: USER) {
|
||||
users(
|
||||
where: {
|
||||
id: { eq: $id }
|
||||
email: { eq: $email }
|
||||
role: { eq: $role }
|
||||
userRole: { eq: $userRole }
|
||||
}
|
||||
) {
|
||||
id
|
||||
email
|
||||
fullName
|
||||
role
|
||||
userRole
|
||||
photoUrl
|
||||
}
|
||||
}
|
||||
52
dataconnect/connector/vendor/mutations.gql
vendored
52
dataconnect/connector/vendor/mutations.gql
vendored
@@ -1,52 +0,0 @@
|
||||
mutation CreateVendor(
|
||||
$vendorNumber: String!,
|
||||
$legalName: String!,
|
||||
$region: VendorRegion!,
|
||||
$platformType: VendorPlatformType!,
|
||||
$primaryContactEmail: String!,
|
||||
$approvalStatus: VendorApprovalStatus!,
|
||||
$isActive: Boolean
|
||||
) @auth(level: USER) {
|
||||
vendor_insert(
|
||||
data: {
|
||||
vendorNumber: $vendorNumber
|
||||
legalName: $legalName
|
||||
region: $region
|
||||
platformType: $platformType
|
||||
primaryContactEmail: $primaryContactEmail
|
||||
approvalStatus: $approvalStatus
|
||||
isActive: $isActive
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateVendor(
|
||||
$id: UUID!,
|
||||
$vendorNumber: String,
|
||||
$legalName: String,
|
||||
$region: VendorRegion,
|
||||
$platformType: VendorPlatformType,
|
||||
$primaryContactEmail: String,
|
||||
$approvalStatus: VendorApprovalStatus,
|
||||
$isActive: Boolean
|
||||
) @auth(level: USER) {
|
||||
vendor_update(
|
||||
id: $id,
|
||||
data: {
|
||||
vendorNumber: $vendorNumber
|
||||
legalName: $legalName
|
||||
region: $region
|
||||
platformType: $platformType
|
||||
primaryContactEmail: $primaryContactEmail
|
||||
approvalStatus: $approvalStatus
|
||||
isActive: $isActive
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteVendor(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
vendor_delete(id: $id)
|
||||
}
|
||||
|
||||
57
dataconnect/connector/vendor/queries.gql
vendored
57
dataconnect/connector/vendor/queries.gql
vendored
@@ -1,57 +0,0 @@
|
||||
query listVendor @auth(level: USER) {
|
||||
vendors {
|
||||
id
|
||||
vendorNumber
|
||||
legalName
|
||||
region
|
||||
platformType
|
||||
primaryContactEmail
|
||||
approvalStatus
|
||||
isActive
|
||||
}
|
||||
}
|
||||
|
||||
query getVendorById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
vendor(id: $id) {
|
||||
id
|
||||
vendorNumber
|
||||
legalName
|
||||
region
|
||||
platformType
|
||||
primaryContactEmail
|
||||
approvalStatus
|
||||
isActive
|
||||
}
|
||||
}
|
||||
|
||||
query filterVendors(
|
||||
$region: VendorRegion,
|
||||
$approvalStatus: VendorApprovalStatus,
|
||||
$isActive: Boolean,
|
||||
$vendorNumber:String,
|
||||
$primaryContactEmail:String,
|
||||
$legalName: String,
|
||||
$platformType: VendorPlatformType
|
||||
) @auth(level: USER) {
|
||||
vendors(where:{
|
||||
region: { eq: $region }
|
||||
approvalStatus: { eq: $approvalStatus }
|
||||
isActive: { eq: $isActive }
|
||||
vendorNumber: { eq: $vendorNumber }
|
||||
primaryContactEmail: { eq: $primaryContactEmail }
|
||||
legalName: { eq: $legalName }
|
||||
platformType: { eq: $platformType }
|
||||
|
||||
}) {
|
||||
id
|
||||
vendorNumber
|
||||
legalName
|
||||
region
|
||||
platformType
|
||||
primaryContactEmail
|
||||
approvalStatus
|
||||
isActive
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
mutation CreateVendorDefaultSetting(
|
||||
$vendorName: String!,
|
||||
$defaultMarkupPercentage: Float!,
|
||||
$defaultVendorFeePercentage: Float!
|
||||
) @auth(level: USER) {
|
||||
vendorDefaultSetting_insert(
|
||||
data: {
|
||||
vendorName: $vendorName
|
||||
defaultMarkupPercentage: $defaultMarkupPercentage
|
||||
defaultVendorFeePercentage: $defaultVendorFeePercentage
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateVendorDefaultSetting(
|
||||
$id: UUID!,
|
||||
$vendorName: String,
|
||||
$defaultMarkupPercentage: Float,
|
||||
$defaultVendorFeePercentage: Float
|
||||
) @auth(level: USER) {
|
||||
vendorDefaultSetting_update(
|
||||
id: $id,
|
||||
data: {
|
||||
vendorName: $vendorName
|
||||
defaultMarkupPercentage: $defaultMarkupPercentage
|
||||
defaultVendorFeePercentage: $defaultVendorFeePercentage
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteVendorDefaultSetting(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
vendorDefaultSetting_delete(id: $id)
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
query listVendorDefaultSettings @auth(level: USER) {
|
||||
vendorDefaultSettings {
|
||||
id
|
||||
vendorName
|
||||
defaultMarkupPercentage
|
||||
defaultVendorFeePercentage
|
||||
}
|
||||
}
|
||||
|
||||
query getVendorDefaultSettingById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
vendorDefaultSetting(id: $id) {
|
||||
id
|
||||
vendorName
|
||||
defaultMarkupPercentage
|
||||
defaultVendorFeePercentage
|
||||
}
|
||||
}
|
||||
|
||||
query filterVendorDefaultSettings(
|
||||
$vendorName: String,
|
||||
$defaultMarkupPercentage: Float,
|
||||
$defaultVendorFeePercentage: Float
|
||||
) @auth(level: USER) {
|
||||
vendorDefaultSettings(
|
||||
where: {
|
||||
vendorName: { eq: $vendorName }
|
||||
defaultMarkupPercentage: { eq: $defaultMarkupPercentage }
|
||||
defaultVendorFeePercentage: { eq: $defaultVendorFeePercentage }
|
||||
}
|
||||
) {
|
||||
id
|
||||
vendorName
|
||||
defaultMarkupPercentage
|
||||
defaultVendorFeePercentage
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
mutation CreateVendorRate(
|
||||
$vendorName: String!,
|
||||
$category: VendorRateCategory!,
|
||||
$roleName: String!,
|
||||
$employeeWage: Float!,
|
||||
$markupPercentage: Float,
|
||||
$vendorFeePercentage: Float,
|
||||
$clientRate: Float!
|
||||
) @auth(level: USER) {
|
||||
vendorRate_insert(
|
||||
data: {
|
||||
vendorName: $vendorName
|
||||
category: $category
|
||||
roleName: $roleName
|
||||
employeeWage: $employeeWage
|
||||
markupPercentage: $markupPercentage
|
||||
vendorFeePercentage: $vendorFeePercentage
|
||||
clientRate: $clientRate
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateVendorRate(
|
||||
$id: UUID!,
|
||||
$vendorName: String,
|
||||
$category: VendorRateCategory,
|
||||
$roleName: String,
|
||||
$employeeWage: Float,
|
||||
$markupPercentage: Float,
|
||||
$vendorFeePercentage: Float,
|
||||
$clientRate: Float
|
||||
) @auth(level: USER) {
|
||||
vendorRate_update(
|
||||
id: $id,
|
||||
data: {
|
||||
vendorName: $vendorName
|
||||
category: $category
|
||||
roleName: $roleName
|
||||
employeeWage: $employeeWage
|
||||
markupPercentage: $markupPercentage
|
||||
vendorFeePercentage: $vendorFeePercentage
|
||||
clientRate: $clientRate
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteVendorRate(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
vendorRate_delete(id: $id)
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
query listVendorRate @auth(level: USER) {
|
||||
vendorRates {
|
||||
id
|
||||
vendorName
|
||||
category
|
||||
roleName
|
||||
employeeWage
|
||||
markupPercentage
|
||||
vendorFeePercentage
|
||||
clientRate
|
||||
}
|
||||
}
|
||||
|
||||
query getVendorRateById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
vendorRate(id: $id) {
|
||||
id
|
||||
vendorName
|
||||
category
|
||||
roleName
|
||||
employeeWage
|
||||
markupPercentage
|
||||
vendorFeePercentage
|
||||
clientRate
|
||||
createdDate
|
||||
updatedDate
|
||||
createdBy
|
||||
}
|
||||
}
|
||||
|
||||
query filterVendorRates(
|
||||
$vendorName: String,
|
||||
$category: VendorRateCategory,
|
||||
$roleName: String,
|
||||
$minClientRate: Float,
|
||||
$maxClientRate: Float
|
||||
) @auth(level: USER) {
|
||||
vendorRates(
|
||||
where: {
|
||||
vendorName: { eq: $vendorName }
|
||||
category: { eq: $category }
|
||||
roleName: { eq: $roleName }
|
||||
clientRate: { ge: $minClientRate, le: $maxClientRate }
|
||||
}
|
||||
) {
|
||||
id
|
||||
vendorName
|
||||
category
|
||||
roleName
|
||||
employeeWage
|
||||
markupPercentage
|
||||
vendorFeePercentage
|
||||
clientRate
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
mutation CreateWorkforce(
|
||||
$workforceNumber: String!,
|
||||
$vendorId: UUID!,
|
||||
$firstName: String!,
|
||||
$lastName: String!,
|
||||
$employmentType: WorkforceEmploymentType
|
||||
) @auth(level: USER) {
|
||||
workforce_insert(
|
||||
data: {
|
||||
workforceNumber: $workforceNumber
|
||||
vendorId: $vendorId
|
||||
firstName: $firstName
|
||||
lastName: $lastName
|
||||
employmentType: $employmentType
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation UpdateWorkforce(
|
||||
$id: UUID!,
|
||||
$workforceNumber: String,
|
||||
$vendorId: UUID,
|
||||
$firstName: String,
|
||||
$lastName: String,
|
||||
$employmentType: WorkforceEmploymentType
|
||||
) @auth(level: USER) {
|
||||
workforce_update(
|
||||
id: $id,
|
||||
data: {
|
||||
workforceNumber: $workforceNumber
|
||||
vendorId: $vendorId
|
||||
firstName: $firstName
|
||||
lastName: $lastName
|
||||
employmentType: $employmentType
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
mutation DeleteWorkforce(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
workforce_delete(id: $id)
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
query listWorkforce @auth(level: USER) {
|
||||
workforces {
|
||||
id
|
||||
workforceNumber
|
||||
vendorId
|
||||
firstName
|
||||
lastName
|
||||
employmentType
|
||||
}
|
||||
}
|
||||
|
||||
query getWorkforceById(
|
||||
$id: UUID!
|
||||
) @auth(level: USER) {
|
||||
workforce(id: $id) {
|
||||
id
|
||||
workforceNumber
|
||||
vendorId
|
||||
firstName
|
||||
lastName
|
||||
employmentType
|
||||
}
|
||||
}
|
||||
|
||||
query filterWorkforce(
|
||||
$workforceNumber: String,
|
||||
$vendorId: UUID,
|
||||
$firstName: String,
|
||||
$lastName: String,
|
||||
$employmentType: WorkforceEmploymentType
|
||||
) @auth(level: USER) {
|
||||
workforces(
|
||||
where: {
|
||||
workforceNumber: { eq: $workforceNumber }
|
||||
vendorId: { eq: $vendorId }
|
||||
firstName: { eq: $firstName }
|
||||
lastName: { eq: $lastName }
|
||||
employmentType: { eq: $employmentType }
|
||||
}
|
||||
) {
|
||||
id
|
||||
workforceNumber
|
||||
vendorId
|
||||
firstName
|
||||
lastName
|
||||
employmentType
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
@@ -1,8 +0,0 @@
|
||||
connectorId: example
|
||||
generate:
|
||||
javascriptSdk:
|
||||
- outputDir: ../../frontend-web/src/dataconnect-generated
|
||||
package: "@dataconnect/generated"
|
||||
packageJsonDir: ../../frontend-web
|
||||
react: true
|
||||
angular: false
|
||||
@@ -1,33 +0,0 @@
|
||||
# Example mutations for a simple movie app
|
||||
|
||||
# Create a movie based on user input
|
||||
mutation CreateMovie($title: String!, $genre: String!, $imageUrl: String!)
|
||||
@auth(level: USER_EMAIL_VERIFIED, insecureReason: "Any email verified users can create a new movie.") {
|
||||
movie_insert(data: { title: $title, genre: $genre, imageUrl: $imageUrl })
|
||||
}
|
||||
|
||||
# Upsert (update or insert) a user's username based on their auth.uid
|
||||
mutation UpsertUser($username: String!) @auth(level: USER) {
|
||||
# The "auth.uid" server value ensures that users can only register their own user.
|
||||
user_upsert(data: { id_expr: "auth.uid", username: $username })
|
||||
}
|
||||
|
||||
# Add a review for a movie
|
||||
mutation AddReview($movieId: UUID!, $rating: Int!, $reviewText: String!)
|
||||
@auth(level: USER) {
|
||||
review_upsert(
|
||||
data: {
|
||||
userId_expr: "auth.uid"
|
||||
movieId: $movieId
|
||||
rating: $rating
|
||||
reviewText: $reviewText
|
||||
# reviewDate defaults to today in the schema. No need to set it manually.
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
# Logged in user can delete their review for a movie
|
||||
mutation DeleteReview($movieId: UUID!) @auth(level: USER) {
|
||||
# The "auth.uid" server value ensures that users can only delete their own reviews.
|
||||
review_delete(key: { userId_expr: "auth.uid", movieId: $movieId })
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
# Example queries for a simple movie app.
|
||||
|
||||
# @auth() directives control who can call each operation.
|
||||
# Anyone should be able to list all movies, so the auth level is set to PUBLIC
|
||||
query ListMovies @auth(level: PUBLIC, insecureReason: "Anyone can list all movies.") {
|
||||
movies {
|
||||
id
|
||||
title
|
||||
imageUrl
|
||||
genre
|
||||
}
|
||||
}
|
||||
|
||||
# List all users, only admins should be able to list all users, so we use NO_ACCESS
|
||||
query ListUsers @auth(level: NO_ACCESS) {
|
||||
users {
|
||||
id
|
||||
username
|
||||
}
|
||||
}
|
||||
|
||||
# Logged in users can list all their reviews and movie titles associated with the review
|
||||
# Since the query uses the uid of the current authenticated user, we set auth level to USER
|
||||
query ListUserReviews @auth(level: USER) {
|
||||
user(key: { id_expr: "auth.uid" }) {
|
||||
id
|
||||
username
|
||||
# <field>_on_<foreign_key_field> makes it easy to grab info from another table
|
||||
# Here, we use it to grab all the reviews written by the user.
|
||||
reviews: reviews_on_user {
|
||||
rating
|
||||
reviewDate
|
||||
reviewText
|
||||
movie {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Get movie by id
|
||||
query GetMovieById($id: UUID!) @auth(level: PUBLIC, insecureReason: "Anyone can get a movie by id.") {
|
||||
movie(id: $id) {
|
||||
id
|
||||
title
|
||||
imageUrl
|
||||
genre
|
||||
metadata: movieMetadata_on_movie {
|
||||
rating
|
||||
releaseYear
|
||||
description
|
||||
}
|
||||
reviews: reviews_on_movie {
|
||||
reviewText
|
||||
reviewDate
|
||||
rating
|
||||
user {
|
||||
id
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Search for movies, actors, and reviews
|
||||
query SearchMovie($titleInput: String, $genre: String) @auth(level: PUBLIC, insecureReason: "Anyone can search for movies.") {
|
||||
movies(
|
||||
where: {
|
||||
_and: [{ genre: { eq: $genre } }, { title: { contains: $titleInput } }]
|
||||
}
|
||||
) {
|
||||
id
|
||||
title
|
||||
genre
|
||||
imageUrl
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
# Example schema for simple movie review app
|
||||
|
||||
# User table is keyed by Firebase Auth UID.
|
||||
type User @table {
|
||||
# `@default(expr: "auth.uid")` sets it to Firebase Auth UID during insert and upsert.
|
||||
id: String! @default(expr: "auth.uid")
|
||||
username: String! @col(dataType: "varchar(50)")
|
||||
# The `user: User!` field in the Review table generates the following one-to-many query field.
|
||||
# reviews_on_user: [Review!]!
|
||||
# The `Review` join table the following many-to-many query field.
|
||||
# movies_via_Review: [Movie!]!
|
||||
}
|
||||
|
||||
# Movie is keyed by a randomly generated UUID.
|
||||
type Movie @table {
|
||||
# If you do not pass a 'key' to `@table`, Data Connect automatically adds the following 'id' column.
|
||||
# Feel free to uncomment and customize it.
|
||||
# id: UUID! @default(expr: "uuidV4()")
|
||||
title: String!
|
||||
imageUrl: String!
|
||||
genre: String
|
||||
}
|
||||
|
||||
# MovieMetadata is a metadata attached to a Movie.
|
||||
# Movie <-> MovieMetadata is a one-to-one relationship
|
||||
type MovieMetadata @table {
|
||||
# @unique ensures each Movie can only one MovieMetadata.
|
||||
movie: Movie! @unique
|
||||
# The movie field adds the following foreign key field. Feel free to uncomment and customize it.
|
||||
# movieId: UUID!
|
||||
rating: Float
|
||||
releaseYear: Int
|
||||
description: String
|
||||
}
|
||||
|
||||
# Reviews is a join table between User and Movie.
|
||||
# It has a composite primary keys `userUid` and `movieId`.
|
||||
# A user can leave reviews for many movies. A movie can have reviews from many users.
|
||||
# User <-> Review is a one-to-many relationship
|
||||
# Movie <-> Review is a one-to-many relationship
|
||||
# Movie <-> User is a many-to-many relationship
|
||||
type Review @table(name: "Reviews", key: ["movie", "user"]) {
|
||||
user: User!
|
||||
# The user field adds the following foreign key field. Feel free to uncomment and customize it.
|
||||
# userUid: String!
|
||||
movie: Movie!
|
||||
# The movie field adds the following foreign key field. Feel free to uncomment and customize it.
|
||||
# movieId: UUID!
|
||||
rating: Int
|
||||
reviewText: String
|
||||
reviewDate: Date! @default(expr: "request.time")
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
enum VendorRateCategory {
|
||||
KITCHEN_AND_CULINARY
|
||||
CONCESSIONS
|
||||
FACILITIES
|
||||
BARTENDING
|
||||
SECURITY
|
||||
EVENT_STAFF
|
||||
MANAGEMENT
|
||||
TECHNICAL
|
||||
OTHER
|
||||
}
|
||||
|
||||
type VendorRate @table(name: "vendor_rates") {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
vendorName: String!
|
||||
category: VendorRateCategory!
|
||||
roleName: String!
|
||||
employeeWage: Float!
|
||||
markupPercentage: Float
|
||||
vendorFeePercentage: Float
|
||||
clientRate: Float!
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
enum ActivityType {
|
||||
EVENT_CREATED
|
||||
EVENT_UPDATED
|
||||
STAFF_ASSIGNED
|
||||
INVOICE_PAID
|
||||
INVOICE_CREATED
|
||||
VENDOR_APPROVED
|
||||
MESSAGE_RECEIVED
|
||||
}
|
||||
|
||||
type ActivityLog @table(name: "activity_logs") {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
title: String!
|
||||
description: String!
|
||||
activityType: ActivityType!
|
||||
userId: String! # user_id (FK lógica a User.id)
|
||||
isRead: Boolean @default(expr: "false")
|
||||
iconType: String
|
||||
iconColor: String
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
enum AssignmentStatus {
|
||||
PENDING
|
||||
CONFIRMED
|
||||
CHECKED_IN
|
||||
IN_PROGRESS
|
||||
COMPLETED
|
||||
CANCELLED
|
||||
NO_SHOW
|
||||
}
|
||||
|
||||
type Assignment @table(name: "assignments") {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
assignmentNumber: String
|
||||
orderId: UUID! # order_id (FK lógica a Order.id)
|
||||
workforceId: UUID! # workforce_id (FK lógica a Workforce.id)
|
||||
vendorId: UUID! # vendor_id (FK lógica a Vendor.id)
|
||||
role: String!
|
||||
assignmentStatus: AssignmentStatus!
|
||||
scheduledStart: Timestamp!
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
enum BusinessSector {
|
||||
BON_APPETIT
|
||||
EUREST
|
||||
ARAMARK
|
||||
EPICUREAN_GROUP
|
||||
CHARTWELLS
|
||||
OTHER
|
||||
}
|
||||
|
||||
enum BusinessRateGroup {
|
||||
STANDARD
|
||||
PREMIUM
|
||||
ENTERPRISE
|
||||
CUSTOM
|
||||
}
|
||||
|
||||
enum BusinessStatus {
|
||||
ACTIVE
|
||||
INACTIVE
|
||||
PENDING
|
||||
}
|
||||
|
||||
type Business @table(name: "business") {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
businessName: String!
|
||||
contactName: String!
|
||||
email: String
|
||||
sector: BusinessSector
|
||||
rateGroup: BusinessRateGroup!
|
||||
status: BusinessStatus
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
enum CertificationType {
|
||||
LEGAL
|
||||
OPERATIONAL
|
||||
SAFETY
|
||||
TRAINING
|
||||
LICENSE
|
||||
OTHER
|
||||
}
|
||||
|
||||
enum CertificationStatus {
|
||||
CURRENT
|
||||
EXPIRING_SOON
|
||||
EXPIRED
|
||||
PENDING_VALIDATION
|
||||
}
|
||||
|
||||
enum CertificationValidationStatus {
|
||||
APPROVED
|
||||
PENDING_EXPERT_REVIEW
|
||||
REJECTED
|
||||
AI_VERIFIED
|
||||
AI_FLAGGED
|
||||
MANUAL_REVIEW_NEEDED
|
||||
}
|
||||
|
||||
type Certification @table(name: "certification") {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
employeeName: String!
|
||||
certificationName: String!
|
||||
certificationType: CertificationType
|
||||
status: CertificationStatus
|
||||
expiryDate: String!
|
||||
validationStatus: CertificationValidationStatus
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
enum ConversationType {
|
||||
CLIENT_VENDOR
|
||||
STAFF_CLIENT
|
||||
STAFF_ADMIN
|
||||
VENDOR_ADMIN
|
||||
CLIENT_ADMIN
|
||||
GROUP_STAFF
|
||||
GROUP_EVENT_STAFF
|
||||
}
|
||||
|
||||
enum ConversationStatus {
|
||||
ACTIVE
|
||||
ARCHIVED
|
||||
CLOSED
|
||||
}
|
||||
|
||||
type Conversation @table(name: "conversations") {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
participants: String! # participants (jsonb -> String, required array of strings)
|
||||
conversationType: ConversationType!
|
||||
relatedTo: UUID! # related_to (generic FK as string)
|
||||
status: ConversationStatus
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
type Enterprise @table(name: "enterprise") {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
enterpriseNumber: String!
|
||||
enterpriseName: String!
|
||||
enterpriseCode: String!
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
enum EventStatus {
|
||||
DRAFT
|
||||
ACTIVE
|
||||
PENDING
|
||||
ASSIGNED
|
||||
CONFIRMED
|
||||
COMPLETED
|
||||
CANCELED
|
||||
PARTIAL
|
||||
PARTIAL_STAFFED
|
||||
FULLY_STAFFED
|
||||
EVENT_CREATED
|
||||
}
|
||||
|
||||
enum RecurrenceType {
|
||||
SINGLE
|
||||
DATE_RANGE
|
||||
SCATTER
|
||||
}
|
||||
|
||||
#enums cant start by a number, reason of C1099
|
||||
enum ContractType {
|
||||
W2
|
||||
C1099
|
||||
TEMP
|
||||
CONTRACT
|
||||
}
|
||||
|
||||
type Event @table(name: "events") {
|
||||
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
eventName: String!
|
||||
isRapid: Boolean @default(expr: "false")
|
||||
isRecurring: Boolean @default(expr: "false")
|
||||
isMultiDay: Boolean @default(expr: "false")
|
||||
recurrenceType: RecurrenceType
|
||||
recurrenceStartDate: Timestamp
|
||||
recurrenceEndDate: Timestamp
|
||||
scatterDates: Any
|
||||
multiDayStartDate: Timestamp
|
||||
multiDayEndDate: Timestamp
|
||||
bufferTimeBefore: Float @default(expr: "0")
|
||||
bufferTimeAfter: Float @default(expr: "0")
|
||||
conflictDetectionEnabled: Boolean @default(expr: "true")
|
||||
detectedConflicts: Any
|
||||
businessId: UUID!
|
||||
businessName: String
|
||||
vendorId: String @default(expr: "auth.uid")
|
||||
vendorName: String
|
||||
hub: String
|
||||
eventLocation: String
|
||||
contractType: ContractType
|
||||
poReference: String
|
||||
status: EventStatus!
|
||||
date: String!
|
||||
shifts: Any
|
||||
addons: Any
|
||||
total: Float
|
||||
clientName: String
|
||||
clientEmail: String
|
||||
clientPhone: String
|
||||
invoiceId: UUID
|
||||
notes: String
|
||||
requested: Int @default(expr: "0")
|
||||
assignedStaff: Any
|
||||
orderType: String
|
||||
department: String
|
||||
recurringStartDate: String
|
||||
recurringEndDate: String
|
||||
recurringDays: Any
|
||||
permanentStartDate: String
|
||||
permanentDays: Any
|
||||
includeBackup: Boolean
|
||||
backupStaffCount: Int
|
||||
recurringTime: String
|
||||
permanentTime: String
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
enum InvoiceStatus {
|
||||
DRAFT
|
||||
PENDING_REVIEW
|
||||
APPROVED
|
||||
DISPUTED
|
||||
UNDER_REVIEW
|
||||
RESOLVED
|
||||
OVERDUE
|
||||
PAID
|
||||
RECONCILED
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
type Invoice @table(name: "invoices") {
|
||||
id: UUID! @default(expr: "uuidV4()")
|
||||
invoiceNumber: String!
|
||||
amount: Float!
|
||||
status: InvoiceStatus!
|
||||
issueDate: Timestamp!
|
||||
dueDate: Timestamp!
|
||||
disputedItems: String
|
||||
isAutoGenerated: Boolean @default(expr: "false") # is_auto_generated
|
||||
createdDate: Timestamp @default(expr: "request.time")
|
||||
updatedDate: Timestamp @default(expr: "request.time")
|
||||
createdBy: String @default(expr: "auth.uid")
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user