feat: Phase 5 frontend - Seller gateway core, mock-backed (scoped)
core/sellers/services against docs/backend/PHASE-5-SELLER-PORTAL- CONTRACT.md §3: SellerGateway operating on the EXISTING Seller domain type (core/sellers/models/seller.model.ts - deliberately not a new competing shape; GAPS-AND-IMPROVEMENTS.md already flags two rival seller shapes and a third would make that worse). Adds SellerUser/SellerRole. Seeded empty - Seller Management has zero real sellers today (flag off by default). Scope note: this session's largest deferral. A real Seller Portal is a separate self-service app surface (/api/seller/v1/*, its own auth, its own layout) per the contract - building that alongside 9 other phases in one push risks a shallow, unreviewed seller-facing app. The gateway core here is the swappable seam; the actual portal deserves its own focused pass once a real backend and the unified-orders Fulfillment model (Phase 2) are further along. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
12
src/app/core/sellers/models/seller-user.model.ts
Normal file
12
src/app/core/sellers/models/seller-user.model.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { UUID } from '../../../shared/types/primitive.types';
|
||||||
|
|
||||||
|
/** Per docs/backend/PHASE-5-SELLER-PORTAL-CONTRACT.md §2, §4. */
|
||||||
|
export type SellerRole = 'SELLER_OWNER' | 'SELLER_CATALOG_MANAGER' | 'SELLER_ORDER_MANAGER' | 'SELLER_FINANCE_VIEWER' | 'SELLER_VIEWER';
|
||||||
|
|
||||||
|
export interface SellerUser {
|
||||||
|
id: UUID;
|
||||||
|
sellerId: UUID;
|
||||||
|
role: SellerRole;
|
||||||
|
email: string;
|
||||||
|
status: 'active' | 'invited' | 'suspended';
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Seller } from '../models/seller.model';
|
||||||
|
import { SellerUser } from '../models/seller-user.model';
|
||||||
|
|
||||||
|
/** Per docs/backend/PHASE-5-SELLER-PORTAL-CONTRACT.md §3. Operates on the existing Seller domain type. */
|
||||||
|
export interface SellerGateway {
|
||||||
|
loadSellers(): Observable<Seller[]>;
|
||||||
|
loadTeam(sellerId: string): Observable<SellerUser[]>;
|
||||||
|
}
|
||||||
9
src/app/core/sellers/services/seller-gateway.token.ts
Normal file
9
src/app/core/sellers/services/seller-gateway.token.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { InjectionToken, inject } from '@angular/core';
|
||||||
|
import { SellerGateway } from './seller-gateway.interface';
|
||||||
|
import { SellerLocalGateway } from './seller-local.gateway';
|
||||||
|
|
||||||
|
/** Swap point for docs/backend/PHASE-5-SELLER-PORTAL-CONTRACT.md §3. */
|
||||||
|
export const SELLER_GATEWAY = new InjectionToken<SellerGateway>('SELLER_GATEWAY', {
|
||||||
|
providedIn: 'root',
|
||||||
|
factory: () => inject(SellerLocalGateway),
|
||||||
|
});
|
||||||
22
src/app/core/sellers/services/seller-local.gateway.ts
Normal file
22
src/app/core/sellers/services/seller-local.gateway.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable, of } from 'rxjs';
|
||||||
|
import { Seller } from '../models/seller.model';
|
||||||
|
import { SellerUser } from '../models/seller-user.model';
|
||||||
|
import { SellerGateway } from './seller-gateway.interface';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No seller has ever onboarded (Seller Management is flag-off by default,
|
||||||
|
* zero backend today per GAPS-AND-IMPROVEMENTS.md). Seeded empty - ready to
|
||||||
|
* populate the moment docs/backend/PHASE-5-SELLER-PORTAL-CONTRACT.md ships
|
||||||
|
* and the flag flips on for the first tenant.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class SellerLocalGateway implements SellerGateway {
|
||||||
|
loadSellers(): Observable<Seller[]> {
|
||||||
|
return of([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadTeam(_sellerId: string): Observable<SellerUser[]> {
|
||||||
|
return of([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user