Compare commits
2 Commits
00e5ce6b20
...
357d346787
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
357d346787 | ||
|
|
23d9f2f66f |
@@ -1,20 +1,13 @@
|
|||||||
import { InjectionToken, inject } from '@angular/core';
|
import { InjectionToken, inject } from '@angular/core';
|
||||||
import { RuntimeProviderStrategyService } from '../providers/runtime-provider-strategy.service';
|
|
||||||
import { ApiCategoryRepository } from './repositories/api-category.repository';
|
import { ApiCategoryRepository } from './repositories/api-category.repository';
|
||||||
import { CategoryRepository } from './repositories/category.repository';
|
import { CategoryRepository } from './repositories/category.repository';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No mock CategoryRepository implementation exists - same dead branch as
|
||||||
|
* PRODUCT_DATA_PROVIDER. Always resolved to the real API repository
|
||||||
|
* regardless of getCategoryProviderMode(); removed the dead switch.
|
||||||
|
*/
|
||||||
export const CATEGORY_REPOSITORY = new InjectionToken<CategoryRepository>('CATEGORY_REPOSITORY', {
|
export const CATEGORY_REPOSITORY = new InjectionToken<CategoryRepository>('CATEGORY_REPOSITORY', {
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
factory: () => {
|
factory: () => inject(ApiCategoryRepository)
|
||||||
const strategy = inject(RuntimeProviderStrategyService);
|
|
||||||
const apiRepository = inject(ApiCategoryRepository);
|
|
||||||
|
|
||||||
switch (strategy.getCategoryProviderMode()) {
|
|
||||||
case 'mock':
|
|
||||||
case 'remote-config':
|
|
||||||
case 'api':
|
|
||||||
default:
|
|
||||||
return apiRepository;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
@@ -1,20 +1,14 @@
|
|||||||
import { InjectionToken, inject } from '@angular/core';
|
import { InjectionToken, inject } from '@angular/core';
|
||||||
import { RuntimeProviderStrategyService } from '../providers/runtime-provider-strategy.service';
|
|
||||||
import { ApiProductDataProvider } from './providers/api-product-data.provider';
|
import { ApiProductDataProvider } from './providers/api-product-data.provider';
|
||||||
import { ProductDataProvider } from './providers/product-data-provider.interface';
|
import { ProductDataProvider } from './providers/product-data-provider.interface';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No mock ProductDataProvider implementation exists - RuntimeProviderStrategyService.
|
||||||
|
* getProductProviderMode() can report 'mock', but there was never a branch that acted
|
||||||
|
* on it, so this always resolved to the real API provider regardless. Removed the dead
|
||||||
|
* switch instead of leaving code that implies a mock mode which doesn't exist.
|
||||||
|
*/
|
||||||
export const PRODUCT_DATA_PROVIDER = new InjectionToken<ProductDataProvider>('PRODUCT_DATA_PROVIDER', {
|
export const PRODUCT_DATA_PROVIDER = new InjectionToken<ProductDataProvider>('PRODUCT_DATA_PROVIDER', {
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
factory: () => {
|
factory: () => inject(ApiProductDataProvider)
|
||||||
const strategy = inject(RuntimeProviderStrategyService);
|
|
||||||
const apiProvider = inject(ApiProductDataProvider);
|
|
||||||
|
|
||||||
switch (strategy.getProductProviderMode()) {
|
|
||||||
case 'mock':
|
|
||||||
case 'remote-config':
|
|
||||||
case 'api':
|
|
||||||
default:
|
|
||||||
return apiProvider;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { UUID } from '../../../../shared/types/primitive.types';
|
||||||
|
|
||||||
export type AdminOrderStatus = 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled' | 'refunded';
|
export type AdminOrderStatus = 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled' | 'refunded';
|
||||||
export type AdminOrderPaymentStatus = 'unpaid' | 'paid' | 'refund_requested' | 'refunded';
|
export type AdminOrderPaymentStatus = 'unpaid' | 'paid' | 'refund_requested' | 'refunded';
|
||||||
|
|
||||||
@@ -57,7 +59,7 @@ export interface AdminOrder {
|
|||||||
* Absent means marketplace-owned, exactly like every order today -
|
* Absent means marketplace-owned, exactly like every order today -
|
||||||
* nothing reads this field yet, no behavior change.
|
* nothing reads this field yet, no behavior change.
|
||||||
*/
|
*/
|
||||||
sellerId?: string;
|
sellerId?: UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AdminOrderListFilters {
|
export interface AdminOrderListFilters {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { UUID } from '../../../../shared/types/primitive.types';
|
||||||
|
|
||||||
export type AdminProductStockStatus = 'in_stock' | 'low_stock' | 'out_of_stock';
|
export type AdminProductStockStatus = 'in_stock' | 'low_stock' | 'out_of_stock';
|
||||||
export type AdminProductSort = 'title' | 'price' | 'priority' | 'stock' | 'updated';
|
export type AdminProductSort = 'title' | 'price' | 'priority' | 'stock' | 'updated';
|
||||||
export type AdminProductEditorMode = 'create' | 'edit' | 'duplicate';
|
export type AdminProductEditorMode = 'create' | 'edit' | 'duplicate';
|
||||||
@@ -117,7 +119,7 @@ export interface AdminProduct {
|
|||||||
* Absent means marketplace-owned, exactly like every product today -
|
* Absent means marketplace-owned, exactly like every product today -
|
||||||
* nothing reads this field yet, nothing breaks by it being undefined.
|
* nothing reads this field yet, nothing breaks by it being undefined.
|
||||||
*/
|
*/
|
||||||
sellerId?: string;
|
sellerId?: UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AdminProductListFilters {
|
export interface AdminProductListFilters {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Injectable, inject, signal } from '@angular/core';
|
import { Injectable, inject, signal } from '@angular/core';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
import { AdminInvitation, AdminRole, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model';
|
import { AdminInvitation, AdminUserRoleRecord, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model';
|
||||||
import { AdminUsersLocalGateway } from '../services/admin-users-local.gateway';
|
import { AdminUsersLocalGateway } from '../services/admin-users-local.gateway';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
@@ -8,7 +8,7 @@ export class AdminUsersFacade {
|
|||||||
private readonly gateway = inject(AdminUsersLocalGateway);
|
private readonly gateway = inject(AdminUsersLocalGateway);
|
||||||
|
|
||||||
readonly users = signal<AdminUser[]>([]);
|
readonly users = signal<AdminUser[]>([]);
|
||||||
readonly roles = signal<AdminRole[]>([]);
|
readonly roles = signal<AdminUserRoleRecord[]>([]);
|
||||||
readonly invitations = signal<AdminInvitation[]>([]);
|
readonly invitations = signal<AdminInvitation[]>([]);
|
||||||
readonly loading = signal(false);
|
readonly loading = signal(false);
|
||||||
readonly error = signal(false);
|
readonly error = signal(false);
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ export type AdminUserScope = 'marketplace' | 'office';
|
|||||||
export type AdminUserStatus = 'active' | 'invited' | 'suspended';
|
export type AdminUserStatus = 'active' | 'invited' | 'suspended';
|
||||||
export type AdminInvitationStatus = 'pending' | 'accepted' | 'expired' | 'revoked';
|
export type AdminInvitationStatus = 'pending' | 'accepted' | 'expired' | 'revoked';
|
||||||
|
|
||||||
export interface AdminRole {
|
/** Users-admin display/permissions shape - unrelated to core/auth/models/permission.model.ts's AdminRole (the real JWT/auth role union). */
|
||||||
|
export interface AdminUserRoleRecord {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
permissions: string[];
|
permissions: string[];
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { AdminInvitation, AdminRole, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model';
|
import { AdminInvitation, AdminUserRoleRecord, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model';
|
||||||
|
|
||||||
export interface AdminUsersGateway {
|
export interface AdminUsersGateway {
|
||||||
loadUsers(): Observable<AdminUser[]>;
|
loadUsers(): Observable<AdminUser[]>;
|
||||||
loadRoles(): Observable<AdminRole[]>;
|
loadRoles(): Observable<AdminUserRoleRecord[]>;
|
||||||
loadInvitations(): Observable<AdminInvitation[]>;
|
loadInvitations(): Observable<AdminInvitation[]>;
|
||||||
loadSessions(userId: string): Observable<AdminSession[]>;
|
loadSessions(userId: string): Observable<AdminSession[]>;
|
||||||
loadAudit(userId: string): Observable<AdminUserAuditEntry[]>;
|
loadAudit(userId: string): Observable<AdminUserAuditEntry[]>;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Injectable, inject } from '@angular/core';
|
import { Injectable, inject } from '@angular/core';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { delay } from 'rxjs/operators';
|
import { delay } from 'rxjs/operators';
|
||||||
import { AdminInvitation, AdminRole, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model';
|
import { AdminInvitation, AdminUserRoleRecord, AdminSession, AdminUser, AdminUserAuditEntry, AdminUserScope, AdminUserStatus } from '../models/admin-user.model';
|
||||||
import { AdminUsersGateway } from './admin-users-gateway.interface';
|
import { AdminUsersGateway } from './admin-users-gateway.interface';
|
||||||
import { AdminAuthService } from '../../../../core/admin-auth/admin-auth.service';
|
import { AdminAuthService } from '../../../../core/admin-auth/admin-auth.service';
|
||||||
|
|
||||||
const BUILT_IN_ROLES: AdminRole[] = [
|
const BUILT_IN_ROLES: AdminUserRoleRecord[] = [
|
||||||
{ id: 'owner', name: 'Owner', permissions: ['*'], builtIn: true },
|
{ id: 'owner', name: 'Owner', permissions: ['*'], builtIn: true },
|
||||||
{ id: 'admin', name: 'Admin', permissions: ['products.manage', 'categories.manage', 'orders.manage', 'media.manage', 'users.manage'], builtIn: true },
|
{ id: 'admin', name: 'Admin', permissions: ['products.manage', 'categories.manage', 'orders.manage', 'media.manage', 'users.manage'], builtIn: true },
|
||||||
{ id: 'editor', name: 'Editor', permissions: ['products.manage', 'categories.manage', 'media.manage'], builtIn: true },
|
{ id: 'editor', name: 'Editor', permissions: ['products.manage', 'categories.manage', 'media.manage'], builtIn: true },
|
||||||
@@ -16,7 +16,7 @@ const BUILT_IN_ROLES: AdminRole[] = [
|
|||||||
export class AdminUsersLocalGateway implements AdminUsersGateway {
|
export class AdminUsersLocalGateway implements AdminUsersGateway {
|
||||||
private readonly adminAuth = inject(AdminAuthService);
|
private readonly adminAuth = inject(AdminAuthService);
|
||||||
private users: AdminUser[] | null = null;
|
private users: AdminUser[] | null = null;
|
||||||
private roles: AdminRole[] = [...BUILT_IN_ROLES];
|
private roles: AdminUserRoleRecord[] = [...BUILT_IN_ROLES];
|
||||||
private invitations: AdminInvitation[] = [];
|
private invitations: AdminInvitation[] = [];
|
||||||
private sessions: Record<string, AdminSession[]> = {};
|
private sessions: Record<string, AdminSession[]> = {};
|
||||||
private audit: Record<string, AdminUserAuditEntry[]> = {};
|
private audit: Record<string, AdminUserAuditEntry[]> = {};
|
||||||
@@ -25,7 +25,7 @@ export class AdminUsersLocalGateway implements AdminUsersGateway {
|
|||||||
return of(this.ensureUsers()).pipe(delay(50));
|
return of(this.ensureUsers()).pipe(delay(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
loadRoles(): Observable<AdminRole[]> {
|
loadRoles(): Observable<AdminUserRoleRecord[]> {
|
||||||
return of(this.roles).pipe(delay(50));
|
return of(this.roles).pipe(delay(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { UUID } from '../shared/types/primitive.types';
|
||||||
|
|
||||||
interface Photo {
|
interface Photo {
|
||||||
photo?: string;
|
photo?: string;
|
||||||
video?: string;
|
video?: string;
|
||||||
@@ -182,7 +184,7 @@ export interface Item {
|
|||||||
* Absent means marketplace-owned, exactly like every product today -
|
* Absent means marketplace-owned, exactly like every product today -
|
||||||
* nothing reads this field yet, nothing breaks by it being undefined.
|
* nothing reads this field yet, nothing breaks by it being undefined.
|
||||||
*/
|
*/
|
||||||
sellerId?: string;
|
sellerId?: UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CartItem extends Item {
|
export interface CartItem extends Item {
|
||||||
|
|||||||
Reference in New Issue
Block a user