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:
sdarbinyan
2026-08-18 00:02:14 +04:00
parent 5d585ff8ff
commit 34f79b0303
4 changed files with 102 additions and 0 deletions

View 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;
}

View File

@@ -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>;
}

View File

@@ -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),
});

View File

@@ -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() });
}
}