@sneat/extension-debtus-ui 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (17) hide show
  1. package/fesm2022/{sneat-extension-debtus-ui-new-transfer-page.component-YaGgYqKB.mjs → sneat-extension-debtus-ui-new-transfer-page.component-DUkdGP92.mjs} +10 -4
  2. package/fesm2022/sneat-extension-debtus-ui-new-transfer-page.component-DUkdGP92.mjs.map +1 -0
  3. package/fesm2022/sneat-extension-debtus-ui-source-obligations-page.component-BJ6Oe79f.mjs +992 -0
  4. package/fesm2022/sneat-extension-debtus-ui-source-obligations-page.component-BJ6Oe79f.mjs.map +1 -0
  5. package/fesm2022/sneat-extension-debtus-ui-source-repayment-form-CZ7EtdUp.mjs +30 -0
  6. package/fesm2022/sneat-extension-debtus-ui-source-repayment-form-CZ7EtdUp.mjs.map +1 -0
  7. package/fesm2022/sneat-extension-debtus-ui-transfer-details-page.component-BSDIDPAb.mjs +254 -0
  8. package/fesm2022/sneat-extension-debtus-ui-transfer-details-page.component-BSDIDPAb.mjs.map +1 -0
  9. package/fesm2022/sneat-extension-debtus-ui.mjs +153 -6
  10. package/fesm2022/sneat-extension-debtus-ui.mjs.map +1 -1
  11. package/package.json +7 -4
  12. package/types/sneat-extension-debtus-ui.d.ts +31 -2
  13. package/fesm2022/sneat-extension-debtus-ui-new-transfer-page.component-YaGgYqKB.mjs.map +0 -1
  14. package/fesm2022/sneat-extension-debtus-ui-source-obligations-page.component-6E9_pHCq.mjs +0 -423
  15. package/fesm2022/sneat-extension-debtus-ui-source-obligations-page.component-6E9_pHCq.mjs.map +0 -1
  16. package/fesm2022/sneat-extension-debtus-ui-transfer-details-page.component-B6iQS1YJ.mjs +0 -105
  17. package/fesm2022/sneat-extension-debtus-ui-transfer-details-page.component-B6iQS1YJ.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sneat-extension-debtus-ui-source-obligations-page.component-BJ6Oe79f.mjs","sources":["../../../../../../libs/extensions/debtus/ui/src/lib/pages/source-obligations/source-obligations-api.service.ts","../../../../../../libs/extensions/debtus/ui/src/lib/pages/source-obligations/source-obligations-page.component.ts","../../../../../../libs/extensions/debtus/ui/src/lib/pages/source-obligations/source-obligations-page.component.html"],"sourcesContent":["import { HttpParams } from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { SneatApiService } from '@sneat/api';\nimport {\n MAX_DEBTUS_SOURCE_OBLIGATION_IDS,\n parseDebtusExactMinorAmountString,\n parseDebtusSourceObligationDueDateV1,\n type DebtusSourceObligationActivityKind,\n type DebtusSourceSettlementStatus,\n type IDebtusSourceContactRefV1,\n type IDebtusSourceObligationActivityV1,\n type IDebtusSourceObligationV1,\n type IDebtusSourceRefV1,\n type IDebtusSourceRepaymentCapabilityV1,\n} from '@sneat/extension-debtus-contract';\nimport { Observable, map } from 'rxjs';\n\nexport type ISourceRef = IDebtusSourceRefV1 & {\n readonly namespace: 'splitus';\n};\n\nexport type SourcePostingStatus =\n 'pending' | 'posting' | 'applied' | 'attention';\nexport type SourceSettlementStatus = DebtusSourceSettlementStatus;\nexport type SourceActivityKind = DebtusSourceObligationActivityKind;\nexport type ISourceContactRef = IDebtusSourceContactRefV1;\nexport type ISourceObligation = IDebtusSourceObligationV1;\n\nexport interface ISourceObligationsStatus {\n readonly source: ISourceRef;\n readonly latestReceipt: {\n readonly receiptID: string;\n readonly revision: string;\n readonly operationKey: string;\n readonly inputDigest: string;\n };\n readonly postingStatus: SourcePostingStatus;\n readonly attentionReason?: string;\n readonly obligations: readonly ISourceObligation[];\n}\n\nexport type ISourceObligationActivity = IDebtusSourceObligationActivityV1;\n\nexport interface ISourceObligationActivitiesPage {\n readonly activities: readonly ISourceObligationActivity[];\n readonly nextCursor?: string;\n}\n\n@Injectable({ providedIn: 'root' })\nexport class SourceObligationsApiService {\n private readonly api = inject(SneatApiService);\n\n public getStatus(source: ISourceRef): Observable<ISourceObligationsStatus> {\n return this.api\n .get<unknown>('api4debtus/source-obligations', sourceParams(source))\n .pipe(map((value) => parseSourceObligationsStatus(value, source)));\n }\n\n public getActivities(\n source: ISourceRef,\n cursor?: string,\n ): Observable<ISourceObligationActivitiesPage> {\n let params = sourceParams(source).set('pageSize', '25');\n if (cursor) {\n params = params.set('cursor', cursor);\n }\n return this.api\n .get<unknown>('api4debtus/source-obligation-activities', params)\n .pipe(map((value) => parseSourceObligationActivitiesPage(value, source)));\n }\n}\n\nfunction sourceParams(source: ISourceRef): HttpParams {\n return new HttpParams()\n .set('spaceID', source.spaceID)\n .set('sourceNamespace', source.namespace)\n .set('sourceRecordID', source.recordID);\n}\n\nexport function parseSourceObligationsStatus(\n value: unknown,\n expectedSource: ISourceRef,\n): ISourceObligationsStatus {\n const input = record(value, 'source obligations status');\n const source = sourceRef(input['source']);\n if (\n source.namespace !== expectedSource.namespace ||\n source.spaceID !== expectedSource.spaceID ||\n source.recordID !== expectedSource.recordID\n ) {\n throw new TypeError(\n 'source obligations response identity does not match the request',\n );\n }\n const receipt = record(input['latestReceipt'], 'latestReceipt');\n const postingStatus = oneOf(\n input['postingStatus'],\n ['pending', 'posting', 'applied', 'attention'] as const,\n 'postingStatus',\n );\n const attentionReason = optionalString(\n input['attentionReason'],\n 'attentionReason',\n );\n if (postingStatus === 'attention' ? !attentionReason : !!attentionReason) {\n throw new TypeError(\n 'attentionReason presence does not match postingStatus',\n );\n }\n return {\n source,\n latestReceipt: {\n receiptID: id(\n inputString(receipt, 'receiptID'),\n 'latestReceipt.receiptID',\n ),\n revision: positiveIntegerString(\n receipt['revision'],\n 'latestReceipt.revision',\n ),\n operationKey: id(\n inputString(receipt, 'operationKey'),\n 'latestReceipt.operationKey',\n ),\n inputDigest: id(\n inputString(receipt, 'inputDigest'),\n 'latestReceipt.inputDigest',\n ),\n },\n postingStatus,\n ...(attentionReason ? { attentionReason } : {}),\n obligations: boundedArray(input['obligations'], 'obligations').map(\n (obligation) => sourceObligation(obligation, source),\n ),\n };\n}\n\nexport function parseSourceObligationActivitiesPage(\n value: unknown,\n expectedSource: ISourceRef,\n): ISourceObligationActivitiesPage {\n const input = record(value, 'source obligation activities');\n const nextCursor = optionalCursor(input['nextCursor']);\n return {\n activities: boundedArray(input['activities'], 'activities').map(\n (activity) => sourceActivity(activity, expectedSource.spaceID),\n ),\n ...(nextCursor ? { nextCursor } : {}),\n };\n}\n\nfunction sourceRef(value: unknown): ISourceRef {\n const input = record(value, 'source');\n const namespace = inputString(input, 'namespace');\n if (namespace !== 'splitus') {\n throw new TypeError('source.namespace must be splitus');\n }\n return {\n namespace,\n spaceID: id(inputString(input, 'spaceID'), 'source.spaceID'),\n recordID: id(inputString(input, 'recordID'), 'source.recordID'),\n };\n}\n\nfunction sourceContact(\n value: unknown,\n label: string,\n expectedSpaceID: string,\n): IDebtusSourceContactRefV1 {\n const input = record(value, label);\n const spaceID = id(inputString(input, 'spaceID'), `${label}.spaceID`);\n if (spaceID !== expectedSpaceID) {\n throw new TypeError(`${label}.spaceID does not match the requested Space`);\n }\n return {\n spaceID,\n contactID: id(inputString(input, 'contactID'), `${label}.contactID`),\n };\n}\n\nfunction sourceObligation(\n value: unknown,\n expectedSource: ISourceRef,\n): IDebtusSourceObligationV1 {\n const input = record(value, 'obligation');\n const lineID = id(inputString(input, 'lineID'), 'obligation.lineID');\n const dueDateTask = input['dueDateTask']\n ? parseDebtusSourceObligationDueDateV1(\n input['dueDateTask'],\n expectedSource,\n lineID,\n )\n : undefined;\n return {\n lineID,\n obligationIDs: stringArray(\n input['obligationIDs'],\n 'obligation.obligationIDs',\n MAX_DEBTUS_SOURCE_OBLIGATION_IDS,\n ),\n debtor: sourceContact(\n input['debtor'],\n 'obligation.debtor',\n expectedSource.spaceID,\n ),\n creditor: sourceContact(\n input['creditor'],\n 'obligation.creditor',\n expectedSource.spaceID,\n ),\n currency: currency(input['currency']),\n principalMinor: parseDebtusExactMinorAmountString(input['principalMinor']),\n outstandingMinor: parseDebtusExactMinorAmountString(\n input['outstandingMinor'],\n ),\n repaidMinor: parseDebtusExactMinorAmountString(input['repaidMinor']),\n creditMinor: parseDebtusExactMinorAmountString(input['creditMinor']),\n status: oneOf(\n input['status'],\n ['unsettled', 'part_settled', 'settled'] as const,\n 'obligation.status',\n ),\n repaymentCapability: sourceRepaymentCapability(\n input['repaymentCapability'],\n ),\n ...(dueDateTask ? { dueDateTask } : {}),\n };\n}\n\nfunction sourceActivity(\n value: unknown,\n expectedSpaceID: string,\n): ISourceObligationActivity {\n const input = record(value, 'activity');\n const occurredAt = utcTimestamp(input['occurredAt'], 'activity.occurredAt');\n return {\n activityID: id(inputString(input, 'activityID'), 'activity.activityID'),\n rootActivityID: id(\n inputString(input, 'rootActivityID'),\n 'activity.rootActivityID',\n ),\n lineIDs: stringArray(\n input['lineIDs'],\n 'activity.lineIDs',\n MAX_DEBTUS_SOURCE_OBLIGATION_IDS,\n ),\n kind: oneOf(\n input['kind'],\n [\n 'obligation',\n 'repayment',\n 'adjustment',\n 'cancellation',\n 'credit',\n ] as const,\n 'activity.kind',\n ),\n from: sourceContact(input['from'], 'activity.from', expectedSpaceID),\n to: sourceContact(input['to'], 'activity.to', expectedSpaceID),\n currency: currency(input['currency']),\n amountMinor: positiveIntegerString(\n input['amountMinor'],\n 'activity.amountMinor',\n ),\n occurredAt,\n };\n}\n\nfunction utcTimestamp(value: unknown, label: string): string {\n const timestamp = text(String(value ?? ''), label);\n if (\n !/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/.test(timestamp) ||\n Number.isNaN(Date.parse(timestamp))\n ) {\n throw new TypeError(\n `${label} must be a valid UTC timestamp with millisecond precision`,\n );\n }\n return timestamp;\n}\n\nfunction record(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new TypeError(`${label} must be an object`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction boundedArray(value: unknown, label: string): readonly unknown[] {\n if (!Array.isArray(value) || value.length > 100) {\n throw new TypeError(`${label} must be an array with at most 100 items`);\n }\n return value;\n}\n\nfunction inputString(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n if (typeof value !== 'string') {\n throw new TypeError(`${key} must be a string`);\n }\n return value;\n}\n\nfunction optionalString(value: unknown, label: string): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (typeof value !== 'string' || !value.trim() || value.length > 2048) {\n throw new TypeError(`${label} must be a bounded non-empty string`);\n }\n return value;\n}\n\nfunction optionalCursor(value: unknown): string | undefined {\n if (value === undefined) {\n return undefined;\n }\n if (typeof value !== 'string' || !value || value.length > 4096) {\n throw new TypeError('nextCursor must be a bounded non-empty string');\n }\n return value;\n}\n\nfunction text(value: string, label: string): string {\n if (!value.trim() || value.length > 2048) {\n throw new TypeError(`${label} must be a bounded non-empty string`);\n }\n return value;\n}\n\nfunction id(value: string, label: string): string {\n if (\n !value ||\n value.trim() !== value ||\n value.length > 512 ||\n Array.from(value).some((character) => {\n const code = character.charCodeAt(0);\n return code < 0x20 || code === 0x7f;\n })\n ) {\n throw new TypeError(`${label} is not a valid bounded identifier`);\n }\n return value;\n}\n\nfunction stringArray(\n value: unknown,\n label: string,\n maximum = 100,\n): readonly string[] {\n if (!Array.isArray(value) || value.length > maximum) {\n throw new TypeError(\n `${label} must be an array with at most ${maximum} items`,\n );\n }\n const values = value.map((item) => {\n if (typeof item !== 'string') {\n throw new TypeError(`${label} entries must be strings`);\n }\n return id(item, label);\n });\n if (!values.length || new Set(values).size !== values.length) {\n throw new TypeError(`${label} must contain unique values`);\n }\n return values;\n}\n\nfunction positiveIntegerString(value: unknown, label: string): string {\n let result: string;\n try {\n result = parseDebtusExactMinorAmountString(value);\n } catch {\n throw new TypeError(`${label} must be an exact positive integer string`);\n }\n if (result === '0') {\n throw new TypeError(`${label} must be an exact positive integer string`);\n }\n return result;\n}\n\nfunction sourceRepaymentCapability(\n value: unknown,\n): IDebtusSourceRepaymentCapabilityV1 {\n const input = record(value, 'repaymentCapability');\n if (input['canRecordRepayment'] === true) {\n if (input['repaymentUnavailableReason'] !== undefined) {\n throw new TypeError(\n 'repaymentCapability must not include an unavailable reason when repayment is allowed',\n );\n }\n return { canRecordRepayment: true };\n }\n if (input['canRecordRepayment'] !== false) {\n throw new TypeError(\n 'repaymentCapability.canRecordRepayment must be boolean',\n );\n }\n return {\n canRecordRepayment: false,\n repaymentUnavailableReason: oneOf(\n input['repaymentUnavailableReason'],\n [\n 'readOnlyRole',\n 'notParty',\n 'notOutstanding',\n 'ledgerPartyUnresolved',\n 'linkedEventLimitReached',\n ] as const,\n 'repaymentCapability.repaymentUnavailableReason',\n ),\n };\n}\n\nfunction currency(value: unknown): string {\n if (typeof value !== 'string' || !/^[A-Z]{3}$/.test(value)) {\n throw new TypeError('currency must be three uppercase ASCII letters');\n }\n return value;\n}\n\nfunction oneOf<const T extends readonly string[]>(\n value: unknown,\n allowed: T,\n label: string,\n): T[number] {\n if (typeof value !== 'string' || !allowed.includes(value as T[number])) {\n throw new TypeError(`${label} has an unsupported value`);\n }\n return value;\n}\n","import { DatePipe } from '@angular/common';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Component, DestroyRef, computed, inject, signal } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { ActivatedRoute } from '@angular/router';\nimport { IonBackButton } from '@ionic/angular/ion-back-button';\nimport { IonBadge } from '@ionic/angular/ion-badge';\nimport { IonButton } from '@ionic/angular/ion-button';\nimport { IonButtons } from '@ionic/angular/ion-buttons';\nimport { IonCardContent } from '@ionic/angular/ion-card-content';\nimport { IonCardHeader } from '@ionic/angular/ion-card-header';\nimport { IonCardTitle } from '@ionic/angular/ion-card-title';\nimport { IonCard } from '@ionic/angular/ion-card';\nimport { IonContent } from '@ionic/angular/ion-content';\nimport { IonHeader } from '@ionic/angular/ion-header';\nimport { IonInput } from '@ionic/angular/ion-input';\nimport { IonItem } from '@ionic/angular/ion-item';\nimport { IonLabel } from '@ionic/angular/ion-label';\nimport { IonList } from '@ionic/angular/ion-list';\nimport { IonNote } from '@ionic/angular/ion-note';\nimport { IonSelect } from '@ionic/angular/ion-select';\nimport { IonSelectOption } from '@ionic/angular/ion-select-option';\nimport { IonSpinner } from '@ionic/angular/ion-spinner';\nimport { IonTitle } from '@ionic/angular/ion-title';\nimport { IonToolbar } from '@ionic/angular/ion-toolbar';\nimport { IIdAndBrief } from '@sneat/core';\nimport {\n CONTACTUS_SPACE_SERVICE,\n IContactBrief,\n contactTitle,\n} from '@sneat/extension-contactus-contract';\nimport {\n DEBTUS_SOURCE_REPAYMENT_CONTRACT_VERSION,\n DEBTUS_SOURCE_DUE_DATE_CONTRACT_VERSION,\n DEBTUS_SOURCE_OBLIGATION_DUE_DATE_SERVICE_V1,\n DEBTUS_SOURCE_REPAYMENT_SERVICE_V1,\n type DebtusSourceRepaymentUnavailableReason,\n type IDebtusSourceObligationV1,\n type IRecordDebtusSourceRepaymentV1Request,\n} from '@sneat/extension-debtus-contract';\nimport {\n type IListBrief,\n LISTUS_SERVICE,\n} from '@sneat/extension-listus-contract';\nimport {\n SpaceComponentBaseParams,\n SpacePageBaseComponent,\n} from '@sneat/space-components';\nimport { ClassName } from '@sneat/ui';\nimport { SpaceServiceModule } from '@sneat/space-services';\nimport {\n BehaviorSubject,\n EMPTY,\n catchError,\n combineLatest,\n first,\n map,\n of,\n switchMap,\n} from 'rxjs';\nimport {\n DEBTUS_SOURCE_RETURN_URL_BUILDER,\n type DebtusSourceReturnUrlBuilder,\n} from '../../source-obligations-navigation';\nimport {\n ISourceObligationActivitiesPage,\n ISourceObligationActivity,\n ISourceObligationsStatus,\n ISourceRef,\n SourceObligationsApiService,\n SourceSettlementStatus,\n} from './source-obligations-api.service';\nimport {\n formatMinorAmountForInput,\n parseRepaymentMajorAmount,\n} from './source-repayment-form';\n\ninterface ILoadedSourceObligations {\n readonly status: ISourceObligationsStatus;\n readonly activityPage: ISourceObligationActivitiesPage;\n readonly contacts: readonly IIdAndBrief<IContactBrief>[];\n readonly todoLists: Readonly<Record<string, IListBrief>>;\n}\n\ntype SourceLoadResult =\n | { readonly data: ILoadedSourceObligations }\n | { readonly error: unknown; readonly message: string };\n\ntype RepaymentRefreshResult =\n | {\n readonly status: ISourceObligationsStatus;\n readonly activityPage: ISourceObligationActivitiesPage;\n }\n | { readonly refreshError: unknown };\n\n@Component({\n selector: 'debtus-source-obligations-page',\n templateUrl: './source-obligations-page.component.html',\n imports: [\n SpaceServiceModule,\n DatePipe,\n IonBackButton,\n IonBadge,\n IonButton,\n IonButtons,\n IonCard,\n IonCardContent,\n IonCardHeader,\n IonCardTitle,\n IonContent,\n IonHeader,\n IonInput,\n IonItem,\n IonLabel,\n IonList,\n IonNote,\n IonSelect,\n IonSelectOption,\n IonSpinner,\n IonTitle,\n IonToolbar,\n ],\n providers: [\n { provide: ClassName, useValue: 'SourceObligationsPageComponent' },\n SpaceComponentBaseParams,\n ],\n})\nexport class SourceObligationsPageComponent extends SpacePageBaseComponent {\n private readonly sourceApi = inject(SourceObligationsApiService);\n private readonly repaymentService = inject(\n DEBTUS_SOURCE_REPAYMENT_SERVICE_V1,\n );\n private readonly dueDateService = inject(\n DEBTUS_SOURCE_OBLIGATION_DUE_DATE_SERVICE_V1,\n { optional: true },\n );\n private readonly sourceReturnUrlBuilder =\n inject<DebtusSourceReturnUrlBuilder | null>(\n DEBTUS_SOURCE_RETURN_URL_BUILDER,\n { optional: true },\n );\n private readonly contactusSpaceService = inject(CONTACTUS_SPACE_SERVICE);\n private readonly listusService = inject(LISTUS_SERVICE);\n private readonly activatedRoute = inject(ActivatedRoute);\n private readonly componentDestroyRef = inject(DestroyRef);\n private readonly reload = new BehaviorSubject<void>(undefined);\n\n protected readonly $loading = signal(true);\n protected readonly $loadingMore = signal(false);\n protected readonly $error = signal<string | undefined>(undefined);\n protected readonly $activityError = signal<string | undefined>(undefined);\n protected readonly $status = signal<ISourceObligationsStatus | undefined>(\n undefined,\n );\n protected readonly $activities = signal<readonly ISourceObligationActivity[]>(\n [],\n );\n protected readonly $nextCursor = signal<string | undefined>(undefined);\n protected readonly $requestedLineID = signal<string | undefined>(undefined);\n protected readonly $routeSpaceType = signal<string | undefined>(undefined);\n protected readonly $selectedObligation = signal<\n IDebtusSourceObligationV1 | undefined\n >(undefined);\n protected readonly $amountInput = signal('');\n protected readonly $repaymentPending = signal(false);\n protected readonly $repaymentError = signal<string | undefined>(undefined);\n protected readonly $repaymentSuccess = signal<string | undefined>(undefined);\n private readonly $dueDrafts = signal<\n Readonly<\n Record<\n string,\n {\n title: string;\n dueDate: string;\n todoListID: string;\n operationKey?: string;\n }\n >\n >\n >({});\n protected readonly $dueLineID = signal<string | undefined>(undefined);\n protected readonly $todoLists = signal<\n readonly { id: string; brief: IListBrief }[]\n >([]);\n protected readonly $duePending = signal(false);\n protected readonly $dueError = signal<string | undefined>(undefined);\n protected readonly $dueSuccess = signal<string | undefined>(undefined);\n protected readonly $repaymentNeedsReconciliation = signal(false);\n private readonly $retryRequest = signal<\n IRecordDebtusSourceRepaymentV1Request | undefined\n >(undefined);\n private routeGeneration = 0;\n private readonly $contactTitles = signal<ReadonlyMap<string, string>>(\n new Map(),\n );\n\n protected readonly $visibleObligations = computed(() => {\n const obligations = this.$status()?.obligations ?? [];\n const requestedLineID = this.$requestedLineID();\n return requestedLineID\n ? obligations.filter(\n (obligation) => obligation.lineID === requestedLineID,\n )\n : obligations;\n });\n\n protected readonly $selectionMessage = computed(() => {\n const requestedLineID = this.$requestedLineID();\n if (!requestedLineID) {\n return undefined;\n }\n const count = this.$visibleObligations().length;\n if (count === 0) {\n return 'No Debtus obligation matches the selected bill line.';\n }\n if (count > 1) {\n return `This bill line has ${count} separate Debtus obligations. Choose the exact repayment target.`;\n }\n return 'Showing the obligation for the selected bill line.';\n });\n\n protected readonly $amountError = computed(() => {\n const obligation = this.$selectedObligation();\n if (!obligation) {\n return undefined;\n }\n try {\n const amountMinor = parseRepaymentMajorAmount(\n this.$amountInput(),\n obligation.currency,\n );\n if (BigInt(amountMinor) > BigInt(obligation.outstandingMinor)) {\n return 'The repayment cannot exceed the outstanding amount.';\n }\n return undefined;\n } catch (error) {\n return error instanceof Error ? error.message : 'Enter a valid amount.';\n }\n });\n\n protected readonly $sourceReturnUrl = computed(() => {\n const status = this.$status();\n const spaceType = this.$routeSpaceType();\n if (!status || !spaceType || !this.sourceReturnUrlBuilder) {\n return undefined;\n }\n return this.sourceReturnUrlBuilder({\n spaceType,\n source: status.source,\n lineID: this.$requestedLineID(),\n });\n });\n\n protected readonly $repaymentMutationLocked = computed(\n () =>\n this.$repaymentPending() ||\n this.$repaymentNeedsReconciliation() ||\n this.$retryRequest() !== undefined,\n );\n\n // Cancel must stay usable whenever $repaymentMutationLocked() is true only\n // because a failed attempt left a retry request queued — that is exactly\n // the state Cancel exists to escape. It still blocks while a repayment is\n // genuinely in flight, and while the outcome of a prior attempt is\n // ambiguous ($repaymentNeedsReconciliation) — that state can mean the\n // repayment was actually recorded, so bailing out without reloading could\n // hide a real mismatch; \"Reload settlement\" is the only safe exit there.\n protected readonly $cancelRepaymentLocked = computed(\n () => this.$repaymentPending() || this.$repaymentNeedsReconciliation(),\n );\n\n protected dueDraft(obligation: IDebtusSourceObligationV1): {\n title: string;\n dueDate: string;\n todoListID: string;\n operationKey?: string;\n } {\n const saved = obligation.dueDateTask;\n return (\n this.$dueDrafts()[obligation.lineID] ?? {\n title:\n saved && 'title' in saved && typeof saved.title === 'string'\n ? saved.title\n : 'Pay shared bill',\n dueDate: saved?.dueDate ?? '',\n todoListID: saved?.todoListID ?? '',\n }\n );\n }\n\n protected dueFieldChanged(\n obligation: IDebtusSourceObligationV1,\n field: 'title' | 'dueDate' | 'todoListID',\n event: CustomEvent<{ value?: string | number | null }>,\n ): void {\n if (this.$duePending()) return;\n const draft = this.dueDraft(obligation);\n this.$dueDrafts.update((drafts) => ({\n ...drafts,\n [obligation.lineID]: {\n ...draft,\n [field]: String(event.detail.value ?? ''),\n operationKey: undefined,\n },\n }));\n this.clearDueFeedback();\n }\n\n protected saveDueDate(obligation: IDebtusSourceObligationV1): void {\n const source = this.$status()?.source;\n const draft = this.dueDraft(obligation);\n const title = draft.title.trim();\n if (!source || this.$duePending() || !title) return;\n this.$dueLineID.set(obligation.lineID);\n if (!this.dueDateService) {\n this.$dueError.set('Due date editing is unavailable.');\n return;\n }\n const generation = this.routeGeneration;\n const operationKey =\n draft.operationKey ?? `web_${globalThis.crypto.randomUUID()}`;\n this.$dueDrafts.update((drafts) => ({\n ...drafts,\n [obligation.lineID]: { ...draft, operationKey },\n }));\n this.$dueLineID.set(obligation.lineID);\n this.$duePending.set(true);\n this.clearDueFeedback();\n this.dueDateService\n .setSourceObligationDueDate({\n contractVersion: DEBTUS_SOURCE_DUE_DATE_CONTRACT_VERSION,\n source,\n lineID: obligation.lineID,\n title,\n dueDate: draft.dueDate || undefined,\n expectedRevision: obligation.dueDateTask?.revision ?? 0,\n operationKey,\n todoListID: draft.todoListID || undefined,\n })\n .pipe(takeUntilDestroyed(this.componentDestroyRef))\n .subscribe({\n next: (dueDateTask) => {\n if (!this.isActiveSource(generation, source)) return;\n this.$dueDrafts.update((drafts) => {\n const next = { ...drafts };\n delete next[obligation.lineID];\n return next;\n });\n this.$duePending.set(false);\n this.$dueSuccess.set('Due date saved.');\n this.$status.update((status) =>\n status\n ? {\n ...status,\n obligations: status.obligations.map((item) =>\n item.lineID === obligation.lineID\n ? { ...item, dueDateTask }\n : item,\n ),\n }\n : status,\n );\n },\n error: (error: unknown) => {\n if (!this.isActiveSource(generation, source)) return;\n this.$duePending.set(false);\n this.$dueError.set('We could not save this due date.');\n this.errorLogger.logError(\n error,\n 'Debtus due date could not be saved',\n );\n },\n });\n }\n\n private clearDueFeedback(): void {\n this.$dueError.set(undefined);\n this.$dueSuccess.set(undefined);\n }\n\n constructor() {\n super();\n this.$defaultBackUrlSpacePath.set('debts');\n combineLatest([\n this.spaceIDChanged$,\n this.activatedRoute.paramMap,\n this.activatedRoute.queryParamMap,\n this.reload,\n ])\n .pipe(\n switchMap(([spaceID, pathParams, queryParams]) => {\n this.resetLoadedState();\n const spaceType = pathParams.get('spaceType')?.trim();\n const sourceNamespace = queryParams.get('sourceNamespace');\n const sourceRecordID = queryParams.get('sourceRecordID')?.trim();\n const requestedLineID = queryParams.get('lineID')?.trim();\n if (\n !spaceID ||\n !spaceType ||\n sourceNamespace !== 'splitus' ||\n !sourceRecordID ||\n !isRouteIdentifier(sourceRecordID) ||\n (requestedLineID && !isRouteIdentifier(requestedLineID))\n ) {\n return of<SourceLoadResult>({\n error: new Error('Invalid source-obligations route'),\n message: 'This settlement link is incomplete or invalid.',\n });\n }\n this.$routeSpaceType.set(spaceType);\n this.$requestedLineID.set(requestedLineID || undefined);\n const source: ISourceRef = {\n namespace: 'splitus',\n spaceID,\n recordID: sourceRecordID,\n };\n return combineLatest({\n status: this.sourceApi.getStatus(source),\n activityPage: this.sourceApi.getActivities(source),\n contacts: this.contactusSpaceService\n .watchContactBriefs(spaceID)\n .pipe(first()),\n todoLists: this.listusService\n .observeSpaceLists(spaceID)\n .pipe(first()),\n }).pipe(\n map((data): SourceLoadResult => ({ data })),\n catchError((error: unknown) =>\n of<SourceLoadResult>({\n error,\n message: 'We could not load this bill settlement.',\n }),\n ),\n );\n }),\n takeUntilDestroyed(),\n )\n .subscribe((result) => {\n this.$loading.set(false);\n if ('error' in result) {\n this.$error.set(result.message);\n this.errorLogger.logError(result.error, result.message);\n return;\n }\n this.applyLoadedData(result.data);\n this.selectUniqueRequestedObligation(result.data.status);\n });\n }\n\n protected retry(): void {\n if (this.$repaymentPending()) {\n return;\n }\n this.reload.next();\n }\n\n protected loadMore(): void {\n const source = this.$status()?.source;\n const cursor = this.$nextCursor();\n if (!source || !cursor || this.$loadingMore()) {\n return;\n }\n const routeGeneration = this.routeGeneration;\n this.$loadingMore.set(true);\n this.$activityError.set(undefined);\n this.sourceApi\n .getActivities(source, cursor)\n .pipe(takeUntilDestroyed(this.componentDestroyRef))\n .subscribe({\n next: (page) => {\n if (!this.isActiveSource(routeGeneration, source)) {\n return;\n }\n this.$activities.update((activities) => [\n ...activities,\n ...page.activities,\n ]);\n this.$nextCursor.set(page.nextCursor);\n this.$loadingMore.set(false);\n },\n error: (error: unknown) => {\n if (!this.isActiveSource(routeGeneration, source)) {\n return;\n }\n this.$activityError.set('We could not load more activity.');\n this.$loadingMore.set(false);\n this.errorLogger.logError(\n error,\n 'Failed to load more Debtus activity',\n );\n },\n });\n }\n\n protected selectObligation(obligation: IDebtusSourceObligationV1): void {\n if (\n !this.canStartRepayment(obligation) ||\n this.$repaymentPending() ||\n this.$repaymentNeedsReconciliation()\n ) {\n return;\n }\n const retryRequest = this.$retryRequest();\n if (retryRequest) {\n if (!this.requestMatchesObligation(retryRequest, obligation)) {\n this.requireUncertainRepaymentReconciliation();\n }\n return;\n }\n this.$selectedObligation.set(obligation);\n this.$amountInput.set(\n formatMinorAmountForInput(obligation.outstandingMinor),\n );\n this.clearRepaymentAttempt();\n }\n\n protected cancelRepayment(): void {\n if (this.$cancelRepaymentLocked()) {\n return;\n }\n this.$selectedObligation.set(undefined);\n this.$amountInput.set('');\n this.clearRepaymentAttempt();\n }\n\n protected useFullOutstanding(): void {\n const obligation = this.$selectedObligation();\n if (\n !obligation ||\n this.$repaymentPending() ||\n this.$repaymentNeedsReconciliation()\n ) {\n return;\n }\n const retryRequest = this.$retryRequest();\n if (retryRequest) {\n if (retryRequest.amountMinor !== obligation.outstandingMinor) {\n this.requireUncertainRepaymentReconciliation();\n }\n return;\n }\n this.$amountInput.set(\n formatMinorAmountForInput(obligation.outstandingMinor),\n );\n this.clearRepaymentAttempt();\n }\n\n protected amountChanged(\n event: CustomEvent<{ value?: string | number | null }>,\n ): void {\n if (this.$repaymentPending() || this.$repaymentNeedsReconciliation()) {\n return;\n }\n const value = String(event.detail.value ?? '');\n const retryRequest = this.$retryRequest();\n const obligation = this.$selectedObligation();\n if (retryRequest && obligation) {\n try {\n if (\n parseRepaymentMajorAmount(value, obligation.currency) !==\n retryRequest.amountMinor\n ) {\n this.requireUncertainRepaymentReconciliation();\n return;\n }\n } catch {\n this.requireUncertainRepaymentReconciliation();\n return;\n }\n this.$amountInput.set(value);\n return;\n }\n this.$amountInput.set(value);\n this.clearRepaymentAttempt();\n }\n\n protected recordRepayment(): void {\n const obligation = this.$selectedObligation();\n const source = this.$status()?.source;\n const obligationID = obligation && this.rootObligationID(obligation);\n if (\n !obligation ||\n !source ||\n !obligationID ||\n !this.canStartRepayment(obligation) ||\n this.$repaymentPending() ||\n this.$repaymentNeedsReconciliation()\n ) {\n return;\n }\n let amountMinor: string;\n try {\n amountMinor = parseRepaymentMajorAmount(\n this.$amountInput(),\n obligation.currency,\n );\n if (BigInt(amountMinor) > BigInt(obligation.outstandingMinor)) {\n throw new RangeError(\n 'The repayment cannot exceed the outstanding amount.',\n );\n }\n } catch (error) {\n this.$repaymentError.set(\n error instanceof Error ? error.message : 'Enter a valid amount.',\n );\n return;\n }\n\n const retryRequest = this.$retryRequest();\n if (\n retryRequest &&\n (!this.requestMatchesObligation(retryRequest, obligation) ||\n !sourceRefsEqual(retryRequest.source, source) ||\n retryRequest.amountMinor !== amountMinor)\n ) {\n this.requireUncertainRepaymentReconciliation();\n return;\n }\n const request =\n retryRequest ??\n ({\n contractVersion: DEBTUS_SOURCE_REPAYMENT_CONTRACT_VERSION,\n source,\n lineID: obligation.lineID,\n obligationID,\n currency: obligation.currency,\n amountMinor,\n repaidAt: new Date().toISOString(),\n operationKey: createRepaymentOperationKey(),\n } satisfies IRecordDebtusSourceRepaymentV1Request);\n const routeGeneration = this.routeGeneration;\n this.$retryRequest.set(request);\n this.$repaymentPending.set(true);\n this.$repaymentError.set(undefined);\n this.$repaymentSuccess.set(undefined);\n\n this.repaymentService\n .recordSourceObligationRepayment(request)\n .pipe(\n switchMap(() => {\n if (!this.isActiveSource(routeGeneration, source)) {\n return EMPTY;\n }\n // The accepted response is the persisted mutation receipt. A refresh\n // failure must block another mutation until status is reconciled.\n this.$retryRequest.set(undefined);\n this.$selectedObligation.set(undefined);\n this.$amountInput.set('');\n this.$repaymentNeedsReconciliation.set(true);\n return combineLatest({\n status: this.sourceApi.getStatus(source),\n activityPage: this.sourceApi.getActivities(source),\n }).pipe(\n map((fresh): RepaymentRefreshResult => fresh),\n catchError((refreshError: unknown) =>\n of<RepaymentRefreshResult>({ refreshError }),\n ),\n );\n }),\n takeUntilDestroyed(this.componentDestroyRef),\n )\n .subscribe({\n next: (result) => {\n if (!this.isActiveSource(routeGeneration, source)) {\n return;\n }\n this.$repaymentPending.set(false);\n if ('refreshError' in result) {\n this.$repaymentError.set(\n 'The repayment was recorded, but the latest settlement could not be refreshed. Reload this page to see it.',\n );\n this.errorLogger.logError(\n result.refreshError,\n 'Debtus repayment refresh failed',\n );\n return;\n }\n this.$status.set(result.status);\n this.$activities.set(result.activityPage.activities);\n this.$nextCursor.set(result.activityPage.nextCursor);\n this.$repaymentNeedsReconciliation.set(false);\n this.$repaymentError.set(undefined);\n this.$repaymentSuccess.set('Repayment recorded.');\n },\n error: (error: unknown) => {\n if (!this.isActiveSource(routeGeneration, source)) {\n return;\n }\n this.$repaymentPending.set(false);\n this.$repaymentError.set(repaymentErrorMessage(error));\n this.errorLogger.logError(\n error,\n 'Debtus source repayment could not be recorded',\n );\n },\n });\n }\n\n protected contactTitle(contactID: string): string {\n return this.$contactTitles().get(contactID) ?? 'Unknown contact';\n }\n\n protected formatMinorAmount(minor: string, currency: string): string {\n if (!['EUR', 'GBP', 'USD'].includes(currency)) {\n return `${minor} minor units ${currency}`;\n }\n return `${currency} ${formatMinorAmountForInput(minor)}`;\n }\n\n protected settlementColor(status: SourceSettlementStatus): string {\n switch (status) {\n case 'settled':\n return 'success';\n case 'part_settled':\n return 'warning';\n default:\n return 'medium';\n }\n }\n\n protected activityTitle(kind: ISourceObligationActivity['kind']): string {\n switch (kind) {\n case 'obligation':\n return 'Obligation recorded';\n case 'repayment':\n return 'Repayment recorded';\n case 'adjustment':\n return 'Adjustment recorded';\n case 'cancellation':\n return 'Obligation cancelled';\n case 'credit':\n return 'Credit recorded';\n }\n }\n\n protected obligationTrackKey(obligation: IDebtusSourceObligationV1): string {\n return `${obligation.lineID}:${obligation.obligationIDs.join(',')}`;\n }\n\n protected isSelected(obligation: IDebtusSourceObligationV1): boolean {\n const selected = this.$selectedObligation();\n return selected\n ? this.obligationTrackKey(selected) ===\n this.obligationTrackKey(obligation)\n : false;\n }\n\n protected canStartRepayment(obligation: IDebtusSourceObligationV1): boolean {\n return (\n obligation.repaymentCapability.canRecordRepayment &&\n obligation.outstandingMinor !== '0' &&\n this.rootObligationID(obligation) !== undefined &&\n ['EUR', 'GBP', 'USD'].includes(obligation.currency)\n );\n }\n\n protected repaymentUnavailableMessage(\n obligation: IDebtusSourceObligationV1,\n ): string | undefined {\n if (!obligation.repaymentCapability.canRecordRepayment) {\n return capabilityUnavailableMessage(\n obligation.repaymentCapability.repaymentUnavailableReason,\n );\n }\n if (obligation.obligationIDs.length !== 1) {\n return 'This repayment target has an ambiguous root obligation.';\n }\n if (!['EUR', 'GBP', 'USD'].includes(obligation.currency)) {\n return `Repayments in ${obligation.currency} are not supported yet.`;\n }\n if (obligation.outstandingMinor === '0') {\n return 'This obligation has no outstanding amount.';\n }\n return undefined;\n }\n\n protected repaymentButtonLabel(): string {\n const obligation = this.$selectedObligation();\n if (!obligation || this.$amountError()) {\n return 'Record repayment';\n }\n const amountMinor = parseRepaymentMajorAmount(\n this.$amountInput(),\n obligation.currency,\n );\n return amountMinor === obligation.outstandingMinor\n ? 'Record full repayment'\n : 'Record partial repayment';\n }\n\n private resetLoadedState(): void {\n this.routeGeneration += 1;\n this.$duePending.set(false);\n this.$dueDrafts.set({});\n this.$dueLineID.set(undefined);\n this.clearDueFeedback();\n this.$loading.set(true);\n this.$loadingMore.set(false);\n this.$error.set(undefined);\n this.$activityError.set(undefined);\n this.$status.set(undefined);\n this.$activities.set([]);\n this.$nextCursor.set(undefined);\n this.$requestedLineID.set(undefined);\n this.$routeSpaceType.set(undefined);\n this.$selectedObligation.set(undefined);\n this.$amountInput.set('');\n this.$repaymentPending.set(false);\n this.$repaymentNeedsReconciliation.set(false);\n this.clearRepaymentAttempt();\n }\n\n private clearRepaymentAttempt(): void {\n this.$retryRequest.set(undefined);\n this.$repaymentError.set(undefined);\n this.$repaymentSuccess.set(undefined);\n }\n\n private requireUncertainRepaymentReconciliation(): void {\n this.$repaymentError.set(\n 'Retry the pending repayment unchanged, or reload the settlement before editing its amount or target.',\n );\n }\n\n private requestMatchesObligation(\n request: IRecordDebtusSourceRepaymentV1Request,\n obligation: IDebtusSourceObligationV1,\n ): boolean {\n return (\n request.lineID === obligation.lineID &&\n request.obligationID === this.rootObligationID(obligation) &&\n request.currency === obligation.currency\n );\n }\n\n private isActiveSource(routeGeneration: number, source: ISourceRef): boolean {\n return (\n routeGeneration === this.routeGeneration &&\n sourceRefsEqual(this.$status()?.source, source)\n );\n }\n\n private applyLoadedData(data: ILoadedSourceObligations): void {\n this.$status.set(data.status);\n this.$activities.set(data.activityPage.activities);\n this.$nextCursor.set(data.activityPage.nextCursor);\n this.$todoLists.set(\n Object.entries(data.todoLists)\n .map(([id, brief]) => ({ id, brief }))\n .filter(\n ({ brief }) => brief.type === 'do' && brief.status !== 'archived',\n )\n .sort((a, b) => a.brief.title.localeCompare(b.brief.title)),\n );\n this.$contactTitles.set(\n new Map(\n data.contacts.map((contact) => [\n contact.id,\n contactTitle(contact, {\n includeBriefShortTitle: true,\n fallbackToID: false,\n fallback: 'Unknown contact',\n }),\n ]),\n ),\n );\n }\n\n private selectUniqueRequestedObligation(\n status: ISourceObligationsStatus,\n ): void {\n const requestedLineID = this.$requestedLineID();\n if (!requestedLineID) {\n return;\n }\n const matching = status.obligations.filter(\n (obligation) => obligation.lineID === requestedLineID,\n );\n if (matching.length === 1 && this.canStartRepayment(matching[0])) {\n this.selectObligation(matching[0]);\n }\n }\n\n protected rootObligationID(\n obligation: IDebtusSourceObligationV1,\n ): string | undefined {\n return obligation.obligationIDs.length === 1\n ? obligation.obligationIDs[0]\n : undefined;\n }\n}\n\nfunction createRepaymentOperationKey(): string {\n return `web_${globalThis.crypto.randomUUID()}`;\n}\n\nfunction sourceRefsEqual(\n first:\n | {\n readonly namespace: string;\n readonly spaceID: string;\n readonly recordID: string;\n }\n | undefined,\n second: {\n readonly namespace: string;\n readonly spaceID: string;\n readonly recordID: string;\n },\n): boolean {\n return (\n first?.namespace === second.namespace &&\n first.spaceID === second.spaceID &&\n first.recordID === second.recordID\n );\n}\n\nfunction isRouteIdentifier(value: string): boolean {\n return (\n value.length <= 512 &&\n value.trim() === value &&\n !Array.from(value).some((character) => {\n const code = character.codePointAt(0) ?? 0;\n return code < 0x20 || code === 0x7f;\n })\n );\n}\n\nfunction capabilityUnavailableMessage(\n reason: DebtusSourceRepaymentUnavailableReason,\n): string {\n switch (reason) {\n case 'readOnlyRole':\n return 'Your Space role can view this obligation but cannot record repayments.';\n case 'notParty':\n return 'You are not a party to this obligation.';\n case 'notOutstanding':\n return 'This obligation is already settled.';\n case 'ledgerPartyUnresolved':\n return 'Debtus could not resolve your ledger party for this obligation.';\n case 'linkedEventLimitReached':\n return 'This obligation has reached its linked repayment limit.';\n }\n}\n\nfunction repaymentErrorMessage(error: unknown): string {\n if (error instanceof HttpErrorResponse) {\n switch (error.status) {\n case 400:\n return 'Debtus rejected the repayment details. Review the amount and try again.';\n case 401:\n return 'Sign in again before recording this repayment.';\n case 403:\n return 'You do not have permission to record this repayment.';\n case 409:\n return 'This obligation changed before the repayment was recorded. Reload the settlement before trying again.';\n }\n }\n if (error instanceof TypeError || error instanceof RangeError) {\n return 'Debtus returned an invalid repayment receipt. Retry uses the same operation key.';\n }\n return 'We could not confirm whether Debtus recorded this repayment. Try again to safely reuse the same operation key.';\n}\n","<ion-header>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>Bill settlement</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"cardy\">\n @if ($loading()) {\n <div class=\"ion-padding ion-text-center\">\n <ion-spinner name=\"dots\" />\n <p>Loading settlement…</p>\n </div>\n } @else if ($error()) {\n <ion-card>\n <ion-card-content>\n <ion-note color=\"danger\">{{ $error() }}</ion-note>\n <ion-button expand=\"block\" fill=\"outline\" (click)=\"retry()\">\n Try again\n </ion-button>\n </ion-card-content>\n </ion-card>\n } @else if ($status(); as status) {\n <ion-card>\n <ion-card-header>\n <ion-card-title>Splitus bill settlement</ion-card-title>\n </ion-card-header>\n <ion-list lines=\"full\">\n <ion-item>\n <ion-label>\n <p>Posting</p>\n <h2>{{ status.postingStatus }}</h2>\n </ion-label>\n <ion-badge\n slot=\"end\"\n [color]=\"status.postingStatus === 'applied' ? 'success' : 'warning'\"\n >\n {{ status.postingStatus }}\n </ion-badge>\n </ion-item>\n <ion-item>\n <ion-label>\n <p>Debtus receipt</p>\n <h2>Recorded in Debtus</h2>\n <ion-note>Revision {{ status.latestReceipt.revision }}</ion-note>\n </ion-label>\n </ion-item>\n @if (status.attentionReason) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n <p>Needs attention</p>\n <h2>{{ status.attentionReason }}</h2>\n </ion-label>\n </ion-item>\n }\n </ion-list>\n @if ($sourceReturnUrl(); as returnUrl) {\n <ion-card-content>\n <ion-button expand=\"block\" fill=\"outline\" [href]=\"returnUrl\">\n Back to this bill in Splitus\n </ion-button>\n </ion-card-content>\n }\n </ion-card>\n\n <ion-card>\n <ion-card-header>\n <ion-card-title>Who owes what</ion-card-title>\n @if ($selectionMessage(); as message) {\n <ion-note>{{ message }}</ion-note>\n }\n </ion-card-header>\n @if ($visibleObligations().length) {\n <ion-list lines=\"full\">\n @for (\n obligation of $visibleObligations();\n track obligationTrackKey(obligation)\n ) {\n <ion-item\n data-testid=\"debtus-obligation\"\n [attr.data-line-id]=\"obligation.lineID\"\n [attr.data-obligation-id]=\"rootObligationID(obligation)\"\n [color]=\"\n obligation.lineID === $requestedLineID() ? 'light' : undefined\n \"\n >\n <ion-label class=\"ion-text-wrap\">\n <h2>\n {{ contactTitle(obligation.debtor.contactID) }} owes\n {{ contactTitle(obligation.creditor.contactID) }}\n </h2>\n <p>\n Outstanding:\n {{\n formatMinorAmount(\n obligation.outstandingMinor,\n obligation.currency\n )\n }}\n </p>\n <ion-note>\n Original\n {{\n formatMinorAmount(\n obligation.principalMinor,\n obligation.currency\n )\n }}\n · Repaid\n {{\n formatMinorAmount(\n obligation.repaidMinor,\n obligation.currency\n )\n }}\n @if (obligation.creditMinor !== '0') {\n · Credit\n {{\n formatMinorAmount(\n obligation.creditMinor,\n obligation.currency\n )\n }}\n }\n </ion-note>\n @if (repaymentUnavailableMessage(obligation); as reason) {\n <p>\n <ion-note color=\"medium\">{{ reason }}</ion-note>\n </p>\n }\n <ion-input\n data-testid=\"debtus-due-title-input\"\n label=\"Reminder title\"\n labelPlacement=\"stacked\"\n [value]=\"dueDraft(obligation).title\"\n [disabled]=\"$duePending()\"\n (ionInput)=\"dueFieldChanged(obligation, 'title', $event)\"\n />\n <ion-input\n data-testid=\"debtus-due-date-input\"\n label=\"Due date\"\n labelPlacement=\"stacked\"\n type=\"date\"\n [value]=\"dueDraft(obligation).dueDate\"\n [disabled]=\"$duePending()\"\n (ionInput)=\"dueFieldChanged(obligation, 'dueDate', $event)\"\n />\n <ion-select\n data-testid=\"debtus-todo-list-select\"\n label=\"Also add to a to-do list\"\n labelPlacement=\"stacked\"\n [value]=\"dueDraft(obligation).todoListID\"\n [disabled]=\"$duePending()\"\n (ionChange)=\"\n dueFieldChanged(obligation, 'todoListID', $event)\n \"\n >\n <ion-select-option value=\"\">No to-do list</ion-select-option>\n @for (list of $todoLists(); track list.id) {\n <ion-select-option [value]=\"list.id\">{{\n list.brief.title\n }}</ion-select-option>\n }\n </ion-select>\n @if (\n $dueLineID() === obligation.lineID && $dueError();\n as dueError\n ) {\n <ion-note color=\"danger\">{{ dueError }}</ion-note>\n }\n @if (\n $dueLineID() === obligation.lineID && $dueSuccess();\n as dueSuccess\n ) {\n <ion-note color=\"success\">{{ dueSuccess }}</ion-note>\n }\n <ion-button\n data-testid=\"debtus-save-due-date\"\n size=\"small\"\n [disabled]=\"\n $duePending() || !dueDraft(obligation).title.trim()\n \"\n (click)=\"saveDueDate(obligation)\"\n >Save due date</ion-button\n >\n @if (canStartRepayment(obligation)) {\n <ion-button\n size=\"small\"\n fill=\"outline\"\n [disabled]=\"$repaymentMutationLocked()\"\n (click)=\"selectObligation(obligation)\"\n >\n {{\n isSelected(obligation) ? 'Selected' : 'Record repayment'\n }}\n </ion-button>\n }\n </ion-label>\n <ion-badge\n slot=\"end\"\n [color]=\"settlementColor(obligation.status)\"\n >\n {{\n obligation.status === 'part_settled'\n ? 'part settled'\n : obligation.status\n }}\n </ion-badge>\n </ion-item>\n }\n </ion-list>\n } @else {\n <ion-card-content>\n <ion-note>\n @if ($requestedLineID()) {\n No obligation was recorded for the selected bill line.\n } @else {\n No obligations were recorded for this bill.\n }\n </ion-note>\n </ion-card-content>\n }\n </ion-card>\n\n @if ($selectedObligation(); as obligation) {\n <ion-card>\n <ion-card-header>\n <ion-card-title>Record repayment</ion-card-title>\n <ion-note>\n {{ contactTitle(obligation.debtor.contactID) }} paid\n {{ contactTitle(obligation.creditor.contactID) }}\n </ion-note>\n </ion-card-header>\n <ion-card-content>\n <ion-input\n label=\"Amount\"\n labelPlacement=\"stacked\"\n type=\"text\"\n inputmode=\"decimal\"\n [value]=\"$amountInput()\"\n [disabled]=\"$repaymentMutationLocked()\"\n [helperText]=\"\n 'Available: ' +\n formatMinorAmount(\n obligation.outstandingMinor,\n obligation.currency\n )\n \"\n (ionInput)=\"amountChanged($event)\"\n />\n @if ($amountError(); as amountError) {\n <p>\n <ion-note color=\"danger\">{{ amountError }}</ion-note>\n </p>\n }\n @if ($repaymentError(); as repaymentError) {\n <p>\n <ion-note color=\"danger\">{{ repaymentError }}</ion-note>\n </p>\n }\n <ion-button\n expand=\"block\"\n fill=\"outline\"\n [disabled]=\"$repaymentMutationLocked()\"\n (click)=\"useFullOutstanding()\"\n >\n Use full outstanding amount\n </ion-button>\n <ion-button\n expand=\"block\"\n [disabled]=\"\n $repaymentPending() ||\n $repaymentNeedsReconciliation() ||\n !!$amountError()\n \"\n (click)=\"recordRepayment()\"\n >\n @if ($repaymentPending()) {\n <ion-spinner name=\"dots\" />\n } @else {\n {{ repaymentButtonLabel() }}\n }\n </ion-button>\n <ion-button\n expand=\"block\"\n fill=\"clear\"\n [disabled]=\"$cancelRepaymentLocked()\"\n (click)=\"cancelRepayment()\"\n >\n Cancel\n </ion-button>\n </ion-card-content>\n </ion-card>\n }\n\n @if ($repaymentNeedsReconciliation()) {\n <ion-card>\n <ion-card-content>\n @if ($repaymentPending()) {\n <ion-spinner name=\"dots\" />\n <ion-note> Repayment recorded. Refreshing settlement… </ion-note>\n } @else {\n <ion-note color=\"danger\">\n {{\n $repaymentError() ||\n 'The repayment was recorded. Reload the settlement before recording another repayment.'\n }}\n </ion-note>\n <ion-button expand=\"block\" fill=\"outline\" (click)=\"retry()\">\n Reload settlement\n </ion-button>\n }\n </ion-card-content>\n </ion-card>\n }\n\n @if ($repaymentSuccess(); as repaymentSuccess) {\n <ion-card>\n <ion-card-content>\n <ion-note color=\"success\">{{ repaymentSuccess }}</ion-note>\n </ion-card-content>\n </ion-card>\n }\n\n <ion-card>\n <ion-card-header>\n <ion-card-title>Activity</ion-card-title>\n </ion-card-header>\n @if ($activities().length) {\n <ion-list lines=\"full\">\n @for (activity of $activities(); track activity.activityID) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n <h2>{{ activityTitle(activity.kind) }}</h2>\n <p>\n {{ contactTitle(activity.from.contactID) }} →\n {{ contactTitle(activity.to.contactID) }}\n </p>\n <ion-note>{{ activity.occurredAt | date: 'medium' }}</ion-note>\n </ion-label>\n <ion-badge slot=\"end\">\n {{ formatMinorAmount(activity.amountMinor, activity.currency) }}\n </ion-badge>\n </ion-item>\n }\n </ion-list>\n } @else {\n <ion-card-content>\n <ion-note>No Debtus activity has been recorded yet.</ion-note>\n </ion-card-content>\n }\n @if ($activityError()) {\n <ion-card-content>\n <ion-note color=\"danger\">{{ $activityError() }}</ion-note>\n </ion-card-content>\n }\n @if ($nextCursor()) {\n <ion-card-content>\n <ion-button\n expand=\"block\"\n fill=\"outline\"\n [disabled]=\"$loadingMore()\"\n (click)=\"loadMore()\"\n >\n @if ($loadingMore()) {\n <ion-spinner name=\"dots\" />\n } @else {\n Load more activity\n }\n </ion-button>\n </ion-card-content>\n }\n </ion-card>\n }\n</ion-content>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { parseDebtusExactMinorAmountString } from '@sneat/extension-debtus-contract';
2
+
3
+ const supportedCurrencies = new Set(['EUR', 'GBP', 'USD']);
4
+ function parseRepaymentMajorAmount(value, currency) {
5
+ if (!supportedCurrencies.has(currency)) {
6
+ throw new RangeError(`Repayments in ${currency} are not supported yet.`);
7
+ }
8
+ const normalized = value.trim();
9
+ const match = /^(0|[1-9]\d*)(?:\.(\d{1,2}))?$/.exec(normalized);
10
+ if (!match) {
11
+ throw new TypeError('Enter an amount with no more than two decimal places.');
12
+ }
13
+ const minor = (BigInt(match[1]) * 100n +
14
+ BigInt((match[2] ?? '').padEnd(2, '0') || '0')).toString();
15
+ const exactMinor = parseDebtusExactMinorAmountString(minor);
16
+ if (exactMinor === '0') {
17
+ throw new RangeError('Enter an amount greater than zero.');
18
+ }
19
+ return exactMinor;
20
+ }
21
+ function formatMinorAmountForInput(minor) {
22
+ const exactMinor = parseDebtusExactMinorAmountString(minor);
23
+ const value = BigInt(exactMinor);
24
+ const whole = value / 100n;
25
+ const fraction = (value % 100n).toString().padStart(2, '0');
26
+ return `${whole}.${fraction}`;
27
+ }
28
+
29
+ export { formatMinorAmountForInput as f, parseRepaymentMajorAmount as p };
30
+ //# sourceMappingURL=sneat-extension-debtus-ui-source-repayment-form-CZ7EtdUp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sneat-extension-debtus-ui-source-repayment-form-CZ7EtdUp.mjs","sources":["../../../../../../libs/extensions/debtus/ui/src/lib/pages/source-obligations/source-repayment-form.ts"],"sourcesContent":["import { parseDebtusExactMinorAmountString } from '@sneat/extension-debtus-contract';\n\nconst supportedCurrencies = new Set(['EUR', 'GBP', 'USD']);\n\nexport function parseRepaymentMajorAmount(\n value: string,\n currency: string,\n): string {\n if (!supportedCurrencies.has(currency)) {\n throw new RangeError(`Repayments in ${currency} are not supported yet.`);\n }\n const normalized = value.trim();\n const match = /^(0|[1-9]\\d*)(?:\\.(\\d{1,2}))?$/.exec(normalized);\n if (!match) {\n throw new TypeError(\n 'Enter an amount with no more than two decimal places.',\n );\n }\n const minor = (\n BigInt(match[1]) * 100n +\n BigInt((match[2] ?? '').padEnd(2, '0') || '0')\n ).toString();\n const exactMinor = parseDebtusExactMinorAmountString(minor);\n if (exactMinor === '0') {\n throw new RangeError('Enter an amount greater than zero.');\n }\n return exactMinor;\n}\n\nexport function formatMinorAmountForInput(minor: string): string {\n const exactMinor = parseDebtusExactMinorAmountString(minor);\n const value = BigInt(exactMinor);\n const whole = value / 100n;\n const fraction = (value % 100n).toString().padStart(2, '0');\n return `${whole}.${fraction}`;\n}\n"],"names":[],"mappings":";;AAEA,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAEpD,SAAU,yBAAyB,CACvC,KAAa,EACb,QAAgB,EAAA;IAEhB,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AACtC,QAAA,MAAM,IAAI,UAAU,CAAC,iBAAiB,QAAQ,CAAA,uBAAA,CAAyB,CAAC;IAC1E;AACA,IAAA,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,EAAE;IAC/B,MAAM,KAAK,GAAG,gCAAgC,CAAC,IAAI,CAAC,UAAU,CAAC;IAC/D,IAAI,CAAC,KAAK,EAAE;AACV,QAAA,MAAM,IAAI,SAAS,CACjB,uDAAuD,CACxD;IACH;IACA,MAAM,KAAK,GAAG,CACZ,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;QACvB,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,GAAG,CAAC,EAC9C,QAAQ,EAAE;AACZ,IAAA,MAAM,UAAU,GAAG,iCAAiC,CAAC,KAAK,CAAC;AAC3D,IAAA,IAAI,UAAU,KAAK,GAAG,EAAE;AACtB,QAAA,MAAM,IAAI,UAAU,CAAC,oCAAoC,CAAC;IAC5D;AACA,IAAA,OAAO,UAAU;AACnB;AAEM,SAAU,yBAAyB,CAAC,KAAa,EAAA;AACrD,IAAA,MAAM,UAAU,GAAG,iCAAiC,CAAC,KAAK,CAAC;AAC3D,IAAA,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC;AAChC,IAAA,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI;AAC1B,IAAA,MAAM,QAAQ,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;AAC3D,IAAA,OAAO,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,QAAQ,EAAE;AAC/B;;;;"}
@@ -0,0 +1,254 @@
1
+ import { DatePipe } from '@angular/common';
2
+ import { HttpErrorResponse } from '@angular/common/http';
3
+ import * as i0 from '@angular/core';
4
+ import { inject, DestroyRef, signal, Component } from '@angular/core';
5
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
+ import { Router } from '@angular/router';
7
+ import { IonHeader, IonToolbar, IonButtons, IonBackButton, IonTitle, IonContent, IonCard, IonCardHeader, IonCardTitle, IonCardContent, IonList, IonItem, IonLabel, IonNote, IonBadge, IonButton, IonIcon, IonSpinner, IonInput, IonSelect, IonSelectOption } from '@ionic/angular';
8
+ import { DEBTUS_SERVICE, DEBTUS_TRANSFER_DUE_DATE_SERVICE, formatAmount, DEBTUS_TRANSFER_DUE_DATE_CONTRACT_VERSION } from '@sneat/extension-debtus-contract';
9
+ import { LISTUS_SERVICE } from '@sneat/extension-listus-contract';
10
+ import { SpacePageBaseComponent, SpaceComponentBaseParams } from '@sneat/space-components';
11
+ import { SpaceServiceModule } from '@sneat/space-services';
12
+ import { ClassName } from '@sneat/ui';
13
+ import { combineLatest, switchMap, of, map, forkJoin, first, catchError, throwError } from 'rxjs';
14
+ import { f as formatMinorAmountForInput, p as parseRepaymentMajorAmount } from './sneat-extension-debtus-ui-source-repayment-form-CZ7EtdUp.mjs';
15
+
16
+ // Transfer detail / receipt — amount, parties, date, note, and its effect on
17
+ // the balance. Mirrors the bot's receipt. Offers a settle-up entry.
18
+ class TransferDetailsPageComponent extends SpacePageBaseComponent {
19
+ debtusService = inject(DEBTUS_SERVICE);
20
+ router = inject(Router);
21
+ dueService = inject(DEBTUS_TRANSFER_DUE_DATE_SERVICE);
22
+ listusService = inject(LISTUS_SERVICE);
23
+ componentDestroyRef = inject(DestroyRef);
24
+ $loading = signal(true, /* @ts-ignore */
25
+ ...(ngDevMode ? [{ debugName: "$loading" }] : /* istanbul ignore next */ []));
26
+ $error = signal(undefined, /* @ts-ignore */
27
+ ...(ngDevMode ? [{ debugName: "$error" }] : /* istanbul ignore next */ []));
28
+ $transfer = signal(undefined, /* @ts-ignore */
29
+ ...(ngDevMode ? [{ debugName: "$transfer" }] : /* istanbul ignore next */ []));
30
+ $dueTask = signal(undefined, /* @ts-ignore */
31
+ ...(ngDevMode ? [{ debugName: "$dueTask" }] : /* istanbul ignore next */ []));
32
+ $needsDebtusAdoption = signal(false, /* @ts-ignore */
33
+ ...(ngDevMode ? [{ debugName: "$needsDebtusAdoption" }] : /* istanbul ignore next */ []));
34
+ $todoLists = signal([], /* @ts-ignore */
35
+ ...(ngDevMode ? [{ debugName: "$todoLists" }] : /* istanbul ignore next */ []));
36
+ $dueDate = signal('', /* @ts-ignore */
37
+ ...(ngDevMode ? [{ debugName: "$dueDate" }] : /* istanbul ignore next */ []));
38
+ $dueTitle = signal('Pay debt', /* @ts-ignore */
39
+ ...(ngDevMode ? [{ debugName: "$dueTitle" }] : /* istanbul ignore next */ []));
40
+ $todoListID = signal('', /* @ts-ignore */
41
+ ...(ngDevMode ? [{ debugName: "$todoListID" }] : /* istanbul ignore next */ []));
42
+ $repaymentAmount = signal('', /* @ts-ignore */
43
+ ...(ngDevMode ? [{ debugName: "$repaymentAmount" }] : /* istanbul ignore next */ []));
44
+ $savingDue = signal(false, /* @ts-ignore */
45
+ ...(ngDevMode ? [{ debugName: "$savingDue" }] : /* istanbul ignore next */ []));
46
+ $repaying = signal(false, /* @ts-ignore */
47
+ ...(ngDevMode ? [{ debugName: "$repaying" }] : /* istanbul ignore next */ []));
48
+ $actionError = signal(undefined, /* @ts-ignore */
49
+ ...(ngDevMode ? [{ debugName: "$actionError" }] : /* istanbul ignore next */ []));
50
+ $actionSuccess = signal(undefined, /* @ts-ignore */
51
+ ...(ngDevMode ? [{ debugName: "$actionSuccess" }] : /* istanbul ignore next */ []));
52
+ $repaymentOperationKey = signal(undefined, /* @ts-ignore */
53
+ ...(ngDevMode ? [{ debugName: "$repaymentOperationKey" }] : /* istanbul ignore next */ []));
54
+ formatAmount = formatAmount;
55
+ formatMinorAmountForDisplay = formatMinorAmountForInput;
56
+ constructor() {
57
+ super();
58
+ this.$defaultBackUrlSpacePath.set('debts');
59
+ // A transfer just created by the new-transfer/settle-up pages is handed
60
+ // over via router `state` (it survives reloads through history.state).
61
+ // Prefer it to avoid an extra read immediately after creation. A cold load
62
+ // retrieves the same persisted transfer through the Debtus API.
63
+ const stateTransfer = (this.router.getCurrentNavigation()?.extras?.state ??
64
+ history.state)?.['transfer'];
65
+ combineLatest([this.spaceIDChanged$, this.route.paramMap])
66
+ .pipe(switchMap(([spaceID, params]) => {
67
+ const transferID = params.get('transferID') ?? '';
68
+ this.$loading.set(true);
69
+ this.$error.set(undefined);
70
+ if (stateTransfer?.id === transferID) {
71
+ return of({ spaceID: spaceID ?? '', transfer: stateTransfer });
72
+ }
73
+ return this.debtusService
74
+ .getTransfer(spaceID ?? '', transferID)
75
+ .pipe(map((transfer) => ({ spaceID: spaceID ?? '', transfer })));
76
+ }), switchMap(({ spaceID, transfer }) => forkJoin({
77
+ transfer: of(transfer),
78
+ dueTask: this.dueService
79
+ .getTransferDueDate(spaceID, transfer.id)
80
+ .pipe(catchError((error) => {
81
+ if (error instanceof HttpErrorResponse &&
82
+ error.status === 403) {
83
+ this.$needsDebtusAdoption.set(true);
84
+ return of(undefined);
85
+ }
86
+ return error instanceof HttpErrorResponse &&
87
+ error.status === 404
88
+ ? of(undefined)
89
+ : throwError(() => error);
90
+ })),
91
+ lists: this.listusService.observeSpaceLists(spaceID).pipe(first()),
92
+ })), takeUntilDestroyed())
93
+ .subscribe({
94
+ next: ({ transfer, dueTask, lists }) => {
95
+ this.$transfer.set(transfer);
96
+ this.$dueTask.set(dueTask);
97
+ this.$dueDate.set(dueTask?.dueDate ?? transfer.dueOn?.slice(0, 10) ?? '');
98
+ this.$dueTitle.set(`Pay ${transfer.counterpartyTitle}`);
99
+ this.$todoListID.set(dueTask?.todoListID ?? '');
100
+ this.$repaymentAmount.set(dueTask ? formatMinorAmountForInput(dueTask.outstandingMinor) : '');
101
+ this.$todoLists.set(Object.entries(lists)
102
+ .filter(([, brief]) => brief.type === 'do' && brief.status !== 'archived')
103
+ .map(([id, brief]) => ({ id, brief }))
104
+ .sort((a, b) => a.brief.title.localeCompare(b.brief.title)));
105
+ this.$loading.set(false);
106
+ },
107
+ error: (err) => {
108
+ this.$error.set('Failed to load transfer');
109
+ this.$loading.set(false);
110
+ this.errorLogger.logError(err, 'Failed to load debtus transfer');
111
+ },
112
+ });
113
+ }
114
+ saveDueDate(clear = false) {
115
+ const transfer = this.$transfer();
116
+ if (!transfer || this.$savingDue() || (!clear && !this.$dueDate()))
117
+ return;
118
+ this.$savingDue.set(true);
119
+ this.$actionError.set(undefined);
120
+ this.$actionSuccess.set(undefined);
121
+ this.dueService
122
+ .setTransferDueDate({
123
+ contractVersion: DEBTUS_TRANSFER_DUE_DATE_CONTRACT_VERSION,
124
+ spaceID: this.space.id,
125
+ transferID: transfer.id,
126
+ title: this.$dueTitle().trim(),
127
+ dueDate: clear ? undefined : this.$dueDate(),
128
+ expectedRevision: this.$dueTask()?.revision ?? 0,
129
+ operationKey: `web_${crypto.randomUUID()}`,
130
+ todoListID: this.$todoListID() || undefined,
131
+ })
132
+ .pipe(takeUntilDestroyed(this.componentDestroyRef))
133
+ .subscribe({
134
+ next: (task) => {
135
+ this.$dueTask.set(task);
136
+ this.$needsDebtusAdoption.set(false);
137
+ this.$savingDue.set(false);
138
+ this.$dueDate.set(task.dueDate ?? '');
139
+ this.$actionSuccess.set('Due date saved.');
140
+ },
141
+ error: (error) => {
142
+ this.$savingDue.set(false);
143
+ this.$actionError.set('We could not save this due date.');
144
+ this.errorLogger.logError(error, 'Debtus transfer due date could not be saved');
145
+ },
146
+ });
147
+ }
148
+ recordRepayment() {
149
+ const transfer = this.$transfer();
150
+ const due = this.$dueTask();
151
+ if (!transfer || !due || this.$repaying())
152
+ return;
153
+ let amountMinor;
154
+ try {
155
+ amountMinor = parseRepaymentMajorAmount(this.$repaymentAmount(), due.currency);
156
+ }
157
+ catch {
158
+ this.$actionError.set('Enter a valid positive repayment amount.');
159
+ return;
160
+ }
161
+ this.$repaying.set(true);
162
+ this.$actionError.set(undefined);
163
+ this.$actionSuccess.set(undefined);
164
+ const operationKey = this.$repaymentOperationKey() ?? `web_${crypto.randomUUID()}`;
165
+ this.$repaymentOperationKey.set(operationKey);
166
+ this.dueService
167
+ .recordTransferRepayment({
168
+ contractVersion: DEBTUS_TRANSFER_DUE_DATE_CONTRACT_VERSION,
169
+ spaceID: this.space.id,
170
+ transferID: transfer.id,
171
+ currency: due.currency,
172
+ amountMinor,
173
+ repaidAt: new Date().toISOString(),
174
+ operationKey,
175
+ })
176
+ .pipe(takeUntilDestroyed(this.componentDestroyRef))
177
+ .subscribe({
178
+ next: (result) => {
179
+ this.$dueTask.set(result.dueDateTask);
180
+ this.$repaymentAmount.set(formatMinorAmountForInput(result.outstandingMinor));
181
+ this.$transfer.set({
182
+ ...transfer,
183
+ isOutstanding: !result.fullyRepaid,
184
+ });
185
+ this.$repaying.set(false);
186
+ this.$repaymentOperationKey.set(undefined);
187
+ this.$actionSuccess.set('Repayment recorded.');
188
+ },
189
+ error: (error) => {
190
+ this.$repaying.set(false);
191
+ this.$actionError.set('We could not record this repayment.');
192
+ this.errorLogger.logError(error, 'Debtus transfer repayment could not be recorded');
193
+ },
194
+ });
195
+ }
196
+ repaymentAmountChanged(value) {
197
+ this.$repaymentAmount.set(value ?? '');
198
+ this.$repaymentOperationKey.set(undefined);
199
+ this.$actionError.set(undefined);
200
+ }
201
+ settleUp() {
202
+ const t = this.$transfer();
203
+ if (!t) {
204
+ return;
205
+ }
206
+ this.spaceNav.navigateForwardToSpacePage(this.space, `settle-up?contactID=${t.counterpartyContactID}`);
207
+ }
208
+ openContact() {
209
+ const t = this.$transfer();
210
+ if (!t?.counterpartyContactID) {
211
+ return;
212
+ }
213
+ this.spaceNav.navigateForwardToSpacePage(this.space, `debtus-contact/${t.counterpartyContactID}`);
214
+ }
215
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TransferDetailsPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
216
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: TransferDetailsPageComponent, isStandalone: true, selector: "sneat-debtus-transfer-details-page", providers: [
217
+ { provide: ClassName, useValue: 'TransferDetailsPageComponent' },
218
+ SpaceComponentBaseParams,
219
+ ], usesInheritance: true, ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>Transfer</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"cardy\">\n @if ($loading()) {\n <div class=\"ion-padding ion-text-center\">\n <ion-spinner name=\"dots\" />\n </div>\n } @else if ($error()) {\n <div class=\"ion-padding\">\n <ion-note color=\"danger\">{{ $error() }}</ion-note>\n </div>\n } @else if ($transfer(); as t) {\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n {{ t.direction === 'lend' ? 'You lent' : 'You borrowed' }}\n @if (t.isReturn) {\n \u00B7 return\n }\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-badge\n [color]=\"t.direction === 'lend' ? 'success' : 'warning'\"\n style=\"font-size: 1.2rem\"\n >\n {{ formatAmount(t.amount) }}\n </ion-badge>\n </ion-card-content>\n </ion-card>\n\n <ion-card>\n <ion-list lines=\"full\">\n <ion-item button (click)=\"openContact()\">\n <ion-label>\n <p>Counterparty</p>\n <h2>{{ t.counterpartyTitle }}</h2>\n </ion-label>\n </ion-item>\n <ion-item>\n <ion-label>\n <p>Date</p>\n <h2>{{ t.created | date: 'medium' }}</h2>\n </ion-label>\n </ion-item>\n @if (t.dueOn) {\n <ion-item>\n <ion-label>\n <p>Due</p>\n <h2>{{ t.dueOn | date: 'mediumDate' }}</h2>\n </ion-label>\n </ion-item>\n }\n @if (t.note) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n <p>Note</p>\n <h2>{{ t.note }}</h2>\n </ion-label>\n </ion-item>\n }\n <ion-item>\n <ion-label>\n <p>Status</p>\n <h2>{{ t.isOutstanding ? 'Outstanding' : 'Settled' }}</h2>\n </ion-label>\n </ion-item>\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n <p>Effect on balance</p>\n <h2>\n @if (t.direction === 'lend') {\n {{ t.counterpartyTitle }} owes you {{ formatAmount(t.amount) }}\n } @else {\n You owe {{ t.counterpartyTitle }} {{ formatAmount(t.amount) }}\n }\n </h2>\n </ion-label>\n </ion-item>\n @if (t.counterpartySpaceID) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n <p>Cross-space</p>\n <h2>Counterparty side is in space {{ t.counterpartySpaceID }}</h2>\n <ion-note color=\"medium\">\n Your side: {{ t.creatorSpaceID }}\n </ion-note>\n </ion-label>\n </ion-item>\n }\n </ion-list>\n </ion-card>\n\n <ion-card>\n <ion-card-header\n ><ion-card-title>Due date</ion-card-title></ion-card-header\n >\n <ion-card-content>\n @if ($needsDebtusAdoption()) {\n <ion-note color=\"medium\">\n Saving this due date will enable Debtus for this space and attach\n this historical transfer to it.\n </ion-note>\n }\n <ion-input\n label=\"Reminder title\"\n labelPlacement=\"stacked\"\n [value]=\"$dueTitle()\"\n (ionInput)=\"$dueTitle.set($any($event.detail.value) ?? '')\"\n data-testid=\"debtus-transfer-due-title\"\n />\n <ion-input\n type=\"date\"\n label=\"Due date\"\n labelPlacement=\"stacked\"\n [value]=\"$dueDate()\"\n (ionInput)=\"$dueDate.set($any($event.detail.value) ?? '')\"\n data-testid=\"debtus-transfer-due-date\"\n />\n <ion-select\n label=\"Also add to a to-do list\"\n labelPlacement=\"stacked\"\n [value]=\"$todoListID()\"\n (ionChange)=\"$todoListID.set($event.detail.value ?? '')\"\n data-testid=\"debtus-transfer-todo-list\"\n >\n <ion-select-option value=\"\">Calendar only</ion-select-option>\n @for (list of $todoLists(); track list.id) {\n <ion-select-option [value]=\"list.id\">{{\n list.brief.title\n }}</ion-select-option>\n }\n </ion-select>\n <ion-button\n expand=\"block\"\n [disabled]=\"$savingDue() || !$dueDate() || !$dueTitle().trim()\"\n (click)=\"saveDueDate()\"\n data-testid=\"debtus-transfer-save-due\"\n >\n @if ($savingDue()) {\n <ion-spinner name=\"dots\" />\n } @else {\n Save due date\n }\n </ion-button>\n @if ($dueTask()) {\n <ion-button\n fill=\"clear\"\n color=\"medium\"\n [disabled]=\"$savingDue()\"\n (click)=\"saveDueDate(true)\"\n data-testid=\"debtus-transfer-clear-due\"\n >Clear due date</ion-button\n >\n }\n </ion-card-content>\n </ion-card>\n\n @if ($dueTask(); as due) {\n <ion-card>\n <ion-card-header\n ><ion-card-title>Repayment</ion-card-title></ion-card-header\n >\n <ion-card-content>\n <ion-note\n >Outstanding: {{ due.currency }}\n {{ formatMinorAmountForDisplay(due.outstandingMinor) }}</ion-note\n >\n @if (due.state !== 'completed') {\n <ion-input\n type=\"text\"\n inputmode=\"decimal\"\n label=\"Amount\"\n labelPlacement=\"stacked\"\n [value]=\"$repaymentAmount()\"\n (ionInput)=\"repaymentAmountChanged($any($event.detail.value))\"\n data-testid=\"debtus-transfer-repayment-amount\"\n />\n <ion-button\n expand=\"block\"\n color=\"success\"\n [disabled]=\"$repaying()\"\n (click)=\"recordRepayment()\"\n data-testid=\"debtus-transfer-record-repayment\"\n >\n @if ($repaying()) {\n <ion-spinner name=\"dots\" />\n } @else {\n Record repayment\n }\n </ion-button>\n }\n </ion-card-content>\n </ion-card>\n }\n\n @if ($actionError()) {\n <ion-note class=\"ion-padding\" color=\"danger\">{{\n $actionError()\n }}</ion-note>\n }\n @if ($actionSuccess()) {\n <ion-note class=\"ion-padding\" color=\"success\">{{\n $actionSuccess()\n }}</ion-note>\n }\n\n @if (t.isOutstanding && !$dueTask()) {\n <div class=\"ion-padding\">\n <ion-button expand=\"block\" color=\"success\" (click)=\"settleUp()\">\n <ion-icon name=\"checkmark-done-outline\" slot=\"start\" />\n Settle up\n </ion-button>\n </div>\n }\n }\n</ion-content>\n", dependencies: [{ kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonBackButton, selector: "ion-back-button" }, { kind: "component", type: IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"], outputs: ["ionScrollStart", "ionScroll", "ionScrollEnd"] }, { kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardHeader, selector: "ion-card-header", inputs: ["color", "mode", "translucent"] }, { kind: "component", type: IonCardTitle, selector: "ion-card-title", inputs: ["color", "mode"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonNote, selector: "ion-note", inputs: ["color", "mode"] }, { kind: "component", type: IonBadge, selector: "ion-badge", inputs: ["color", "mode"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"], outputs: ["ionFocus", "ionBlur"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["description", "disabled", "justify", "labelPlacement", "mode", "value"] }, { kind: "ngmodule", type: SpaceServiceModule }, { kind: "pipe", type: DatePipe, name: "date" }] });
220
+ }
221
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: TransferDetailsPageComponent, decorators: [{
222
+ type: Component,
223
+ args: [{ selector: 'sneat-debtus-transfer-details-page', imports: [
224
+ IonHeader,
225
+ IonToolbar,
226
+ IonButtons,
227
+ IonBackButton,
228
+ IonTitle,
229
+ IonContent,
230
+ IonCard,
231
+ IonCardHeader,
232
+ IonCardTitle,
233
+ IonCardContent,
234
+ IonList,
235
+ IonItem,
236
+ IonLabel,
237
+ IonNote,
238
+ IonBadge,
239
+ IonButton,
240
+ IonIcon,
241
+ IonSpinner,
242
+ IonInput,
243
+ IonSelect,
244
+ IonSelectOption,
245
+ DatePipe,
246
+ SpaceServiceModule,
247
+ ], providers: [
248
+ { provide: ClassName, useValue: 'TransferDetailsPageComponent' },
249
+ SpaceComponentBaseParams,
250
+ ], template: "<ion-header>\n <ion-toolbar color=\"light\">\n <ion-buttons slot=\"start\">\n <ion-back-button [defaultHref]=\"$defaultBackUrl()\" />\n </ion-buttons>\n <ion-title>Transfer</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content class=\"cardy\">\n @if ($loading()) {\n <div class=\"ion-padding ion-text-center\">\n <ion-spinner name=\"dots\" />\n </div>\n } @else if ($error()) {\n <div class=\"ion-padding\">\n <ion-note color=\"danger\">{{ $error() }}</ion-note>\n </div>\n } @else if ($transfer(); as t) {\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n {{ t.direction === 'lend' ? 'You lent' : 'You borrowed' }}\n @if (t.isReturn) {\n \u00B7 return\n }\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-badge\n [color]=\"t.direction === 'lend' ? 'success' : 'warning'\"\n style=\"font-size: 1.2rem\"\n >\n {{ formatAmount(t.amount) }}\n </ion-badge>\n </ion-card-content>\n </ion-card>\n\n <ion-card>\n <ion-list lines=\"full\">\n <ion-item button (click)=\"openContact()\">\n <ion-label>\n <p>Counterparty</p>\n <h2>{{ t.counterpartyTitle }}</h2>\n </ion-label>\n </ion-item>\n <ion-item>\n <ion-label>\n <p>Date</p>\n <h2>{{ t.created | date: 'medium' }}</h2>\n </ion-label>\n </ion-item>\n @if (t.dueOn) {\n <ion-item>\n <ion-label>\n <p>Due</p>\n <h2>{{ t.dueOn | date: 'mediumDate' }}</h2>\n </ion-label>\n </ion-item>\n }\n @if (t.note) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n <p>Note</p>\n <h2>{{ t.note }}</h2>\n </ion-label>\n </ion-item>\n }\n <ion-item>\n <ion-label>\n <p>Status</p>\n <h2>{{ t.isOutstanding ? 'Outstanding' : 'Settled' }}</h2>\n </ion-label>\n </ion-item>\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n <p>Effect on balance</p>\n <h2>\n @if (t.direction === 'lend') {\n {{ t.counterpartyTitle }} owes you {{ formatAmount(t.amount) }}\n } @else {\n You owe {{ t.counterpartyTitle }} {{ formatAmount(t.amount) }}\n }\n </h2>\n </ion-label>\n </ion-item>\n @if (t.counterpartySpaceID) {\n <ion-item>\n <ion-label class=\"ion-text-wrap\">\n <p>Cross-space</p>\n <h2>Counterparty side is in space {{ t.counterpartySpaceID }}</h2>\n <ion-note color=\"medium\">\n Your side: {{ t.creatorSpaceID }}\n </ion-note>\n </ion-label>\n </ion-item>\n }\n </ion-list>\n </ion-card>\n\n <ion-card>\n <ion-card-header\n ><ion-card-title>Due date</ion-card-title></ion-card-header\n >\n <ion-card-content>\n @if ($needsDebtusAdoption()) {\n <ion-note color=\"medium\">\n Saving this due date will enable Debtus for this space and attach\n this historical transfer to it.\n </ion-note>\n }\n <ion-input\n label=\"Reminder title\"\n labelPlacement=\"stacked\"\n [value]=\"$dueTitle()\"\n (ionInput)=\"$dueTitle.set($any($event.detail.value) ?? '')\"\n data-testid=\"debtus-transfer-due-title\"\n />\n <ion-input\n type=\"date\"\n label=\"Due date\"\n labelPlacement=\"stacked\"\n [value]=\"$dueDate()\"\n (ionInput)=\"$dueDate.set($any($event.detail.value) ?? '')\"\n data-testid=\"debtus-transfer-due-date\"\n />\n <ion-select\n label=\"Also add to a to-do list\"\n labelPlacement=\"stacked\"\n [value]=\"$todoListID()\"\n (ionChange)=\"$todoListID.set($event.detail.value ?? '')\"\n data-testid=\"debtus-transfer-todo-list\"\n >\n <ion-select-option value=\"\">Calendar only</ion-select-option>\n @for (list of $todoLists(); track list.id) {\n <ion-select-option [value]=\"list.id\">{{\n list.brief.title\n }}</ion-select-option>\n }\n </ion-select>\n <ion-button\n expand=\"block\"\n [disabled]=\"$savingDue() || !$dueDate() || !$dueTitle().trim()\"\n (click)=\"saveDueDate()\"\n data-testid=\"debtus-transfer-save-due\"\n >\n @if ($savingDue()) {\n <ion-spinner name=\"dots\" />\n } @else {\n Save due date\n }\n </ion-button>\n @if ($dueTask()) {\n <ion-button\n fill=\"clear\"\n color=\"medium\"\n [disabled]=\"$savingDue()\"\n (click)=\"saveDueDate(true)\"\n data-testid=\"debtus-transfer-clear-due\"\n >Clear due date</ion-button\n >\n }\n </ion-card-content>\n </ion-card>\n\n @if ($dueTask(); as due) {\n <ion-card>\n <ion-card-header\n ><ion-card-title>Repayment</ion-card-title></ion-card-header\n >\n <ion-card-content>\n <ion-note\n >Outstanding: {{ due.currency }}\n {{ formatMinorAmountForDisplay(due.outstandingMinor) }}</ion-note\n >\n @if (due.state !== 'completed') {\n <ion-input\n type=\"text\"\n inputmode=\"decimal\"\n label=\"Amount\"\n labelPlacement=\"stacked\"\n [value]=\"$repaymentAmount()\"\n (ionInput)=\"repaymentAmountChanged($any($event.detail.value))\"\n data-testid=\"debtus-transfer-repayment-amount\"\n />\n <ion-button\n expand=\"block\"\n color=\"success\"\n [disabled]=\"$repaying()\"\n (click)=\"recordRepayment()\"\n data-testid=\"debtus-transfer-record-repayment\"\n >\n @if ($repaying()) {\n <ion-spinner name=\"dots\" />\n } @else {\n Record repayment\n }\n </ion-button>\n }\n </ion-card-content>\n </ion-card>\n }\n\n @if ($actionError()) {\n <ion-note class=\"ion-padding\" color=\"danger\">{{\n $actionError()\n }}</ion-note>\n }\n @if ($actionSuccess()) {\n <ion-note class=\"ion-padding\" color=\"success\">{{\n $actionSuccess()\n }}</ion-note>\n }\n\n @if (t.isOutstanding && !$dueTask()) {\n <div class=\"ion-padding\">\n <ion-button expand=\"block\" color=\"success\" (click)=\"settleUp()\">\n <ion-icon name=\"checkmark-done-outline\" slot=\"start\" />\n Settle up\n </ion-button>\n </div>\n }\n }\n</ion-content>\n" }]
251
+ }], ctorParameters: () => [] });
252
+
253
+ export { TransferDetailsPageComponent };
254
+ //# sourceMappingURL=sneat-extension-debtus-ui-transfer-details-page.component-BSDIDPAb.mjs.map