diff --git a/CardListing/05e5c772-d134-43b2-99c8-151e5c96bc27.json b/CardListing/05e5c772-d134-43b2-99c8-151e5c96bc27.json new file mode 100644 index 0000000..1c6e8fd --- /dev/null +++ b/CardListing/05e5c772-d134-43b2-99c8-151e5c96bc27.json @@ -0,0 +1,84 @@ +{ + "data": { + "meta": { + "adoptsFrom": { + "name": "CardListing", + "module": "https://realms-staging.stack.cards/catalog/catalog-app/listing/listing" + } + }, + "type": "card", + "attributes": { + "name": "To-Do Item Management Card", + "images": [], + "summary": "The Todo component defines a structured representation of a task with properties such as title, description, status, priority, due date, and completion state. It provides multiple visual formats—isolated, embedded, fitted, badge, strip, tile, and card—to suit different UI contexts and device sizes. Using descriptive labels and color-coded badges, it visually communicates task status and priority. The component supports dynamic computation of display elements, conditional rendering, and scoped styling to present task details clearly and adaptively across various layouts. Its main purpose is to serve as a flexible, stylized todo-list item for task management interfaces.", + "cardInfo": { + "name": null, + "notes": null, + "summary": null, + "cardThumbnailURL": null + } + }, + "relationships": { + "tags": { + "links": { + "self": null + } + }, + "skills": { + "links": { + "self": null + } + }, + "license": { + "links": { + "self": null + } + }, + "specs.0": { + "links": { + "self": "../Spec/c41b4e4c-f364-4677-a461-80f0c2bb105f" + } + }, + "publisher": { + "links": { + "self": null + } + }, + "categories": { + "links": { + "self": null + } + }, + "examples.0": { + "links": { + "self": "../Todo/c48139c8-05e5-4772-9134-13b259c8151e" + } + }, + "examples.1": { + "links": { + "self": "../Todo/77254bcc-c678-4649-845f-189496460355" + } + }, + "examples.2": { + "links": { + "self": "../Todo/update-readme" + } + }, + "examples.3": { + "links": { + "self": "../Todo/design-review" + } + }, + "examples.4": { + "links": { + "self": "../Todo/fix-login-bug" + } + }, + "cardInfo.theme": { + "links": { + "self": null + } + } + } + } +} \ No newline at end of file diff --git a/Spec/c41b4e4c-f364-4677-a461-80f0c2bb105f.json b/Spec/c41b4e4c-f364-4677-a461-80f0c2bb105f.json new file mode 100644 index 0000000..659577c --- /dev/null +++ b/Spec/c41b4e4c-f364-4677-a461-80f0c2bb105f.json @@ -0,0 +1,40 @@ +{ + "data": { + "meta": { + "adoptsFrom": { + "name": "Spec", + "module": "https://cardstack.com/base/spec" + } + }, + "type": "card", + "attributes": { + "ref": { + "name": "Todo", + "module": "../todo" + }, + "readMe": "Here is the usage documentation for the Todo card spec:\n\n## Todo\n\n**Summary**:\nThe Todo card spec defines a card for tracking tasks, including fields for title, description, status, priority, due date, and completion status.\n\n**Import**:\n```gts\nimport { Todo } from 'https://realms-staging.stack.cards/richard.tan/deep-whippet-89/todo';\n```\n\n**Usage as a Field**:\nTo use the Todo card as a field, import the spec and include it as a `linksTo` field:\n\n```gts\n@field todo = linksTo(Todo);\n```\n\n**Template Usage**:\nTo display a Todo card in a template, use the field name and specify the desired format:\n\n```hbs\n<@fields.todo @format=\"isolated\" />\n```\n\nThis will render the Todo card in the isolated format, which provides a detailed view of the task.", + "cardInfo": { + "name": null, + "notes": null, + "summary": null, + "cardThumbnailURL": null + }, + "specType": "card", + "cardTitle": "Todo", + "cardDescription": null, + "containedExamples": [] + }, + "relationships": { + "cardInfo.theme": { + "links": { + "self": null + } + }, + "linkedExamples": { + "links": { + "self": null + } + } + } + } +} \ No newline at end of file diff --git a/Todo/77254bcc-c678-4649-845f-189496460355.json b/Todo/77254bcc-c678-4649-845f-189496460355.json new file mode 100644 index 0000000..b345924 --- /dev/null +++ b/Todo/77254bcc-c678-4649-845f-189496460355.json @@ -0,0 +1,25 @@ +{ + "data": { + "type": "card", + "attributes": { + "title": null, + "description": null, + "status": null, + "priority": null, + "dueDate": null, + "completed": false, + "cardInfo": { + "name": null, + "summary": null, + "cardThumbnailURL": null, + "notes": null + } + }, + "meta": { + "adoptsFrom": { + "module": "../todo", + "name": "Todo" + } + } + } +} \ No newline at end of file diff --git a/Todo/c48139c8-05e5-4772-9134-13b259c8151e.json b/Todo/c48139c8-05e5-4772-9134-13b259c8151e.json new file mode 100644 index 0000000..b345924 --- /dev/null +++ b/Todo/c48139c8-05e5-4772-9134-13b259c8151e.json @@ -0,0 +1,25 @@ +{ + "data": { + "type": "card", + "attributes": { + "title": null, + "description": null, + "status": null, + "priority": null, + "dueDate": null, + "completed": false, + "cardInfo": { + "name": null, + "summary": null, + "cardThumbnailURL": null, + "notes": null + } + }, + "meta": { + "adoptsFrom": { + "module": "../todo", + "name": "Todo" + } + } + } +} \ No newline at end of file diff --git a/Todo/design-review.json b/Todo/design-review.json new file mode 100644 index 0000000..f74aad8 --- /dev/null +++ b/Todo/design-review.json @@ -0,0 +1,32 @@ +{ + "data": { + "meta": { + "adoptsFrom": { + "name": "Todo", + "module": "../todo" + } + }, + "type": "card", + "attributes": { + "title": "Conduct Q2 design review", + "status": "done", + "dueDate": "2026-04-05", + "cardInfo": { + "name": "Conduct Q2 design review", + "notes": null, + "summary": "Review and finalize Q2 dashboard mockups with the team", + "cardThumbnailURL": null + }, + "priority": "medium", + "completed": true, + "description": "Schedule and run a design review session with the team to evaluate the new dashboard mockups. Collect feedback, document action items, and align on the final direction before handoff to engineering." + }, + "relationships": { + "cardInfo.theme": { + "links": { + "self": null + } + } + } + } +} \ No newline at end of file diff --git a/Todo/fix-login-bug.json b/Todo/fix-login-bug.json new file mode 100644 index 0000000..c9eb9fd --- /dev/null +++ b/Todo/fix-login-bug.json @@ -0,0 +1,32 @@ +{ + "data": { + "meta": { + "adoptsFrom": { + "name": "Todo", + "module": "../todo" + } + }, + "type": "card", + "attributes": { + "title": "Fix login authentication bug", + "status": "in-progress", + "dueDate": "2026-04-10", + "cardInfo": { + "name": "Fix login authentication bug", + "notes": null, + "summary": "Investigate and fix JWT token refresh causing unexpected logouts", + "cardThumbnailURL": null + }, + "priority": "high", + "completed": false, + "description": "Users are being logged out unexpectedly after 5 minutes due to a token refresh issue. Investigate the JWT expiry logic and ensure the refresh token flow is working correctly." + }, + "relationships": { + "cardInfo.theme": { + "links": { + "self": null + } + } + } + } +} \ No newline at end of file diff --git a/Todo/update-readme.json b/Todo/update-readme.json new file mode 100644 index 0000000..78c8b7a --- /dev/null +++ b/Todo/update-readme.json @@ -0,0 +1,32 @@ +{ + "data": { + "meta": { + "adoptsFrom": { + "name": "Todo", + "module": "../todo" + } + }, + "type": "card", + "attributes": { + "title": "Update project README", + "status": "todo", + "dueDate": "2026-04-18", + "cardInfo": { + "name": "Update project README", + "notes": null, + "summary": "Add Docker setup instructions and contribution guidelines to the README", + "cardThumbnailURL": null + }, + "priority": "low", + "completed": false, + "description": "The README is outdated and missing setup instructions for the new Docker-based development environment. Add installation steps, environment variable documentation, and contribution guidelines." + }, + "relationships": { + "cardInfo.theme": { + "links": { + "self": null + } + } + } + } +} \ No newline at end of file diff --git a/todo.gts b/todo.gts new file mode 100644 index 0000000..a53b2e8 --- /dev/null +++ b/todo.gts @@ -0,0 +1,715 @@ +// ═══ [EDIT TRACKING: ON] Mark all changes with ⁿ ═══ +import { + // ¹ Core imports + CardDef, + Component, + field, + contains, +} from 'https://cardstack.com/base/card-api'; +import StringField from 'https://cardstack.com/base/string'; // ² +import BooleanField from 'https://cardstack.com/base/boolean'; // ³ +import DateField from 'https://cardstack.com/base/date'; // ⁴ +import TextAreaField from 'https://cardstack.com/base/text-area'; // ⁵ +import enumField from 'https://cardstack.com/base/enum'; // ⁶ +import { formatDateTime } from '@cardstack/boxel-ui/helpers'; // ⁷ +import { eq } from '@cardstack/boxel-ui/helpers'; // ⁸ +import CheckSquareIcon from '@cardstack/boxel-icons/square-check'; // ⁹ + +// ¹⁰ Priority enum field +const PriorityField = enumField(StringField, { + options: [ + { value: 'low', label: 'Low' }, + { value: 'medium', label: 'Medium' }, + { value: 'high', label: 'High' }, + ], +}); + +// ¹¹ Status enum field +const StatusField = enumField(StringField, { + options: [ + { value: 'todo', label: 'To Do' }, + { value: 'in-progress', label: 'In Progress' }, + { value: 'done', label: 'Done' }, + ], +}); + +export class Todo extends CardDef { + // ¹² + static displayName = 'Todo'; + static icon = CheckSquareIcon; + + @field title = contains(StringField); // ¹³ + @field description = contains(TextAreaField); // ¹⁴ + @field status = contains(StatusField); // ¹⁵ + @field priority = contains(PriorityField); // ¹⁶ + @field dueDate = contains(DateField); // ¹⁷ + @field completed = contains(BooleanField); // ¹⁸ + + @field cardTitle = contains(StringField, { + // ¹⁹ + computeVia: function (this: Todo) { + return this.cardInfo?.name ?? this.title ?? 'Untitled Todo'; + }, + }); + + static isolated = class Isolated extends Component { + // ²⁰ + get statusLabel() { + const s = this.args.model?.status; + if (s === 'done') return 'Done'; + if (s === 'in-progress') return 'In Progress'; + return 'To Do'; + } + + get priorityLabel() { + const p = this.args.model?.priority; + if (p === 'high') return 'High'; + if (p === 'medium') return 'Medium'; + return 'Low'; + } + + get priorityClass() { + const p = this.args.model?.priority; + if (p === 'high') return 'priority-high'; + if (p === 'medium') return 'priority-medium'; + return 'priority-low'; + } + + get statusClass() { + const s = this.args.model?.status; + if (s === 'done') return 'status-done'; + if (s === 'in-progress') return 'status-in-progress'; + return 'status-todo'; + } + + + }; + + static embedded = class Embedded extends Component { + // ²² + get statusClass() { + const s = this.args.model?.status; + if (s === 'done') return 'status-done'; + if (s === 'in-progress') return 'status-in-progress'; + return 'status-todo'; + } + + get statusLabel() { + const s = this.args.model?.status; + if (s === 'done') return 'Done'; + if (s === 'in-progress') return 'In Progress'; + return 'To Do'; + } + + get priorityClass() { + const p = this.args.model?.priority; + if (p === 'high') return 'priority-high'; + if (p === 'medium') return 'priority-medium'; + return 'priority-low'; + } + + get priorityLabel() { + const p = this.args.model?.priority; + if (p === 'high') return 'High'; + if (p === 'medium') return 'Medium'; + return 'Low'; + } + + + }; + + static fitted = class Fitted extends Component { + // ²⁴ + get statusClass() { + const s = this.args.model?.status; + if (s === 'done') return 'status-done'; + if (s === 'in-progress') return 'status-in-progress'; + return 'status-todo'; + } + + get statusLabel() { + const s = this.args.model?.status; + if (s === 'done') return 'Done'; + if (s === 'in-progress') return 'In Progress'; + return 'To Do'; + } + + get priorityClass() { + const p = this.args.model?.priority; + if (p === 'high') return 'priority-high'; + if (p === 'medium') return 'priority-medium'; + return 'priority-low'; + } + + get priorityDot() { + const p = this.args.model?.priority; + if (p === 'high') return '🔴'; + if (p === 'medium') return '🟡'; + return '🟢'; + } + + + }; +}