Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions AppListing/93005fb3-c47f-4252-a365-7eeceaf3dae1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"data": {
"meta": {
"adoptsFrom": {
"name": "AppListing",
"module": "https://realms-staging.stack.cards/catalog/catalog-app/listing/listing"
}
},
"type": "card",
"attributes": {
"name": "Single-Entry Account Ledger Catalog Listing",
"images": [],
"summary": "The SingleEntryAccountLedger component provides a visual and data structure for tracking and managing a financial account with a single-entry (cash book style) ledger. Its primary purpose is to record, display, and summarize account transactions, including credits and debits, to facilitate easy reconciliation of account balances over time. It supports embedded and full-width formats, allowing it to be integrated into various user interfaces for monitoring account activity, presenting running balances, and adding new ledger entries seamlessly.",
"cardInfo": {
"name": null,
"notes": null,
"summary": null,
"cardThumbnailURL": null
}
},
"relationships": {
"skills": {
"links": {
"self": null
}
},
"tags.0": {
"links": {
"self": "https://realms-staging.stack.cards/catalog/Tag/140feda8-625b-4a24-9ddb-6f4da891aef2"
}
},
"tags.1": {
"links": {
"self": "https://realms-staging.stack.cards/catalog/Tag/4d0f9ae2-048e-4ce0-b263-7006602ce6a4"
}
},
"license": {
"links": {
"self": "https://realms-staging.stack.cards/catalog/License/4c5a023b-a72c-4f90-930b-da60a1de5b2d"
}
},
"specs.0": {
"links": {
"self": "../Spec/64c751f3-a579-4e28-b257-5be7db15f9e8"
}
},
"specs.1": {
"links": {
"self": "../Spec/f3a5793e-2872-475b-a7db-15f9e81a1033"
}
},
"publisher": {
"links": {
"self": null
}
},
"categories.0": {
"links": {
"self": "https://realms-staging.stack.cards/catalog/Category/software-development"
}
},
"categories.1": {
"links": {
"self": "https://realms-staging.stack.cards/catalog/Category/web-development"
}
},
"examples.0": {
"links": {
"self": "../SingleEntryAccountLedger/6c93a7ce-ccd0-4c8d-87de-28963ac8ed6b"
}
},
"cardInfo.theme": {
"links": {
"self": null
}
}
}
}
}
96 changes: 96 additions & 0 deletions SingleEntryAccountLedger/6c93a7ce-ccd0-4c8d-87de-28963ac8ed6b.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"data": {
"meta": {
"adoptsFrom": {
"name": "SingleEntryAccountLedger",
"module": "../single-entry-account-ledger"
}
},
"type": "card",
"attributes": {
"entries": [
{
"entryDate": "2026-03-11",
"description": "Morning Coffee Sales",
"debit": null,
"credit": 250,
"reference": "Money coming IN from customers",
"category": null
},
{
"entryDate": "2026-03-11",
"description": "Coffee beans purchase",
"debit": 80,
"credit": null,
"reference": "Money going OUT for supplies",
"category": null
},
{
"entryDate": "2026-03-11",
"description": "Afternoon sales",
"debit": null,
"credit": 180,
"reference": "More money IN",
"category": null
},
{
"entryDate": "2026-03-11",
"description": "Electricity bill",
"debit": 45,
"credit": null,
"reference": "Money OUT for utilities",
"category": null
},
{
"entryDate": "2026-03-11",
"description": "Catering order",
"debit": null,
"credit": 320,
"reference": "Big order = money IN",
"category": null
},
{
"entryDate": "2026-03-11",
"description": "Staff wages",
"debit": 400,
"credit": null,
"reference": "Paying employees = money OUT",
"category": null
},
{
"entryDate": "2026-03-11",
"description": "Weekend sales",
"debit": null,
"credit": 290,
"reference": "Weekend rush = money IN",
"category": null
},
{
"entryDate": "2026-03-11",
"description": "test",
"debit": null,
"credit": 50,
"reference": "a thing",
"category": "huh"
}
],
"cardInfo": {
"name": "My Coffee Shop",
"notes": "This is ledger for 2025 Coffee Shop Account",
"summary": null,
"cardThumbnailURL": null
},
"currency": "$",
"accountName": "Coffee Shop Account",
"accountNumber": "8886767676767",
"openingBalance": 1000
},
"relationships": {
"cardInfo.theme": {
"links": {
"self": null
}
}
}
}
}
40 changes: 40 additions & 0 deletions Spec/64c751f3-a579-4e28-b257-5be7db15f9e8.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"data": {
"type": "card",
"attributes": {
"readMe": null,
"ref": {
"module": "../ledger-entry-field",
"name": "LedgerEntryField"
},
"specType": "field",
"containedExamples": [],
"cardTitle": "Ledger Entry",
"cardDescription": null,
"cardInfo": {
"name": null,
"summary": null,
"cardThumbnailURL": null,
"notes": null
}
},
"relationships": {
"linkedExamples": {
"links": {
"self": null
}
},
"cardInfo.theme": {
"links": {
"self": null
}
}
},
"meta": {
"adoptsFrom": {
"module": "https://cardstack.com/base/spec",
"name": "Spec"
}
}
}
}
40 changes: 40 additions & 0 deletions Spec/f3a5793e-2872-475b-a7db-15f9e81a1033.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"data": {
"type": "card",
"attributes": {
"readMe": null,
"ref": {
"module": "../single-entry-account-ledger",
"name": "SingleEntryAccountLedger"
},
"specType": "card",
"containedExamples": [],
"cardTitle": "Single-Entry Account Ledger",
"cardDescription": null,
"cardInfo": {
"name": null,
"summary": null,
"cardThumbnailURL": null,
"notes": null
}
},
"relationships": {
"linkedExamples": {
"links": {
"self": null
}
},
"cardInfo.theme": {
"links": {
"self": null
}
}
},
"meta": {
"adoptsFrom": {
"module": "https://cardstack.com/base/spec",
"name": "Spec"
}
}
}
}
65 changes: 65 additions & 0 deletions ledger-entry-field.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// ═══ [EDIT TRACKING: ON] Mark all changes with ⁿ ═══
import {
FieldDef, // ¹ FieldDef for embedded data
field,
contains,
Component,
} from 'https://cardstack.com/base/card-api';
import StringField from 'https://cardstack.com/base/string';
import NumberField from 'https://cardstack.com/base/number';
import DateField from 'https://cardstack.com/base/date';

export class LedgerEntryField extends FieldDef { // ² FieldDef, not CardDef
static displayName = 'Ledger Entry';

@field entryDate = contains(DateField);
@field description = contains(StringField);
@field debit = contains(NumberField);
@field credit = contains(NumberField);
@field reference = contains(StringField);
@field category = contains(StringField);

// ³ Embedded template for display within parent
static embedded = class Embedded extends Component<typeof LedgerEntryField> {
get debitDisplay() {
const d = this.args.model?.debit;
if (!d || d <= 0) return '';
return d.toLocaleString('en-US', { minimumFractionDigits: 2 });
}

get creditDisplay() {
const c = this.args.model?.credit;
if (!c || c <= 0) return '';
return c.toLocaleString('en-US', { minimumFractionDigits: 2 });
}

<template>
<div class="entry-row">
<span class="date">{{if @model.entryDate @model.entryDate "—"}}</span>
<span class="desc">{{if @model.description @model.description "—"}}</span>
<span class="ref">{{if @model.reference @model.reference ""}}</span>
<span class="debit">{{this.debitDisplay}}</span>
<span class="credit">{{this.creditDisplay}}</span>
</div>

<style scoped>
.entry-row {
display: grid;
grid-template-columns: 100px 1fr 80px 90px 90px;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
border-bottom: 1px solid var(--border, #e5e5e5);
align-items: center;
}
.entry-row:hover { background: var(--muted, #f5f5f5); }
.date { color: var(--muted-foreground, #6b7280); }
.desc { font-weight: 500; }
.ref { color: var(--muted-foreground, #6b7280); font-size: 0.75rem; }
.debit, .credit { text-align: right; font-weight: 500; }
.debit { color: hsl(0 84% 50%); }
.credit { color: hsl(142 76% 36%); }
</style>
</template>
};
}
Loading
Loading