refactor: restructure monorepo to align with industry standards
This commit restructures the monorepo to improve organization, maintainability, and scalability. The changes include: - Moving mobile apps from `mobile-apps/` to `apps/mobile-*`. - Moving the web dashboard from `admin-web/` and `frontend-web/` to `apps/web-dashboard/`. - Moving Firebase-related files to the root `firebase/` directory. - Adding a `.geminiignore` file to exclude unnecessary files from Gemini analysis. - Updating `.gitignore` to reflect the new structure and exclude sensitive files. - Updating `codemagic.yaml` to reflect the new app locations. - Adding a `make help` command to the root directory. - Adding a `make install-git-hooks` command to install git hooks. - Adding a `docs/02-codemagic-env-vars.md` file to document Codemagic environment variables. - Adding a `docs/03-contributing.md` file to document contribution guidelines. - Adding prototype placeholders to the internal launchpad. - Updating the `README.md` file to reflect the new structure and provide updated instructions. These changes improve the overall structure of the monorepo and make it easier to develop, maintain, and scale the KROW Workforce platform.
This commit is contained in:
8
internal/api-harness/.env.staging
Normal file
8
internal/api-harness/.env.staging
Normal file
@@ -0,0 +1,8 @@
|
||||
VITE_HARNESS_FIREBASE_API_KEY="AIzaSyC43vK-6gwtLcPoDHFAUH4g2vBj6YrRN2A"
|
||||
VITE_HARNESS_FIREBASE_AUTH_DOMAIN="krow-workforce-staging.firebaseapp.com"
|
||||
VITE_HARNESS_FIREBASE_PROJECT_ID="krow-workforce-staging"
|
||||
VITE_HARNESS_FIREBASE_STORAGE_BUCKET="krow-workforce-staging.firebasestorage.app"
|
||||
VITE_HARNESS_FIREBASE_MESSAGING_SENDER_ID="1032971403708"
|
||||
VITE_HARNESS_FIREBASE_APP_ID="1:1032971403708:web:7f877b82b3f5dbee356bb9"
|
||||
VITE_HARNESS_ENVIRONMENT="staging"
|
||||
VITE_API_BASE_URL="http://localhost:8080"
|
||||
24
internal/api-harness/.gitignore
vendored
24
internal/api-harness/.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?
|
||||
@@ -24,6 +24,40 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Prototypes",
|
||||
"iconColorClass": "bg-indigo-100",
|
||||
"iconPath": "assets/images/icon-design.svg",
|
||||
"links": [
|
||||
{
|
||||
"title": "Mobile Client MVP",
|
||||
"url": "/prototypes/mobile/client/index.html",
|
||||
"badge": "Concept",
|
||||
"badgeColorClass": "bg-blue-500",
|
||||
"containerClass": "bg-gradient-to-r from-blue-50 to-indigo-100 hover:from-blue-100 hover:to-indigo-200",
|
||||
"iconClass": "w-2 h-2 bg-blue-500 rounded-full",
|
||||
"textHoverClass": "group-hover:text-blue-700"
|
||||
},
|
||||
{
|
||||
"title": "Mobile Staff MVP",
|
||||
"url": "/prototypes/mobile/staff/index.html",
|
||||
"badge": "Concept",
|
||||
"badgeColorClass": "bg-green-500",
|
||||
"containerClass": "bg-gradient-to-r from-green-50 to-emerald-100 hover:from-green-100 hover:to-emerald-200",
|
||||
"iconClass": "w-2 h-2 bg-green-500 rounded-full",
|
||||
"textHoverClass": "group-hover:text-green-700"
|
||||
},
|
||||
{
|
||||
"title": "Web Dashboard MVP",
|
||||
"url": "/prototypes/web/index.html",
|
||||
"badge": "Concept",
|
||||
"badgeColorClass": "bg-purple-500",
|
||||
"containerClass": "bg-gradient-to-r from-purple-50 to-fuchsia-100 hover:from-purple-100 hover:to-fuchsia-200",
|
||||
"iconClass": "w-2 h-2 bg-purple-500 rounded-full",
|
||||
"textHoverClass": "group-hover:text-purple-700"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Legacy Mobile Apps",
|
||||
"iconColorClass": "bg-green-100",
|
||||
@@ -93,7 +127,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Design",
|
||||
"title": "Legacy Design",
|
||||
"iconColorClass": "bg-pink-100",
|
||||
"iconPath": "assets/images/icon-design.svg",
|
||||
"links": [
|
||||
@@ -142,4 +176,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -218,35 +218,3 @@ flowchart TD
|
||||
B5 --> E5[Display profile information];
|
||||
end
|
||||
```
|
||||
|
||||
## G. Replacing or Plugging in a New Backend: Considerations & Recommendations
|
||||
|
||||
This section provides guidance on how to replace the current GraphQL + Firebase backend with a different backend solution.
|
||||
|
||||
### Tightly Coupled Components
|
||||
|
||||
* **`ApiClient`:** This class is tightly coupled to `graphql_flutter`.
|
||||
* **Firebase Auth:** The authentication logic is directly tied to the `firebase_auth` package.
|
||||
* **BLoCs:** Some BLoCs might have direct dependencies on Firebase or GraphQL-specific models.
|
||||
|
||||
### Abstraction Recommendations
|
||||
|
||||
To make the architecture more backend-agnostic, the following abstractions should be implemented:
|
||||
|
||||
* **Repositories:** Create an abstract `Repository` class for each feature in the `domain` layer. The implementation of this repository will be in the `data` layer. The BLoCs should only depend on the abstract repository.
|
||||
* **Authentication Service:** Create an abstract `AuthService` class that defines the methods for authentication (e.g., `signIn`, `signOut`, `getToken`). The implementation of this service will be in the `data` layer and will use the specific authentication provider (e.g., Firebase Auth, OAuth).
|
||||
* **Data Transfer Objects (DTOs):** Use DTOs to transfer data between the data layer and the domain layer. This will prevent the domain layer from having dependencies on backend-specific models.
|
||||
|
||||
### Suggested Design Improvements
|
||||
|
||||
* **Formalize Clean Architecture:** While the current architecture has elements of Clean Architecture, it could be more formally implemented by creating a clear separation between the `domain`, `data`, and `presentation` layers for all features.
|
||||
* **Introduce Use Cases:** Introduce `UseCase` classes in the `domain` layer to encapsulate specific business operations. This will make the BLoCs simpler and more focused on state management.
|
||||
|
||||
### Migration Strategies
|
||||
|
||||
To replace the current backend with a new one (e.g., REST API, Supabase), follow these steps:
|
||||
|
||||
1. **Implement New Repositories:** Create new implementations of the repository interfaces for the new backend.
|
||||
2. **Implement New Auth Service:** Create a new implementation of the `AuthService` interface for the new authentication provider.
|
||||
3. **Update Dependency Injection:** Use dependency injection (e.g., `get_it` and `injectable`) to provide the new repository and auth service implementations to the BLoCs.
|
||||
4. **Gradual Migration:** If possible, migrate one feature at a time to the new backend. This will reduce the risk of breaking the entire application at once.
|
||||
|
||||
@@ -85,36 +85,3 @@ The application uses the **Bloc** library for state management.
|
||||
2. **Logic:** The `ShiftsBloc` requests a list of shifts.
|
||||
3. **Backend:** The use case calls the `ShiftsRepository`, which sends a `getShifts` query to the GraphQL server. The server fetches the shifts from Firestore.
|
||||
4. **Response:** The GraphQL server returns the list of shifts, which is then displayed on the UI.
|
||||
|
||||
## G. Replacing or Plugging in a New Backend: Considerations & Recommendations
|
||||
|
||||
This section provides guidance on how to replace the current GraphQL + Firebase backend with a different solution (e.g., REST, Supabase, Hasura).
|
||||
|
||||
### Tightly Coupled Components
|
||||
|
||||
- **Data Layer:** The current `ApiProvider` implementations are tightly coupled to the GraphQL API.
|
||||
- **Authentication:** The authentication flow is tightly coupled to Firebase Auth.
|
||||
- **DTOs:** The data transfer objects are generated based on the GraphQL schema.
|
||||
|
||||
### Abstraction Recommendations
|
||||
|
||||
To make the architecture more backend-agnostic, the following components should be abstracted:
|
||||
|
||||
- **Repositories:** The repository interfaces in the Domain Layer should remain unchanged. The implementations in the Data Layer will need to be rewritten for the new backend.
|
||||
- **Services:** Services like authentication should be abstracted behind an interface. For example, an `AuthService` interface can be defined in the Domain Layer, with a `FirebaseAuthService` implementation in the Data Layer.
|
||||
- **DTOs:** The DTOs should be mapped to domain entities in the Data Layer. This ensures that the Domain Layer is not affected by changes in the backend's data model.
|
||||
- **Error Handling:** A generic error handling mechanism should be implemented to handle different types of backend errors.
|
||||
|
||||
### Suggested Design Improvements
|
||||
|
||||
- **Introduce a Service Locator:** Use a service locator like `get_it` to decouple the layers and make it easier to swap out implementations.
|
||||
- **Define Abstract Data Sources:** Instead of directly calling the API client in the repository implementations, introduce abstract data source interfaces (e.g., `UserRemoteDataSource`). This adds another layer of abstraction and makes the repositories more testable.
|
||||
|
||||
### Migration Strategies
|
||||
|
||||
1. **Define Interfaces:** Start by defining abstract interfaces for all backend interactions (repositories, services).
|
||||
2. **Implement New Data Layer:** Create a new implementation of the Data Layer for the new backend. This will involve writing new repository implementations, API clients, and DTOs.
|
||||
3. **Swap Implementations:** Use the service locator to swap the old Data Layer implementation with the new one.
|
||||
4. **Test:** Thoroughly test the application to ensure that everything works as expected with the new backend.
|
||||
|
||||
By following these recommendations, the Krow Mobile Staff App can be migrated to a new backend with minimal impact on the overall architecture and business logic.
|
||||
|
||||
22
internal/launchpad/prototypes/mobile/client/index.html
Normal file
22
internal/launchpad/prototypes/mobile/client/index.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>KROW Mobile Client - Prototype</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
<body class="bg-gray-100 flex items-center justify-center h-screen">
|
||||
<div class="text-center p-8 bg-white rounded-xl shadow-lg max-w-md">
|
||||
<div class="w-16 h-16 bg-blue-100 text-blue-600 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z"></path></svg>
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold text-gray-900 mb-2">Mobile Client App</h1>
|
||||
<p class="text-gray-500 mb-6">Interactive prototype placeholder.</p>
|
||||
<div class="animate-pulse flex space-x-4 justify-center">
|
||||
<div class="h-2 bg-gray-200 rounded w-12"></div>
|
||||
<div class="h-2 bg-gray-200 rounded w-12"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
22
internal/launchpad/prototypes/mobile/staff/index.html
Normal file
22
internal/launchpad/prototypes/mobile/staff/index.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>KROW Mobile Staff - Prototype</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
<body class="bg-gray-100 flex items-center justify-center h-screen">
|
||||
<div class="text-center p-8 bg-white rounded-xl shadow-lg max-w-md">
|
||||
<div class="w-16 h-16 bg-green-100 text-green-600 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg>
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold text-gray-900 mb-2">Mobile Staff App</h1>
|
||||
<p class="text-gray-500 mb-6">Interactive prototype placeholder.</p>
|
||||
<div class="animate-pulse flex space-x-4 justify-center">
|
||||
<div class="h-2 bg-gray-200 rounded w-12"></div>
|
||||
<div class="h-2 bg-gray-200 rounded w-12"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
22
internal/launchpad/prototypes/web/index.html
Normal file
22
internal/launchpad/prototypes/web/index.html
Normal file
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>KROW Web Dashboard - Prototype</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
</head>
|
||||
<body class="bg-gray-100 flex items-center justify-center h-screen">
|
||||
<div class="text-center p-8 bg-white rounded-xl shadow-lg max-w-md">
|
||||
<div class="w-16 h-16 bg-purple-100 text-purple-600 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg>
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold text-gray-900 mb-2">Web Dashboard</h1>
|
||||
<p class="text-gray-500 mb-6">Interactive prototype placeholder.</p>
|
||||
<div class="animate-pulse flex space-x-4 justify-center">
|
||||
<div class="h-2 bg-gray-200 rounded w-12"></div>
|
||||
<div class="h-2 bg-gray-200 rounded w-12"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user