feat: Phase 10 frontend - Gorbushka-class content module core (models only)
core/content-modules against docs/backend/PHASE-10-CONTENT-MODULES- CONTRACT.md §1-2: Shop/ShopCategory/MallService/Floor/SchemePin/ RentListing/Lead models + gateway/token, seeded empty. Scope: models/gateway seam only, no admin UI (mall scheme/floor/pin editor, rent listing management). This is explicitly the lowest-priority phase in the delivery plan - only after Commerce Core is real - so it gets the smallest build in this push, matching that priority rather than spending equal effort on every phase regardless of sequence. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
58
src/app/core/content-modules/models/mall-content.model.ts
Normal file
58
src/app/core/content-modules/models/mall-content.model.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/** Per docs/backend/PHASE-10-CONTENT-MODULES-CONTRACT.md §1. Gorbushka-class (mall_directory) tenants. */
|
||||||
|
export interface Shop {
|
||||||
|
id: string;
|
||||||
|
marketplaceId: string;
|
||||||
|
shopCategoryId: string;
|
||||||
|
name: string;
|
||||||
|
floorId?: string;
|
||||||
|
status: 'draft' | 'published';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShopCategory {
|
||||||
|
id: string;
|
||||||
|
marketplaceId: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MallService {
|
||||||
|
id: string;
|
||||||
|
marketplaceId: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
status: 'draft' | 'published';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Floor {
|
||||||
|
id: string;
|
||||||
|
marketplaceId: string;
|
||||||
|
order: number;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SchemePin {
|
||||||
|
id: string;
|
||||||
|
marketplaceId: string;
|
||||||
|
floorId: string;
|
||||||
|
shopId?: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RentListing {
|
||||||
|
id: string;
|
||||||
|
marketplaceId: string;
|
||||||
|
title: string;
|
||||||
|
areaSqm: number;
|
||||||
|
floorId?: string;
|
||||||
|
status: 'available' | 'leased';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Lead {
|
||||||
|
id: string;
|
||||||
|
marketplaceId: string;
|
||||||
|
rentListingId?: string;
|
||||||
|
contactName: string;
|
||||||
|
contactPhone: string;
|
||||||
|
message?: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Floor, Lead, RentListing, SchemePin, Shop, ShopCategory } from '../models/mall-content.model';
|
||||||
|
|
||||||
|
/** Per docs/backend/PHASE-10-CONTENT-MODULES-CONTRACT.md §2. */
|
||||||
|
export interface MallContentGateway {
|
||||||
|
loadShops(): Observable<Shop[]>;
|
||||||
|
loadShopCategories(): Observable<ShopCategory[]>;
|
||||||
|
loadFloors(): Observable<Floor[]>;
|
||||||
|
loadSchemePins(floorId: string): Observable<SchemePin[]>;
|
||||||
|
loadRentListings(): Observable<RentListing[]>;
|
||||||
|
submitLead(lead: Omit<Lead, 'id' | 'createdAt'>): Observable<Lead>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { InjectionToken, inject } from '@angular/core';
|
||||||
|
import { MallContentGateway } from './mall-content-gateway.interface';
|
||||||
|
import { MallContentLocalGateway } from './mall-content-local.gateway';
|
||||||
|
|
||||||
|
/** Swap point for docs/backend/PHASE-10-CONTENT-MODULES-CONTRACT.md. */
|
||||||
|
export const MALL_CONTENT_GATEWAY = new InjectionToken<MallContentGateway>('MALL_CONTENT_GATEWAY', {
|
||||||
|
providedIn: 'root',
|
||||||
|
factory: () => inject(MallContentLocalGateway),
|
||||||
|
});
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable, of } from 'rxjs';
|
||||||
|
import { Floor, Lead, RentListing, SchemePin, Shop, ShopCategory } from '../models/mall-content.model';
|
||||||
|
import { MallContentGateway } from './mall-content-gateway.interface';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lowest-priority phase per the delivery plan - only after Commerce Core is
|
||||||
|
* real. Seeded empty; the current Gorbushka frontend/archive remains UX
|
||||||
|
* reference only per ADR-0001, production data routes through the shared
|
||||||
|
* platform once docs/backend/PHASE-10-CONTENT-MODULES-CONTRACT.md ships.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class MallContentLocalGateway implements MallContentGateway {
|
||||||
|
loadShops(): Observable<Shop[]> { return of([]); }
|
||||||
|
loadShopCategories(): Observable<ShopCategory[]> { return of([]); }
|
||||||
|
loadFloors(): Observable<Floor[]> { return of([]); }
|
||||||
|
loadSchemePins(_floorId: string): Observable<SchemePin[]> { return of([]); }
|
||||||
|
loadRentListings(): Observable<RentListing[]> { return of([]); }
|
||||||
|
|
||||||
|
submitLead(lead: Omit<Lead, 'id' | 'createdAt'>): Observable<Lead> {
|
||||||
|
return of({ ...lead, id: `lead_${Date.now()}`, createdAt: new Date().toISOString() });
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user