Istruzioni copilot
This commit is contained in:
+425
-42
@@ -1,67 +1,450 @@
|
|||||||
# GitHub Copilot Instructions — Fixiy
|
# GitHub Copilot Instructions — Fixiy
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Fixiy is a MAUI Blazor Hybrid application with a shared codebase.
|
||||||
|
|
||||||
|
### Solution Structure
|
||||||
|
|
||||||
|
* `Fixiy.Shared` contains:
|
||||||
|
|
||||||
|
* Business logic
|
||||||
|
* Razor pages
|
||||||
|
* Shared components
|
||||||
|
* DTOs
|
||||||
|
* Interfaces
|
||||||
|
* Service abstractions
|
||||||
|
|
||||||
|
* `Fixiy.Maui` is the MAUI host application.
|
||||||
|
|
||||||
|
* `Fixiy.Web` is the ASP.NET Core host application.
|
||||||
|
|
||||||
|
The Shared project is the source of truth. Avoid duplicating logic between hosts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agent Behaviour
|
||||||
|
|
||||||
|
* Before making changes, inspect the existing implementation and follow established patterns.
|
||||||
|
* Prefer extending existing functionality over creating new implementations.
|
||||||
|
* Make the smallest change necessary to satisfy the requirement.
|
||||||
|
* Never rewrite large portions of working code unless explicitly requested.
|
||||||
|
* Search for existing services, DTOs, components, pages and interfaces before creating new ones.
|
||||||
|
* Never create duplicate functionality.
|
||||||
|
* Do not rename public classes, interfaces, routes, pages or services without verifying all usages.
|
||||||
|
* When requirements are unclear, ask for clarification instead of making assumptions.
|
||||||
|
* Preserve the existing architecture.
|
||||||
|
* Do not move files between projects unless explicitly requested.
|
||||||
|
* Do not generate placeholder implementations containing TODO comments unless specifically requested.
|
||||||
|
* Always check whether a change affects both MAUI and Web hosts.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Language and Style
|
## Language and Style
|
||||||
|
|
||||||
- **C# 12+** with `<Nullable>enable</Nullable>` and `<ImplicitUsings>enable</ImplicitUsings>` throughout. Never disable these per-file without strong justification.
|
* Use C# 12+.
|
||||||
- Use **file-scoped namespaces** (`namespace Fixiy.Shared.Services;`) not block-scoped.
|
* Always keep:
|
||||||
- Prefer `record` types for immutable DTOs.
|
|
||||||
- Use `async`/`await` consistently — never `.Result` or `.Wait()` on Tasks.
|
```xml
|
||||||
- Remove unused `using` directives.
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
```
|
||||||
|
|
||||||
|
* Never disable nullable reference types without strong justification.
|
||||||
|
* Use file-scoped namespaces:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
namespace Fixiy.Shared.Services;
|
||||||
|
```
|
||||||
|
|
||||||
|
* Never use block-scoped namespaces.
|
||||||
|
* Prefer `record` types for immutable DTOs.
|
||||||
|
* Use expression-bodied members when they improve readability.
|
||||||
|
* Use collection expressions when appropriate.
|
||||||
|
* Use `async`/`await` consistently.
|
||||||
|
* Never use `.Result`, `.Wait()` or `.GetAwaiter().GetResult()`.
|
||||||
|
* Remove unused `using` directives.
|
||||||
|
* One type per file.
|
||||||
|
* File names must match type names.
|
||||||
|
* Constants use PascalCase.
|
||||||
|
* Do not use Hungarian notation.
|
||||||
|
* Omit the `private` modifier on fields.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Blazor Component Conventions
|
## Blazor Component Conventions
|
||||||
|
|
||||||
- All shared components live in `Fixiy.Shared/Components/`. Do not create components in `Fixiy.Maui` or `Fixiy.Web`.
|
### Component Locations
|
||||||
- Pages go in `Fixiy.Shared/Components/Pages/`, layout in `Layout/`, reusable elements in `SingleElements/`.
|
|
||||||
- Scoped CSS goes in a matching `.razor.css` file alongside the component.
|
Shared components must live inside:
|
||||||
- Inject services via `@inject` in `.razor` files — Blazor components do not support constructor injection.
|
|
||||||
- Prefer `[Parameter]` for component inputs; avoid cascading parameters unless genuinely needed across deep trees.
|
```text
|
||||||
|
Fixiy.Shared/Components/
|
||||||
|
```
|
||||||
|
|
||||||
|
Never create reusable components in:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Maui
|
||||||
|
Fixiy.Web
|
||||||
|
```
|
||||||
|
|
||||||
|
### Structure
|
||||||
|
|
||||||
|
Pages:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Shared/Components/Pages/
|
||||||
|
```
|
||||||
|
|
||||||
|
Layouts:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Shared/Components/Layout/
|
||||||
|
```
|
||||||
|
|
||||||
|
Reusable elements:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Shared/Components/SingleElements/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Styling
|
||||||
|
|
||||||
|
* Scoped styles must use matching `.razor.css` files.
|
||||||
|
* Keep component-specific styling inside scoped CSS whenever possible.
|
||||||
|
|
||||||
|
### Dependency Injection
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```razor
|
||||||
|
@inject IService Service
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not attempt constructor injection in Razor components.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
* Prefer `[Parameter]`.
|
||||||
|
* Avoid `CascadingParameter` unless truly necessary across multiple levels.
|
||||||
|
|
||||||
|
### Code Organization
|
||||||
|
|
||||||
|
* Keep `@code` blocks small.
|
||||||
|
* Extract complex logic into:
|
||||||
|
|
||||||
|
* `.razor.cs`
|
||||||
|
* Service classes
|
||||||
|
* ViewModels
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Render Mode Rules
|
## Render Mode Rules
|
||||||
|
|
||||||
- **Always use `InteractiveRenderSettings.*` properties** (`@InteractiveServer`, `@InteractiveAuto`, `@InteractiveWebAssembly`) in shared components — never hard-coded `RenderMode.*` constants.
|
Always use:
|
||||||
- `Fixiy.Maui/MauiProgram.cs` calls `ConfigureBlazorHybridRenderModes()` which sets all three properties to `null`. This is intentional — MAUI Blazor Hybrid runs components statically.
|
|
||||||
- Do not work around the null render modes in shared code. Components that need interactivity must tolerate `null` render mode in MAUI context.
|
```razor
|
||||||
|
@InteractiveServer
|
||||||
|
@InteractiveAuto
|
||||||
|
@InteractiveWebAssembly
|
||||||
|
```
|
||||||
|
|
||||||
|
through:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
InteractiveRenderSettings
|
||||||
|
```
|
||||||
|
|
||||||
|
Never use:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
RenderMode.Server
|
||||||
|
RenderMode.Auto
|
||||||
|
RenderMode.WebAssembly
|
||||||
|
```
|
||||||
|
|
||||||
|
directly.
|
||||||
|
|
||||||
|
### Important
|
||||||
|
|
||||||
|
`Fixiy.Maui/MauiProgram.cs` calls:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
ConfigureBlazorHybridRenderModes()
|
||||||
|
```
|
||||||
|
|
||||||
|
which intentionally sets render modes to `null`.
|
||||||
|
|
||||||
|
This is required for MAUI Blazor Hybrid.
|
||||||
|
|
||||||
|
Do not:
|
||||||
|
|
||||||
|
* Replace null render modes
|
||||||
|
* Add workarounds
|
||||||
|
* Introduce MAUI-specific render mode hacks
|
||||||
|
|
||||||
|
All shared components must tolerate null render modes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MAUI Blazor Hybrid Rules
|
||||||
|
|
||||||
|
* Navigation must remain compatible with iOS swipe-back gestures.
|
||||||
|
|
||||||
|
* Prefer native MAUI navigation for secondary pages.
|
||||||
|
|
||||||
|
* Use PushAsync for stack navigation.
|
||||||
|
|
||||||
|
* Do not introduce JavaScript solutions when a MAUI or Blazor solution exists.
|
||||||
|
|
||||||
|
* Shared components must work identically in:
|
||||||
|
|
||||||
|
* MAUI Hybrid
|
||||||
|
* ASP.NET Core Server
|
||||||
|
* WebAssembly
|
||||||
|
|
||||||
|
* Never introduce host-specific code into shared components.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## MVVM Guidelines
|
||||||
|
|
||||||
|
* Business logic must not live inside Razor pages.
|
||||||
|
* Complex state management belongs in services or ViewModels.
|
||||||
|
* UI components should focus on presentation.
|
||||||
|
* Keep ViewModels platform-independent.
|
||||||
|
* Avoid code duplication between ViewModels and services.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## IFormFactor Platform Abstraction
|
## IFormFactor Platform Abstraction
|
||||||
|
|
||||||
- Platform-specific device info must be accessed via `IFormFactor` injection (`Fixiy.Shared/Interfaces/IFormFactor.cs`).
|
Platform-specific functionality must be accessed through:
|
||||||
- **Never call `DeviceInfo`, `Connectivity`, `FileSystem`, or any `Microsoft.Maui.*` API from `Fixiy.Shared`.**
|
|
||||||
- When adding new platform capabilities: define interface in `Fixiy.Shared/Interfaces/` → implement in both `Fixiy.Maui/Services/` and `Fixiy.Web/Services/` → register in both DI roots.
|
```csharp
|
||||||
|
IFormFactor
|
||||||
|
```
|
||||||
|
|
||||||
|
located in:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Shared/Interfaces/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Forbidden in Shared
|
||||||
|
|
||||||
|
Never directly access:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
DeviceInfo
|
||||||
|
Connectivity
|
||||||
|
FileSystem
|
||||||
|
Permissions
|
||||||
|
Launcher
|
||||||
|
Preferences
|
||||||
|
SecureStorage
|
||||||
|
Microsoft.Maui.*
|
||||||
|
```
|
||||||
|
|
||||||
|
from:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Shared
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding New Platform Features
|
||||||
|
|
||||||
|
Always follow this process:
|
||||||
|
|
||||||
|
1. Create interface in:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Shared/Interfaces/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Implement in:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Maui/Services/
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Implement in:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Fixiy.Web/Services/
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Register in both DI roots.
|
||||||
|
|
||||||
|
Do not skip any step.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependency Injection
|
||||||
|
|
||||||
|
### Service Registration
|
||||||
|
|
||||||
|
Always verify registrations in both hosts.
|
||||||
|
|
||||||
|
### Lifetimes
|
||||||
|
|
||||||
|
#### MAUI
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Singleton
|
||||||
|
```
|
||||||
|
|
||||||
|
for platform services.
|
||||||
|
|
||||||
|
#### Web
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
Scoped
|
||||||
|
```
|
||||||
|
|
||||||
|
for platform services.
|
||||||
|
|
||||||
|
### Interfaces
|
||||||
|
|
||||||
|
Interfaces must not assume any specific lifetime.
|
||||||
|
|
||||||
|
### Injection
|
||||||
|
|
||||||
|
Prefer:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
IService
|
||||||
|
```
|
||||||
|
|
||||||
|
over concrete implementations.
|
||||||
|
|
||||||
|
Never inject a concrete type when an abstraction exists.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## IntegryApiClient Registration
|
## IntegryApiClient Registration
|
||||||
|
|
||||||
- Register with the same `appToken` and `useLoginAzienda: true` in both hosts.
|
Use the same configuration in both hosts.
|
||||||
- MAUI: `.UseIntegry(appToken, useLoginAzienda: true)` on the `MauiAppBuilder` chain.
|
|
||||||
- Web: `builder.Services.UseIntegry(appToken, useLoginAzienda: true)` in `Program.cs`.
|
|
||||||
- One registration per DI root — do not call it twice.
|
|
||||||
|
|
||||||
## Service Registration Lifetimes
|
### MAUI
|
||||||
|
|
||||||
- `Fixiy.Maui` registers platform services as **`Singleton`** — the MAUI app has a single long-lived process.
|
```csharp
|
||||||
- `Fixiy.Web` registers platform services as **`Scoped`** — ASP.NET Core server-side per-request scope.
|
.UseIntegry(appToken, useLoginAzienda: true)
|
||||||
- Interfaces must not assume a specific lifetime; implementations may.
|
```
|
||||||
|
|
||||||
|
### Web
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
builder.Services.UseIntegry(
|
||||||
|
appToken,
|
||||||
|
useLoginAzienda: true)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rules
|
||||||
|
|
||||||
|
* One registration per host.
|
||||||
|
* Never register twice.
|
||||||
|
* Always keep app tokens aligned.
|
||||||
|
* Always keep versions aligned.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data Access Guidelines
|
||||||
|
|
||||||
|
### Entity Framework
|
||||||
|
|
||||||
|
* Prefer async APIs.
|
||||||
|
* Use `AsNoTracking()` for read-only queries.
|
||||||
|
* Avoid loading entire tables into memory.
|
||||||
|
* Avoid N+1 query patterns.
|
||||||
|
* Prefer projections over loading full entities when possible.
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
|
||||||
|
* Minimize allocations.
|
||||||
|
* Reuse existing services.
|
||||||
|
* Avoid unnecessary LINQ enumerations.
|
||||||
|
* Prefer server-side filtering.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
* Use exceptions only for exceptional situations.
|
||||||
|
* Validate inputs early.
|
||||||
|
* Log meaningful information.
|
||||||
|
* Never swallow exceptions silently.
|
||||||
|
* Preserve stack traces.
|
||||||
|
|
||||||
|
Do not write:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Maintenance Matrix
|
## Maintenance Matrix
|
||||||
|
|
||||||
| Change | Cascades to |
|
| Change | Cascades To |
|
||||||
|--------|-------------|
|
| ----------------------------------------- | ----------------------------------------------------------------- |
|
||||||
| Add/modify `Fixiy.Shared/Interfaces/*.cs` | Both `Fixiy.Maui/Services/` and `Fixiy.Web/Services/` implementations + DI registration in both hosts |
|
| Add/modify `Fixiy.Shared/Interfaces/*.cs` | Update MAUI implementation + Web implementation + DI registration |
|
||||||
| Modify `InteractiveRenderSettings.cs` | `MauiProgram.ConfigureBlazorHybridRenderModes()` — must null every new property |
|
| Modify `InteractiveRenderSettings.cs` | Update `ConfigureBlazorHybridRenderModes()` |
|
||||||
| Add a new shared page | `Fixiy.Shared/Components/Pages/` → nav link in `NavMenu.razor` if user-accessible |
|
| Add shared page | Add navigation entry if user accessible |
|
||||||
| Add a NuGet package | Target `.csproj` file; check private NuGet feed has it |
|
| Add shared service | Verify registration in both hosts |
|
||||||
| Change IntegryApiClient version | All three `.csproj` files (`Fixiy.Maui`, `Fixiy.Shared`, `Fixiy.Web`) |
|
| Add platform capability | Interface + MAUI implementation + Web implementation |
|
||||||
| Modify `_Imports.razor` | Verify no MAUI-only or web-only namespaces are introduced |
|
| Add NuGet package | Verify target project and feed availability |
|
||||||
| Update app token | `Fixiy.Maui/MauiProgram.cs` `AppToken` const + `Fixiy.Web/Program.cs` `appToken` const |
|
| Change IntegryApiClient version | Update all project references |
|
||||||
|
| Modify `_Imports.razor` | Ensure no host-specific namespaces are introduced |
|
||||||
|
| Update app token | Update both hosts |
|
||||||
|
|
||||||
## Test Conventions
|
---
|
||||||
|
|
||||||
- No test projects are currently configured. When adding tests, use **xUnit** with **bUnit** for Razor component testing.
|
## Testing Conventions
|
||||||
- Test projects should reference `Fixiy.Shared` and provide mock implementations of `IFormFactor`.
|
|
||||||
- Use `Moq` or `NSubstitute` for mocking; do not create manual stubs unless the interface is trivial.
|
|
||||||
|
|
||||||
## Code Style Notes
|
Current solution has no dedicated test projects.
|
||||||
|
|
||||||
- Omit the `private` modifier on fields — it is the default in C#.
|
When adding tests:
|
||||||
- Constants: `PascalCase` for class-level `const`, no Hungarian notation.
|
|
||||||
- One type per file; file name matches type name.
|
### Frameworks
|
||||||
- Keep `@code` blocks in `.razor` files focused — extract complex logic to a `*.razor.cs` code-behind or a separate service class.
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
* xUnit
|
||||||
|
* bUnit
|
||||||
|
* Moq or NSubstitute
|
||||||
|
|
||||||
|
### Requirements
|
||||||
|
|
||||||
|
* Test projects should reference `Fixiy.Shared`.
|
||||||
|
* Mock `IFormFactor`.
|
||||||
|
* Avoid manual stubs unless interfaces are trivial.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code Review Checklist
|
||||||
|
|
||||||
|
Before completing a task verify:
|
||||||
|
|
||||||
|
* Existing patterns were followed.
|
||||||
|
* No duplicate services were created.
|
||||||
|
* No duplicate DTOs were created.
|
||||||
|
* No duplicate pages were created.
|
||||||
|
* No duplicate components were created.
|
||||||
|
* Shared code contains no MAUI-specific APIs.
|
||||||
|
* DI registrations are correct.
|
||||||
|
* Both hosts were updated when required.
|
||||||
|
* Nullable reference types remain enabled.
|
||||||
|
* Async APIs are used correctly.
|
||||||
|
* Render mode rules were respected.
|
||||||
|
* Navigation compatibility remains intact.
|
||||||
|
* No unnecessary files were added.
|
||||||
|
* No working code was rewritten unnecessarily.
|
||||||
|
* The solution architecture remains consistent.
|
||||||
|
|||||||
Reference in New Issue
Block a user