import { Component } from '@angular/core'; import { RouterLink } from '@angular/router'; import { AUTH_FORGOT_PASSWORD_PATH, COUNTRY_READ_PATH, CURRENCY_CREATE_PATH, CURRENCY_DELETE_PATH, CURRENCY_READ_PATH, CURRENCY_UPDATE_PATH, DOCUMENT_READ_PATH, FILE_READ_PATH, MODE_CONFIG_PATH, NOTIFICATION_READ_PATH, NOTIFICATION_UPDATE_PATH, PAYMENT_METHOD_READ_PATH, PAYMENT_METHOD_UPDATE_PATH, PLAN_READ_PATH, PRODUCT_READ_PATH, SERVICE_READ_PATH, SHIPMENT_METHOD_READ_PATH, USER_CHANGE_PASSWORD_PATH, USER_LOGOUT_FROM_ALL_SESSIONS_PATH, USER_PATH, WAREHOUSE_READ_PATH, ZONE_READ_PATH, } from '@africanies/africanies-core'; import { DemoSectionComponent } from '../shared/demo-section.component'; import { PageHeaderComponent } from '../shared/page-header.component'; import { PlaygroundForgotPasswordComponent } from '../shared/playground-forgot-password.component'; import { API_AUTH, API_COUNTRY, API_CURRENCY, API_DOCUMENT, API_FILE, API_MODE_CONFIG, API_NOTIFICATION, API_OVERVIEW, API_PAYMENT_METHOD, API_PLAN, API_PRODUCT, API_SERVICE, API_SHIPMENT_METHOD, API_USER, API_WAREHOUSE, API_ZONE, } from '../snippets'; interface ResourceIdRow { id: string; meaning: string; path: string; serviceCall: string; customCall: string; } interface ApiServiceEntry { id: string; title: string; hint: string; path: string; /** Models page fragment for the matching shape group. */ modelAnchor: string; modelLabel: string; resourceCalls?: { page: string; all: string; byId: string; }; returns?: string; code: string; } interface ApiServiceGroup { id: string; title: string; hint: string; services: ApiServiceEntry[]; } /** * How-to catalog for `@africanies/africanies-core` HTTP services. * Field shapes live on the Models page. */ @Component({ selector: 'app-api-page', standalone: true, imports: [ PageHeaderComponent, DemoSectionComponent, RouterLink, PlaygroundForgotPasswordComponent, ], template: `

After setup, inject a domain service below — or use ApiClient helpers for custom routes.

@for (row of resourceIdRows; track row.id) { }
id Meaning Path Service Custom
{{ row.id }} {{ row.meaning }} {{ row.path }} {{ row.serviceCall }} {{ row.customCall }}

Paginated calls may send page / size / order. Page size defaults to 15 when omitted (UI sizes: 5 / 15 / 30). Notifications default to 30. Bind res.pagination to africanies-pagination. Shapes: Pagination & ResourceId.

@for (group of serviceGroups; track group.id) {

{{ group.title }}

{{ group.hint }}

@for (entry of group.services; track entry.id) {
Path
{{ entry.path }}
@if (entry.resourceCalls; as calls) {
Calls
{{ calls.page }} {{ calls.all }} {{ calls.byId }}
} @if (entry.returns) {
Returns
{{ entry.returns }}
}
Model
{{ entry.modelLabel }}
@if (entry.id === 'auth') { }
}
}
`, }) export class ApiPage { protected readonly overviewCode = API_OVERVIEW; protected readonly resourceIdRows: ResourceIdRow[] = [ { id: 'null', meaning: 'Paginated page', path: '{base}', serviceCall: 'read() / readPage({ page })', customCall: 'getResourcePage(base, query)', }, { id: "'all'", meaning: 'Full list, not paginated', path: '{base}/all', serviceCall: "read('all') / readAll()", customCall: 'getResourceAll(base)', }, { id: 'number', meaning: 'Single matching record', path: '{base}/{id}', serviceCall: 'read(42) / readById(42)', customCall: 'getResourceById(base, 42)', }, ]; protected readonly serviceGroups: ApiServiceGroup[] = [ { id: 'reference-data', title: 'Reference data', hint: 'Catalog GETs that follow ResourceId — page, all, or by id.', services: [ { id: 'country', title: 'CountryService', hint: 'Public countries for destination pickers and address forms.', path: `GET ${COUNTRY_READ_PATH}/{id?}`, modelAnchor: 'country', modelLabel: 'CountryModel', resourceCalls: { page: 'readPage({ page }) → CountryModel[]', all: 'readAll() → CountryModel[]', byId: 'readById(n) → CountryModel', }, code: API_COUNTRY, }, { id: 'service', title: 'ServiceService', hint: 'Public App Settings subscription/add-on services. No auth required — same catalog the admin boards use for Services, Plans, and Plan Packages.', path: `GET ${SERVICE_READ_PATH}/{id?}`, modelAnchor: 'service', modelLabel: 'ServiceModel', resourceCalls: { page: 'readPage({ page, order, search, from, to }) → ServiceModel[]', all: 'readAll() → ServiceModel[]', byId: 'readById(n) → ServiceModel', }, code: API_SERVICE, }, { id: 'document', title: 'DocumentService', hint: 'Document catalog by numeric id — preview via readById → data.file_ref.base_64. For raw file_ref strings on records, use FileService.', path: `GET ${DOCUMENT_READ_PATH}/{id?}`, modelAnchor: 'document', modelLabel: 'DocumentModel', resourceCalls: { page: 'readPage({ page, order, search, from, to }) → DocumentModel[]', all: 'readAll() → DocumentModel[]', byId: 'readById(n) → DocumentModel (file_ref preview)', }, code: API_DOCUMENT, }, { id: 'plan', title: 'PlanService', hint: 'Public subscription plans with nested packages. Authenticated create/update/delete use api/plan/*.', path: `GET ${PLAN_READ_PATH}/{id?}`, modelAnchor: 'plan', modelLabel: 'PlanModel', resourceCalls: { page: 'readPage({ page, order, search, from, to }) → PlanModel[]', all: 'readAll() → PlanModel[]', byId: 'readById(n) → PlanModel', }, code: API_PLAN, }, { id: 'currency', title: 'CurrencyService', hint: 'App Settings currencies. PaymentMethodService.readPage() fills create/update checkboxes. Create name/code come from the host list, not GET. After each write, show res.message and readPage again.', path: `GET ${CURRENCY_READ_PATH}/{id?} · POST ${CURRENCY_CREATE_PATH} · PUT ${CURRENCY_UPDATE_PATH} · DELETE ${CURRENCY_DELETE_PATH}`, modelAnchor: 'currency', modelLabel: 'CurrencyModel', resourceCalls: { page: 'readPage({ page, order, search, from, to }) → CurrencyModel[]', all: 'readAll() → CurrencyModel[]', byId: 'readById(n) → CurrencyModel', }, returns: 'create(body) · update(body) · remove({ id }) → ApiResponseModel', code: API_CURRENCY, }, { id: 'payment-method', title: 'PaymentMethodService', hint: 'App Settings payment methods. Read + active toggle only (no create/delete). After update, show res.message and patch that row’s updated_at — do not reload the list. Processors are linked from Currencies via payment_method_ids.', path: `GET ${PAYMENT_METHOD_READ_PATH}/{id?} · PUT ${PAYMENT_METHOD_UPDATE_PATH}`, modelAnchor: 'payment-method', modelLabel: 'PaymentMethodModel', resourceCalls: { page: 'readPage({ page, order, search, from, to }) → PaymentMethodModel[]', all: 'readAll() → PaymentMethodModel[]', byId: 'readById(n) → PaymentMethodModel', }, returns: 'update({ id, name, model, active }) → ApiResponseModel', code: API_PAYMENT_METHOD, }, { id: 'shipment-method', title: 'ShipmentMethodService', hint: 'Carriers with delivery windows and zone values.', path: `GET ${SHIPMENT_METHOD_READ_PATH}/{id?}`, modelAnchor: 'shipment-method', modelLabel: 'ShipmentMethodModel', resourceCalls: { page: 'readPage({ page }) → ShipmentMethodModel[]', all: 'readAll() → ShipmentMethodModel[]', byId: 'readById(n) → ShipmentMethodModel', }, code: API_SHIPMENT_METHOD, }, { id: 'warehouse', title: 'WarehouseService', hint: 'Warehouse locations with address, charges, and nested country.', path: `GET ${WAREHOUSE_READ_PATH}/{id?}`, modelAnchor: 'warehouse', modelLabel: 'WarehouseModel', resourceCalls: { page: 'readPage({ page }) → WarehouseModel[]', all: 'readAll() → WarehouseModel[]', byId: 'readById(n) → WarehouseModel', }, code: API_WAREHOUSE, }, { id: 'zone', title: 'ZoneService', hint: 'Shipping zones for routing and pricing rules.', path: `GET ${ZONE_READ_PATH}/{id?}`, modelAnchor: 'zone', modelLabel: 'ZoneModel', resourceCalls: { page: 'readPage({ page }) → ZoneModel[]', all: 'readAll() → ZoneModel[]', byId: 'readById(n) → ZoneModel', }, code: API_ZONE, }, { id: 'product', title: 'ProductService', hint: 'Catalog products with HS codes and document / ETW labels.', path: `GET ${PRODUCT_READ_PATH}/{id?}`, modelAnchor: 'product', modelLabel: 'ProductModel', resourceCalls: { page: 'readPage({ page }) → ProductModel[]', all: 'readAll() → ProductModel[]', byId: 'readById(n) → ProductModel', }, code: API_PRODUCT, }, ], }, { id: 'session-config', title: 'Session & config', hint: 'Auth email flows, current user, and STN/SFN region units — not ResourceId list reads.', services: [ { id: 'auth', title: 'AuthService', hint: 'Email-only. POST { email } — backend emails a reset link. This UI never collects a new password for that link. Admins reuse forgot(email).', path: `POST ${AUTH_FORGOT_PASSWORD_PATH}`, modelAnchor: 'auth', modelLabel: 'ForgotPasswordRequestModel', returns: 'forgot(email) → ApiResponseModel', code: API_AUTH, }, { id: 'user', title: 'UserService', hint: 'Current user. Call AuthTokenService.set(access_token) after login. If user.default_password, send them to /onboarding/reset-password (not the email-link flow). Logout: POST while the token is set, then AuthTokenService.clear().', path: `GET ${USER_PATH} · POST ${USER_CHANGE_PASSWORD_PATH} · POST ${USER_LOGOUT_FROM_ALL_SESSIONS_PATH}`, modelAnchor: 'user', modelLabel: 'UserModel', returns: 'me() → UserModel · changePassword(body) → ApiResponseModel · logoutFromAllSessions() → ApiResponseModel', code: API_USER, }, { id: 'notification', title: 'NotificationService', hint: 'Authenticated inbox for the header bell — readPage for badge + drawer infinite scroll.', path: `GET ${NOTIFICATION_READ_PATH}/{id?} · PUT ${NOTIFICATION_UPDATE_PATH}`, modelAnchor: 'notification', modelLabel: 'NotificationModel', resourceCalls: { page: 'readPage({ page }) → NotificationModel[]', all: 'readAll() → NotificationModel[]', byId: 'readOne(uuid) → NotificationModel', }, returns: 'markRead(id?) → ApiResponseModel ({} marks all read)', code: API_NOTIFICATION, }, { id: 'mode-config', title: 'ModeConfigService', hint: 'Region currency and units for STN/SFN — usually loaded at startup.', path: `GET ${MODE_CONFIG_PATH}`, modelAnchor: 'mode-config', modelLabel: 'ModeConfigDataModel', returns: 'loadConfig() → ModeConfigDataModel', code: API_MODE_CONFIG, }, ], }, { id: 'files', title: 'Files', hint: 'Single-object file resolve — not a list, not paginated.', services: [ { id: 'file', title: 'FileService', hint: 'Primary preview when a record stores file_ref — POST { ref }. Waybills: readMultiple(ref) → POST ?multiple=yes.', path: `POST ${FILE_READ_PATH} · POST ${FILE_READ_PATH}?multiple=yes`, modelAnchor: 'file', modelLabel: 'FileReadModel', returns: 'read(ref) → FileReadModel · readMultiple(ref) → FileReadModel[]', code: API_FILE, }, ], }, ]; }