From a5cd9538b0db731a0d0e10e58804ef8ad32211b7 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Fri, 13 Feb 2026 07:13:18 -0800 Subject: Implement Frontend Settings with tests --- .thicket/tickets.jsonl | 6 +- frontend/coverage/clover.xml | 67 ++- frontend/coverage/coverage-final.json | 4 +- frontend/coverage/index.html | 56 +-- frontend/coverage/src/App.css.html | 2 +- frontend/coverage/src/App.tsx.html | 54 ++- frontend/coverage/src/components/FeedItem.css.html | 2 +- frontend/coverage/src/components/FeedItem.tsx.html | 2 +- .../coverage/src/components/FeedItems.css.html | 2 +- .../coverage/src/components/FeedItems.tsx.html | 2 +- frontend/coverage/src/components/FeedList.css.html | 2 +- frontend/coverage/src/components/FeedList.tsx.html | 2 +- frontend/coverage/src/components/Login.css.html | 2 +- frontend/coverage/src/components/Login.tsx.html | 2 +- frontend/coverage/src/components/Settings.css.html | 331 +++++++++++++++ frontend/coverage/src/components/Settings.tsx.html | 448 +++++++++++++++++++++ frontend/coverage/src/components/index.html | 48 ++- frontend/coverage/src/index.html | 34 +- frontend/src/App.tsx | 12 + frontend/src/components/Settings.css | 83 ++++ frontend/src/components/Settings.test.tsx | 92 +++++ frontend/src/components/Settings.tsx | 121 ++++++ 22 files changed, 1290 insertions(+), 84 deletions(-) create mode 100644 frontend/coverage/src/components/Settings.css.html create mode 100644 frontend/coverage/src/components/Settings.tsx.html create mode 100644 frontend/src/components/Settings.css create mode 100644 frontend/src/components/Settings.test.tsx create mode 100644 frontend/src/components/Settings.tsx diff --git a/.thicket/tickets.jsonl b/.thicket/tickets.jsonl index 312d198..ef27c08 100644 --- a/.thicket/tickets.jsonl +++ b/.thicket/tickets.jsonl @@ -1,5 +1,5 @@ {"id":"NK-0nf7hu","title":"Implement Frontend Logout","description":"Add logout button/link in dashboard and call /api/logout.","type":"task","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-13T05:50:46.760744241Z","updated":"2026-02-13T05:50:46.760744241Z"} -{"id":"NK-0ppv3f","title":"Implement Frontend Settings","description":"Create settings page for managing feeds/categories.","type":"task","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-13T05:44:01.631640578Z","updated":"2026-02-13T05:44:01.631640578Z"} +{"id":"NK-0ppv3f","title":"Implement Frontend Settings","description":"Create settings page for managing feeds/categories.","type":"task","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T05:44:01.631640578Z","updated":"2026-02-13T15:04:12.408401691Z"} {"id":"NK-1phdpf","title":"refactor backend to have a clean API","description":"create a nice clean API for the backend GO code that is more independent of the frontend\n\nensure that it is working with good tests","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T01:52:49.8322638Z","updated":"2026-02-13T04:26:47.517515371Z"} {"id":"NK-27or4b","title":"Increase Test Coverage to \u003e80%","description":"Project-wide test coverage is currently ~63%. Key gaps are in the new and packages, as well as some core model logic. Increase coverage to at least 80% to ensure stability.","type":"task","status":"open","priority":3,"labels":null,"assignee":"","created":"2026-02-13T05:03:09.677147894Z","updated":"2026-02-13T05:03:09.677147894Z"} {"id":"NK-3om7x2","title":"Implement Feed Items View","description":"Create a component to display items for a selected feed. Fetch items from /api/stream?feed_id=...","type":"","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T05:59:46.161356437Z","updated":"2026-02-13T14:55:14.795643835Z"} @@ -11,19 +11,23 @@ {"id":"NK-ed1iah","title":"Make feed crawling async in API","description":"Currently, POST /api/feed triggers an immediate crawl which blocks the response (or at least keeps the goroutine alive). Refactor the crawling architecture to be truly async with a job queue or status updates, improving API responsiveness and reliability.","type":"cleanup","status":"open","priority":3,"labels":null,"assignee":"","created":"2026-02-13T04:26:55.908243985Z","updated":"2026-02-13T04:26:55.908243985Z"} {"id":"NK-ek0cox","title":"Implement Item Interactions","description":"Add ability to toggle read/unread and star/unstar status for items. Use PUT /item/:id","type":"","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T14:55:14.825454967Z","updated":"2026-02-13T14:58:18.307521003Z"} {"id":"NK-gqkh96","title":"Remaining test coverage gaps","description":"Cross-package test coverage is at 81.2%. The remaining untested functions are: GetFullContent (goose HTTP extraction), indexHandler/serveBoxedFile (rice.MustFindBox), Serve (starts HTTP server), main, util.init. To reach 90%, consider: (1) refactoring GetFullContent to accept an interface for HTTP fetching, (2) refactoring Serve to extract route setup into a testable function, (3) mocking rice.MustFindBox, (4) using feeds from https://trenchant.org/feeds.txt as static test fixtures for integration tests.","type":"cleanup","status":"open","priority":3,"labels":null,"assignee":"","created":"2026-02-13T03:54:30.298141982Z","updated":"2026-02-13T03:54:30.298141982Z"} +{"id":"NK-mwf9q2","title":"Implement Tag View","description":"Create frontend view for browsing items by tag/category. Use /tag/:id endpoint.","type":"","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-13T15:04:12.441165286Z","updated":"2026-02-13T15:04:12.441165286Z"} {"id":"NK-op5594","title":"Ensure 80% Frontend Test Coverage","description":"Configure coverage reporting in vitest and ensure the frontend codebase maintains at least 80% test coverage.","type":"task","status":"closed","priority":2,"labels":null,"assignee":"","created":"2026-02-13T05:46:24.13314466Z","updated":"2026-02-13T05:50:46.728239299Z"} {"id":"NK-ric1zs","title":"Migrate frontend to /api/ endpoints","description":"The backend now provides a clean REST API at /api/. Update the frontend UI to use these new endpoints instead of the legacy backward-compatibility routes (/stream/, /feed/, etc.). This will allow for cleaner separation and better utilization of proper REST patterns.","type":"cleanup","status":"open","priority":3,"labels":null,"assignee":"","created":"2026-02-13T04:26:55.864725765Z","updated":"2026-02-13T04:26:55.864725765Z"} +{"id":"NK-sne5ox","title":"Implement Export/Import UI","description":"Add UI in settings to download OPML export and upload OPML import. Use /export/ and /import/ (need to check if import exists).","type":"","status":"open","priority":3,"labels":null,"assignee":"","created":"2026-02-13T15:05:23.266731399Z","updated":"2026-02-13T15:05:23.266731399Z"} {"id":"NK-t0nmbj","title":"new web frontend","description":"The current frontend uses an old version of backbone and jquery. Let's \"deprecate\" it -- keep it arouond so we can test against it and use it, but let's be able to also serve and use a nice shiny new frontend written in either simiple, highly efficient vanilla javascript, or put together something in react or similar. Needs to feel fast and low latency!\n\nIt's very important that this new frontend has all the functionality of the existing one AND looks similar (use same style, etc, but adjust a little if needed.)\n\nALSO make it highly testable and have high test coverage as you go. I don't want it to use the Chrome browser plugin thing, just test it on your own using things from the command line you can do.","type":"epic","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-13T02:01:37.2107893Z","updated":"2026-02-13T05:43:47.613995925Z"} {"id":"NK-tw0nga","title":"E2E Testing","description":"Set up E2E testing with Playwright or Cypress to verify full flows: Login -\u003e View Feeds -\u003e View Items -\u003e Logout","type":"","status":"open","priority":2,"labels":null,"assignee":"","created":"2026-02-13T15:01:33.817314728Z","updated":"2026-02-13T15:01:33.817314728Z"} {"id":"NK-x924bu","title":"test coverage","description":"assume the code works properly (it mostly does)\nget to 90% test coverage on the go code","type":"task","status":"closed","priority":0,"labels":null,"assignee":"","created":"2026-02-13T01:52:01.042476226Z","updated":"2026-02-13T03:54:21.526519915Z"} {"id":"NK-zt4e32","title":"Implement Frontend Feed List","description":"Create feed list view in new frontend. Fetch feeds from API.","type":"task","status":"closed","priority":1,"labels":null,"assignee":"","created":"2026-02-13T05:44:01.58866298Z","updated":"2026-02-13T05:59:46.132148641Z"} {"id":"NK-d0ghccy","from_ticket_id":"NK-ric1zs","to_ticket_id":"NK-1phdpf","type":"created_from","created":"2026-02-13T04:26:55.875394997Z"} +{"id":"NK-d0lgaab","from_ticket_id":"NK-sne5ox","to_ticket_id":"NK-0ppv3f","type":"created_from","created":"2026-02-13T15:05:23.289745853Z"} {"id":"NK-d1uyy71","from_ticket_id":"NK-27or4b","to_ticket_id":"NK-bsdwqz","type":"created_from","created":"2026-02-13T05:03:09.689282214Z"} {"id":"NK-d50pbhs","from_ticket_id":"NK-zt4e32","to_ticket_id":"NK-t0nmbj","type":"created_from","created":"2026-02-13T05:44:01.598803513Z"} {"id":"NK-d86tgcs","from_ticket_id":"NK-ed1iah","to_ticket_id":"NK-1phdpf","type":"created_from","created":"2026-02-13T04:26:55.917754798Z"} {"id":"NK-dew7hvb","from_ticket_id":"NK-tw0nga","to_ticket_id":"NK-59kbij","type":"created_from","created":"2026-02-13T15:01:33.825547908Z"} {"id":"NK-dgbrb79","from_ticket_id":"NK-9hx0y7","to_ticket_id":"NK-t0nmbj","type":"created_from","created":"2026-02-13T05:44:01.556027956Z"} {"id":"NK-dgfppki","from_ticket_id":"NK-gqkh96","to_ticket_id":"NK-x924bu","type":"created_from","created":"2026-02-13T03:54:30.303602703Z"} +{"id":"NK-dkhu8ov","from_ticket_id":"NK-mwf9q2","to_ticket_id":"NK-0ppv3f","type":"created_from","created":"2026-02-13T15:04:12.449401674Z"} {"id":"NK-dl8clj9","from_ticket_id":"NK-0nf7hu","to_ticket_id":"NK-9hx0y7","type":"created_from","created":"2026-02-13T05:50:46.769436228Z"} {"id":"NK-dlvmiyc","from_ticket_id":"NK-7tzbql","to_ticket_id":"NK-bsdwqz","type":"created_from","created":"2026-02-13T05:02:57.392616851Z"} {"id":"NK-dm75oc8","from_ticket_id":"NK-3om7x2","to_ticket_id":"NK-zt4e32","type":"created_from","created":"2026-02-13T05:59:46.169842933Z"} diff --git a/frontend/coverage/clover.xml b/frontend/coverage/clover.xml index a6ecc62..26fec33 100644 --- a/frontend/coverage/clover.xml +++ b/frontend/coverage/clover.xml @@ -1,14 +1,14 @@ - - - + + + - + - + @@ -22,14 +22,16 @@ - - - - + + + + + + - + @@ -126,6 +128,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/coverage/coverage-final.json b/frontend/coverage/coverage-final.json index 2a5fa12..14d4351 100644 --- a/frontend/coverage/coverage-final.json +++ b/frontend/coverage/coverage-final.json @@ -1,5 +1,5 @@ {"/Users/adam/workspace/vibecode/neko/frontend/src/App.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/App.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/App.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/App.tsx","statementMap":{"0":{"start":{"line":8,"column":22},"end":{"line":8,"column":null}},"1":{"start":{"line":9,"column":8},"end":{"line":9,"column":null}},"2":{"start":{"line":11,"column":2},"end":{"line":21,"column":null}},"3":{"start":{"line":12,"column":4},"end":{"line":20,"column":null}},"4":{"start":{"line":14,"column":8},"end":{"line":18,"column":null}},"5":{"start":{"line":15,"column":10},"end":{"line":15,"column":null}},"6":{"start":{"line":17,"column":10},"end":{"line":17,"column":null}},"7":{"start":{"line":20,"column":19},"end":{"line":20,"column":33}},"8":{"start":{"line":23,"column":2},"end":{"line":25,"column":null}},"9":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"10":{"start":{"line":27,"column":2},"end":{"line":29,"column":null}},"11":{"start":{"line":28,"column":4},"end":{"line":28,"column":null}},"12":{"start":{"line":31,"column":2},"end":{"line":31,"column":null}},"13":{"start":{"line":38,"column":2},"end":{"line":62,"column":null}},"14":{"start":{"line":44,"column":12},"end":{"line":45,"column":null}},"15":{"start":{"line":45,"column":26},"end":{"line":45,"column":58}},"16":{"start":{"line":67,"column":2},"end":{"line":80,"column":null}}},"fnMap":{"0":{"name":"RequireAuth","decl":{"start":{"line":7,"column":9},"end":{"line":7,"column":21}},"loc":{"start":{"line":7,"column":69},"end":{"line":32,"column":null}},"line":7},"1":{"name":"(anonymous_1)","decl":{"start":{"line":11,"column":12},"end":{"line":11,"column":18}},"loc":{"start":{"line":11,"column":18},"end":{"line":21,"column":5}},"line":11},"2":{"name":"(anonymous_2)","decl":{"start":{"line":13,"column":12},"end":{"line":13,"column":13}},"loc":{"start":{"line":13,"column":21},"end":{"line":19,"column":7}},"line":13},"3":{"name":"(anonymous_3)","decl":{"start":{"line":20,"column":13},"end":{"line":20,"column":19}},"loc":{"start":{"line":20,"column":19},"end":{"line":20,"column":33}},"line":20},"4":{"name":"Dashboard","decl":{"start":{"line":37,"column":9},"end":{"line":37,"column":21}},"loc":{"start":{"line":37,"column":21},"end":{"line":64,"column":null}},"line":37},"5":{"name":"(anonymous_5)","decl":{"start":{"line":43,"column":27},"end":{"line":43,"column":33}},"loc":{"start":{"line":43,"column":33},"end":{"line":46,"column":13}},"line":43},"6":{"name":"(anonymous_6)","decl":{"start":{"line":45,"column":20},"end":{"line":45,"column":26}},"loc":{"start":{"line":45,"column":26},"end":{"line":45,"column":58}},"line":45},"7":{"name":"App","decl":{"start":{"line":66,"column":9},"end":{"line":66,"column":15}},"loc":{"start":{"line":66,"column":15},"end":{"line":82,"column":null}},"line":66}},"branchMap":{"0":{"loc":{"start":{"line":14,"column":8},"end":{"line":18,"column":null}},"type":"if","locations":[{"start":{"line":14,"column":8},"end":{"line":18,"column":null}},{"start":{"line":16,"column":15},"end":{"line":18,"column":null}}],"line":14},"1":{"loc":{"start":{"line":23,"column":2},"end":{"line":25,"column":null}},"type":"if","locations":[{"start":{"line":23,"column":2},"end":{"line":25,"column":null}},{"start":{},"end":{}}],"line":23},"2":{"loc":{"start":{"line":27,"column":2},"end":{"line":29,"column":null}},"type":"if","locations":[{"start":{"line":27,"column":2},"end":{"line":29,"column":null}},{"start":{},"end":{}}],"line":27}},"s":{"0":2,"1":2,"2":2,"3":1,"4":1,"5":1,"6":0,"7":0,"8":2,"9":1,"10":1,"11":0,"12":1,"13":1,"14":1,"15":1,"16":2},"f":{"0":2,"1":1,"2":1,"3":0,"4":1,"5":1,"6":1,"7":2},"b":{"0":[1,0],"1":[1,1],"2":[0,1]},"meta":{"lastBranch":3,"lastFunction":8,"lastStatement":17,"seen":{"f:7:9:7:21":0,"s:8:22:8:Infinity":0,"s:9:8:9:Infinity":1,"s:11:2:21:Infinity":2,"f:11:12:11:18":1,"s:12:4:20:Infinity":3,"f:13:12:13:13":2,"b:14:8:18:Infinity:16:15:18:Infinity":0,"s:14:8:18:Infinity":4,"s:15:10:15:Infinity":5,"s:17:10:17:Infinity":6,"f:20:13:20:19":3,"s:20:19:20:33":7,"b:23:2:25:Infinity:undefined:undefined:undefined:undefined":1,"s:23:2:25:Infinity":8,"s:24:4:24:Infinity":9,"b:27:2:29:Infinity:undefined:undefined:undefined:undefined":2,"s:27:2:29:Infinity":10,"s:28:4:28:Infinity":11,"s:31:2:31:Infinity":12,"f:37:9:37:21":4,"s:38:2:62:Infinity":13,"f:43:27:43:33":5,"s:44:12:45:Infinity":14,"f:45:20:45:26":6,"s:45:26:45:58":15,"f:66:9:66:15":7,"s:67:2:80:Infinity":16}}} +,"/Users/adam/workspace/vibecode/neko/frontend/src/App.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/App.tsx","statementMap":{"0":{"start":{"line":8,"column":22},"end":{"line":8,"column":null}},"1":{"start":{"line":9,"column":8},"end":{"line":9,"column":null}},"2":{"start":{"line":11,"column":2},"end":{"line":21,"column":null}},"3":{"start":{"line":12,"column":4},"end":{"line":20,"column":null}},"4":{"start":{"line":14,"column":8},"end":{"line":18,"column":null}},"5":{"start":{"line":15,"column":10},"end":{"line":15,"column":null}},"6":{"start":{"line":17,"column":10},"end":{"line":17,"column":null}},"7":{"start":{"line":20,"column":19},"end":{"line":20,"column":33}},"8":{"start":{"line":23,"column":2},"end":{"line":25,"column":null}},"9":{"start":{"line":24,"column":4},"end":{"line":24,"column":null}},"10":{"start":{"line":27,"column":2},"end":{"line":29,"column":null}},"11":{"start":{"line":28,"column":4},"end":{"line":28,"column":null}},"12":{"start":{"line":31,"column":2},"end":{"line":31,"column":null}},"13":{"start":{"line":39,"column":2},"end":{"line":74,"column":null}},"14":{"start":{"line":45,"column":12},"end":{"line":45,"column":null}},"15":{"start":{"line":46,"column":12},"end":{"line":46,"column":null}},"16":{"start":{"line":55,"column":12},"end":{"line":56,"column":null}},"17":{"start":{"line":56,"column":26},"end":{"line":56,"column":58}},"18":{"start":{"line":79,"column":2},"end":{"line":92,"column":null}}},"fnMap":{"0":{"name":"RequireAuth","decl":{"start":{"line":7,"column":9},"end":{"line":7,"column":21}},"loc":{"start":{"line":7,"column":69},"end":{"line":32,"column":null}},"line":7},"1":{"name":"(anonymous_1)","decl":{"start":{"line":11,"column":12},"end":{"line":11,"column":18}},"loc":{"start":{"line":11,"column":18},"end":{"line":21,"column":5}},"line":11},"2":{"name":"(anonymous_2)","decl":{"start":{"line":13,"column":12},"end":{"line":13,"column":13}},"loc":{"start":{"line":13,"column":21},"end":{"line":19,"column":7}},"line":13},"3":{"name":"(anonymous_3)","decl":{"start":{"line":20,"column":13},"end":{"line":20,"column":19}},"loc":{"start":{"line":20,"column":19},"end":{"line":20,"column":33}},"line":20},"4":{"name":"Dashboard","decl":{"start":{"line":38,"column":9},"end":{"line":38,"column":21}},"loc":{"start":{"line":38,"column":21},"end":{"line":76,"column":null}},"line":38},"5":{"name":"(anonymous_5)","decl":{"start":{"line":44,"column":39},"end":{"line":44,"column":40}},"loc":{"start":{"line":44,"column":46},"end":{"line":52,"column":13}},"line":44},"6":{"name":"(anonymous_6)","decl":{"start":{"line":54,"column":27},"end":{"line":54,"column":33}},"loc":{"start":{"line":54,"column":33},"end":{"line":57,"column":13}},"line":54},"7":{"name":"(anonymous_7)","decl":{"start":{"line":56,"column":20},"end":{"line":56,"column":26}},"loc":{"start":{"line":56,"column":26},"end":{"line":56,"column":58}},"line":56},"8":{"name":"App","decl":{"start":{"line":78,"column":9},"end":{"line":78,"column":15}},"loc":{"start":{"line":78,"column":15},"end":{"line":94,"column":null}},"line":78}},"branchMap":{"0":{"loc":{"start":{"line":14,"column":8},"end":{"line":18,"column":null}},"type":"if","locations":[{"start":{"line":14,"column":8},"end":{"line":18,"column":null}},{"start":{"line":16,"column":15},"end":{"line":18,"column":null}}],"line":14},"1":{"loc":{"start":{"line":23,"column":2},"end":{"line":25,"column":null}},"type":"if","locations":[{"start":{"line":23,"column":2},"end":{"line":25,"column":null}},{"start":{},"end":{}}],"line":23},"2":{"loc":{"start":{"line":27,"column":2},"end":{"line":29,"column":null}},"type":"if","locations":[{"start":{"line":27,"column":2},"end":{"line":29,"column":null}},{"start":{},"end":{}}],"line":27}},"s":{"0":2,"1":2,"2":2,"3":1,"4":1,"5":1,"6":0,"7":0,"8":2,"9":1,"10":1,"11":0,"12":1,"13":1,"14":0,"15":0,"16":1,"17":1,"18":2},"f":{"0":2,"1":1,"2":1,"3":0,"4":1,"5":0,"6":1,"7":1,"8":2},"b":{"0":[1,0],"1":[1,1],"2":[0,1]},"meta":{"lastBranch":3,"lastFunction":9,"lastStatement":19,"seen":{"f:7:9:7:21":0,"s:8:22:8:Infinity":0,"s:9:8:9:Infinity":1,"s:11:2:21:Infinity":2,"f:11:12:11:18":1,"s:12:4:20:Infinity":3,"f:13:12:13:13":2,"b:14:8:18:Infinity:16:15:18:Infinity":0,"s:14:8:18:Infinity":4,"s:15:10:15:Infinity":5,"s:17:10:17:Infinity":6,"f:20:13:20:19":3,"s:20:19:20:33":7,"b:23:2:25:Infinity:undefined:undefined:undefined:undefined":1,"s:23:2:25:Infinity":8,"s:24:4:24:Infinity":9,"b:27:2:29:Infinity:undefined:undefined:undefined:undefined":2,"s:27:2:29:Infinity":10,"s:28:4:28:Infinity":11,"s:31:2:31:Infinity":12,"f:38:9:38:21":4,"s:39:2:74:Infinity":13,"f:44:39:44:40":5,"s:45:12:45:Infinity":14,"s:46:12:46:Infinity":15,"f:54:27:54:33":6,"s:55:12:56:Infinity":16,"f:56:20:56:26":7,"s:56:26:56:58":17,"f:78:9:78:15":8,"s:79:2:92:Infinity":18}}} ,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} ,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItem.tsx","statementMap":{"0":{"start":{"line":10,"column":24},"end":{"line":10,"column":null}},"1":{"start":{"line":11,"column":30},"end":{"line":11,"column":null}},"2":{"start":{"line":13,"column":23},"end":{"line":15,"column":null}},"3":{"start":{"line":14,"column":8},"end":{"line":14,"column":null}},"4":{"start":{"line":17,"column":23},"end":{"line":19,"column":null}},"5":{"start":{"line":18,"column":8},"end":{"line":18,"column":null}},"6":{"start":{"line":21,"column":23},"end":{"line":55,"column":null}},"7":{"start":{"line":22,"column":8},"end":{"line":22,"column":null}},"8":{"start":{"line":24,"column":29},"end":{"line":24,"column":null}},"9":{"start":{"line":25,"column":8},"end":{"line":25,"column":null}},"10":{"start":{"line":27,"column":8},"end":{"line":54,"column":null}},"11":{"start":{"line":39,"column":16},"end":{"line":41,"column":null}},"12":{"start":{"line":40,"column":20},"end":{"line":40,"column":null}},"13":{"start":{"line":42,"column":16},"end":{"line":42,"column":null}},"14":{"start":{"line":47,"column":16},"end":{"line":47,"column":null}},"15":{"start":{"line":50,"column":16},"end":{"line":50,"column":null}},"16":{"start":{"line":52,"column":16},"end":{"line":52,"column":null}},"17":{"start":{"line":53,"column":16},"end":{"line":53,"column":null}},"18":{"start":{"line":57,"column":4},"end":{"line":87,"column":null}}},"fnMap":{"0":{"name":"FeedItem","decl":{"start":{"line":9,"column":24},"end":{"line":9,"column":33}},"loc":{"start":{"line":9,"column":71},"end":{"line":89,"column":null}},"line":9},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":23},"end":{"line":13,"column":29}},"loc":{"start":{"line":13,"column":29},"end":{"line":15,"column":null}},"line":13},"2":{"name":"(anonymous_2)","decl":{"start":{"line":17,"column":23},"end":{"line":17,"column":29}},"loc":{"start":{"line":17,"column":29},"end":{"line":19,"column":null}},"line":17},"3":{"name":"(anonymous_3)","decl":{"start":{"line":21,"column":23},"end":{"line":21,"column":24}},"loc":{"start":{"line":21,"column":42},"end":{"line":55,"column":null}},"line":21},"4":{"name":"(anonymous_4)","decl":{"start":{"line":38,"column":18},"end":{"line":38,"column":19}},"loc":{"start":{"line":38,"column":27},"end":{"line":43,"column":13}},"line":38},"5":{"name":"(anonymous_5)","decl":{"start":{"line":44,"column":18},"end":{"line":44,"column":24}},"loc":{"start":{"line":44,"column":24},"end":{"line":48,"column":13}},"line":44},"6":{"name":"(anonymous_6)","decl":{"start":{"line":49,"column":19},"end":{"line":49,"column":20}},"loc":{"start":{"line":49,"column":28},"end":{"line":54,"column":13}},"line":49}},"branchMap":{"0":{"loc":{"start":{"line":39,"column":16},"end":{"line":41,"column":null}},"type":"if","locations":[{"start":{"line":39,"column":16},"end":{"line":41,"column":null}},{"start":{},"end":{}}],"line":39},"1":{"loc":{"start":{"line":58,"column":36},"end":{"line":58,"column":65}},"type":"cond-expr","locations":[{"start":{"line":58,"column":48},"end":{"line":58,"column":57}},{"start":{"line":58,"column":57},"end":{"line":58,"column":65}}],"line":58},"2":{"loc":{"start":{"line":58,"column":69},"end":{"line":58,"column":93}},"type":"cond-expr","locations":[{"start":{"line":58,"column":79},"end":{"line":58,"column":91}},{"start":{"line":58,"column":91},"end":{"line":58,"column":93}}],"line":58},"3":{"loc":{"start":{"line":61,"column":21},"end":{"line":61,"column":null}},"type":"binary-expr","locations":[{"start":{"line":61,"column":21},"end":{"line":61,"column":35}},{"start":{"line":61,"column":35},"end":{"line":61,"column":null}}],"line":61},"4":{"loc":{"start":{"line":66,"column":49},"end":{"line":66,"column":84}},"type":"cond-expr","locations":[{"start":{"line":66,"column":61},"end":{"line":66,"column":73}},{"start":{"line":66,"column":73},"end":{"line":66,"column":84}}],"line":66},"5":{"loc":{"start":{"line":67,"column":31},"end":{"line":67,"column":null}},"type":"cond-expr","locations":[{"start":{"line":67,"column":43},"end":{"line":67,"column":62}},{"start":{"line":67,"column":62},"end":{"line":67,"column":null}}],"line":67},"6":{"loc":{"start":{"line":69,"column":25},"end":{"line":69,"column":null}},"type":"cond-expr","locations":[{"start":{"line":69,"column":37},"end":{"line":69,"column":44}},{"start":{"line":69,"column":44},"end":{"line":69,"column":null}}],"line":69},"7":{"loc":{"start":{"line":73,"column":49},"end":{"line":73,"column":93}},"type":"cond-expr","locations":[{"start":{"line":73,"column":64},"end":{"line":73,"column":79}},{"start":{"line":73,"column":79},"end":{"line":73,"column":93}}],"line":73},"8":{"loc":{"start":{"line":74,"column":31},"end":{"line":74,"column":null}},"type":"cond-expr","locations":[{"start":{"line":74,"column":46},"end":{"line":74,"column":57}},{"start":{"line":74,"column":57},"end":{"line":74,"column":null}}],"line":74},"9":{"loc":{"start":{"line":76,"column":25},"end":{"line":76,"column":null}},"type":"cond-expr","locations":[{"start":{"line":76,"column":40},"end":{"line":76,"column":46}},{"start":{"line":76,"column":46},"end":{"line":76,"column":null}}],"line":76},"10":{"loc":{"start":{"line":82,"column":17},"end":{"line":82,"column":null}},"type":"binary-expr","locations":[{"start":{"line":82,"column":17},"end":{"line":82,"column":36}},{"start":{"line":82,"column":36},"end":{"line":82,"column":null}}],"line":82},"11":{"loc":{"start":{"line":84,"column":13},"end":{"line":85,"column":null}},"type":"binary-expr","locations":[{"start":{"line":84,"column":13},"end":{"line":84,"column":null}},{"start":{"line":85,"column":16},"end":{"line":85,"column":null}}],"line":84}},"s":{"0":12,"1":12,"2":12,"3":2,"4":12,"5":1,"6":12,"7":3,"8":3,"9":3,"10":3,"11":2,"12":0,"13":2,"14":2,"15":1,"16":1,"17":1,"18":12},"f":{"0":12,"1":2,"2":1,"3":3,"4":2,"5":2,"6":1},"b":{"0":[0,2],"1":[4,8],"2":[3,9],"3":[12,0],"4":[4,8],"5":[4,8],"6":[4,8],"7":[2,10],"8":[2,10],"9":[2,10],"10":[12,10],"11":[12,10]},"meta":{"lastBranch":12,"lastFunction":7,"lastStatement":19,"seen":{"f:9:24:9:33":0,"s:10:24:10:Infinity":0,"s:11:30:11:Infinity":1,"s:13:23:15:Infinity":2,"f:13:23:13:29":1,"s:14:8:14:Infinity":3,"s:17:23:19:Infinity":4,"f:17:23:17:29":2,"s:18:8:18:Infinity":5,"s:21:23:55:Infinity":6,"f:21:23:21:24":3,"s:22:8:22:Infinity":7,"s:24:29:24:Infinity":8,"s:25:8:25:Infinity":9,"s:27:8:54:Infinity":10,"f:38:18:38:19":4,"b:39:16:41:Infinity:undefined:undefined:undefined:undefined":0,"s:39:16:41:Infinity":11,"s:40:20:40:Infinity":12,"s:42:16:42:Infinity":13,"f:44:18:44:24":5,"s:47:16:47:Infinity":14,"f:49:19:49:20":6,"s:50:16:50:Infinity":15,"s:52:16:52:Infinity":16,"s:53:16:53:Infinity":17,"s:57:4:87:Infinity":18,"b:58:48:58:57:58:57:58:65":1,"b:58:79:58:91:58:91:58:93":2,"b:61:21:61:35:61:35:61:Infinity":3,"b:66:61:66:73:66:73:66:84":4,"b:67:43:67:62:67:62:67:Infinity":5,"b:69:37:69:44:69:44:69:Infinity":6,"b:73:64:73:79:73:79:73:93":7,"b:74:46:74:57:74:57:74:Infinity":8,"b:76:40:76:46:76:46:76:Infinity":9,"b:82:17:82:36:82:36:82:Infinity":10,"b:84:13:84:Infinity:85:16:85:Infinity":11}}} ,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} @@ -8,4 +8,6 @@ ,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.tsx","statementMap":{"0":{"start":{"line":7,"column":26},"end":{"line":7,"column":null}},"1":{"start":{"line":8,"column":30},"end":{"line":8,"column":null}},"2":{"start":{"line":9,"column":26},"end":{"line":9,"column":null}},"3":{"start":{"line":11,"column":4},"end":{"line":27,"column":null}},"4":{"start":{"line":12,"column":8},"end":{"line":26,"column":null}},"5":{"start":{"line":14,"column":16},"end":{"line":16,"column":null}},"6":{"start":{"line":15,"column":20},"end":{"line":15,"column":null}},"7":{"start":{"line":17,"column":16},"end":{"line":17,"column":null}},"8":{"start":{"line":20,"column":16},"end":{"line":20,"column":null}},"9":{"start":{"line":21,"column":16},"end":{"line":21,"column":null}},"10":{"start":{"line":24,"column":16},"end":{"line":24,"column":null}},"11":{"start":{"line":25,"column":16},"end":{"line":25,"column":null}},"12":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"13":{"start":{"line":29,"column":17},"end":{"line":29,"column":null}},"14":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"15":{"start":{"line":30,"column":15},"end":{"line":30,"column":null}},"16":{"start":{"line":32,"column":4},"end":{"line":49,"column":null}},"17":{"start":{"line":40,"column":24},"end":{"line":45,"column":null}}},"fnMap":{"0":{"name":"FeedList","decl":{"start":{"line":6,"column":24},"end":{"line":6,"column":35}},"loc":{"start":{"line":6,"column":35},"end":{"line":51,"column":null}},"line":6},"1":{"name":"(anonymous_1)","decl":{"start":{"line":11,"column":14},"end":{"line":11,"column":20}},"loc":{"start":{"line":11,"column":20},"end":{"line":27,"column":7}},"line":11},"2":{"name":"(anonymous_2)","decl":{"start":{"line":13,"column":18},"end":{"line":13,"column":19}},"loc":{"start":{"line":13,"column":27},"end":{"line":18,"column":13}},"line":13},"3":{"name":"(anonymous_3)","decl":{"start":{"line":19,"column":18},"end":{"line":19,"column":19}},"loc":{"start":{"line":19,"column":28},"end":{"line":22,"column":13}},"line":19},"4":{"name":"(anonymous_4)","decl":{"start":{"line":23,"column":19},"end":{"line":23,"column":20}},"loc":{"start":{"line":23,"column":28},"end":{"line":26,"column":13}},"line":23},"5":{"name":"(anonymous_5)","decl":{"start":{"line":39,"column":31},"end":{"line":39,"column":32}},"loc":{"start":{"line":40,"column":24},"end":{"line":45,"column":null}},"line":40}},"branchMap":{"0":{"loc":{"start":{"line":14,"column":16},"end":{"line":16,"column":null}},"type":"if","locations":[{"start":{"line":14,"column":16},"end":{"line":16,"column":null}},{"start":{},"end":{}}],"line":14},"1":{"loc":{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},"type":"if","locations":[{"start":{"line":29,"column":4},"end":{"line":29,"column":null}},{"start":{},"end":{}}],"line":29},"2":{"loc":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"type":"if","locations":[{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},{"start":{},"end":{}}],"line":30},"3":{"loc":{"start":{"line":35,"column":13},"end":{"line":47,"column":null}},"type":"cond-expr","locations":[{"start":{"line":36,"column":16},"end":{"line":36,"column":null}},{"start":{"line":38,"column":16},"end":{"line":47,"column":null}}],"line":35},"4":{"loc":{"start":{"line":42,"column":33},"end":{"line":42,"column":null}},"type":"binary-expr","locations":[{"start":{"line":42,"column":33},"end":{"line":42,"column":47}},{"start":{"line":42,"column":47},"end":{"line":42,"column":null}}],"line":42},"5":{"loc":{"start":{"line":44,"column":29},"end":{"line":44,"column":null}},"type":"binary-expr","locations":[{"start":{"line":44,"column":29},"end":{"line":44,"column":46}},{"start":{"line":44,"column":46},"end":{"line":44,"column":null}}],"line":44}},"s":{"0":9,"1":9,"2":9,"3":9,"4":5,"5":3,"6":0,"7":3,"8":3,"9":3,"10":1,"11":1,"12":9,"13":5,"14":4,"15":4,"16":3,"17":2},"f":{"0":9,"1":5,"2":3,"3":3,"4":1,"5":2},"b":{"0":[0,3],"1":[5,4],"2":[1,3],"3":[2,1],"4":[2,0],"5":[2,2]},"meta":{"lastBranch":6,"lastFunction":6,"lastStatement":18,"seen":{"f:6:24:6:35":0,"s:7:26:7:Infinity":0,"s:8:30:8:Infinity":1,"s:9:26:9:Infinity":2,"s:11:4:27:Infinity":3,"f:11:14:11:20":1,"s:12:8:26:Infinity":4,"f:13:18:13:19":2,"b:14:16:16:Infinity:undefined:undefined:undefined:undefined":0,"s:14:16:16:Infinity":5,"s:15:20:15:Infinity":6,"s:17:16:17:Infinity":7,"f:19:18:19:19":3,"s:20:16:20:Infinity":8,"s:21:16:21:Infinity":9,"f:23:19:23:20":4,"s:24:16:24:Infinity":10,"s:25:16:25:Infinity":11,"b:29:4:29:Infinity:undefined:undefined:undefined:undefined":1,"s:29:4:29:Infinity":12,"s:29:17:29:Infinity":13,"b:30:4:30:Infinity:undefined:undefined:undefined:undefined":2,"s:30:4:30:Infinity":14,"s:30:15:30:Infinity":15,"s:32:4:49:Infinity":16,"b:36:16:36:Infinity:38:16:47:Infinity":3,"f:39:31:39:32":5,"s:40:24:45:Infinity":17,"b:42:33:42:47:42:47:42:Infinity":4,"b:44:29:44:46:44:46:44:Infinity":5}}} ,"/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} ,"/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/Login.tsx","statementMap":{"0":{"start":{"line":6,"column":32},"end":{"line":6,"column":null}},"1":{"start":{"line":7,"column":26},"end":{"line":7,"column":null}},"2":{"start":{"line":8,"column":10},"end":{"line":8,"column":null}},"3":{"start":{"line":10,"column":25},"end":{"line":33,"column":null}},"4":{"start":{"line":11,"column":8},"end":{"line":11,"column":null}},"5":{"start":{"line":12,"column":8},"end":{"line":12,"column":null}},"6":{"start":{"line":14,"column":8},"end":{"line":32,"column":null}},"7":{"start":{"line":16,"column":27},"end":{"line":16,"column":null}},"8":{"start":{"line":17,"column":12},"end":{"line":17,"column":null}},"9":{"start":{"line":19,"column":24},"end":{"line":22,"column":null}},"10":{"start":{"line":24,"column":12},"end":{"line":29,"column":null}},"11":{"start":{"line":25,"column":16},"end":{"line":25,"column":null}},"12":{"start":{"line":27,"column":29},"end":{"line":27,"column":null}},"13":{"start":{"line":28,"column":16},"end":{"line":28,"column":null}},"14":{"start":{"line":31,"column":12},"end":{"line":31,"column":null}},"15":{"start":{"line":35,"column":4},"end":{"line":52,"column":null}},"16":{"start":{"line":45,"column":41},"end":{"line":45,"column":null}}},"fnMap":{"0":{"name":"Login","decl":{"start":{"line":5,"column":24},"end":{"line":5,"column":32}},"loc":{"start":{"line":5,"column":32},"end":{"line":54,"column":null}},"line":5},"1":{"name":"(anonymous_1)","decl":{"start":{"line":10,"column":25},"end":{"line":10,"column":32}},"loc":{"start":{"line":10,"column":49},"end":{"line":33,"column":null}},"line":10},"2":{"name":"(anonymous_2)","decl":{"start":{"line":45,"column":34},"end":{"line":45,"column":35}},"loc":{"start":{"line":45,"column":41},"end":{"line":45,"column":null}},"line":45}},"branchMap":{"0":{"loc":{"start":{"line":24,"column":12},"end":{"line":29,"column":null}},"type":"if","locations":[{"start":{"line":24,"column":12},"end":{"line":29,"column":null}},{"start":{"line":26,"column":19},"end":{"line":29,"column":null}}],"line":24},"1":{"loc":{"start":{"line":28,"column":25},"end":{"line":28,"column":55}},"type":"binary-expr","locations":[{"start":{"line":28,"column":25},"end":{"line":28,"column":41}},{"start":{"line":28,"column":41},"end":{"line":28,"column":55}}],"line":28},"2":{"loc":{"start":{"line":49,"column":17},"end":{"line":49,"column":null}},"type":"binary-expr","locations":[{"start":{"line":49,"column":17},"end":{"line":49,"column":26}},{"start":{"line":49,"column":26},"end":{"line":49,"column":null}}],"line":49}},"s":{"0":14,"1":14,"2":14,"3":14,"4":3,"5":3,"6":3,"7":3,"8":3,"9":3,"10":2,"11":1,"12":1,"13":1,"14":1,"15":14,"16":3},"f":{"0":14,"1":3,"2":3},"b":{"0":[1,1],"1":[1,0],"2":[14,2]},"meta":{"lastBranch":3,"lastFunction":3,"lastStatement":17,"seen":{"f:5:24:5:32":0,"s:6:32:6:Infinity":0,"s:7:26:7:Infinity":1,"s:8:10:8:Infinity":2,"s:10:25:33:Infinity":3,"f:10:25:10:32":1,"s:11:8:11:Infinity":4,"s:12:8:12:Infinity":5,"s:14:8:32:Infinity":6,"s:16:27:16:Infinity":7,"s:17:12:17:Infinity":8,"s:19:24:22:Infinity":9,"b:24:12:29:Infinity:26:19:29:Infinity":0,"s:24:12:29:Infinity":10,"s:25:16:25:Infinity":11,"s:27:29:27:Infinity":12,"s:28:16:28:Infinity":13,"b:28:25:28:41:28:41:28:55":1,"s:31:12:31:Infinity":14,"s:35:4:52:Infinity":15,"f:45:34:45:35":2,"s:45:41:45:Infinity":16,"b:49:17:49:26:49:26:49:Infinity":2}}} +,"/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} +,"/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/Settings.tsx","statementMap":{"0":{"start":{"line":6,"column":26},"end":{"line":6,"column":null}},"1":{"start":{"line":7,"column":36},"end":{"line":7,"column":null}},"2":{"start":{"line":8,"column":30},"end":{"line":8,"column":null}},"3":{"start":{"line":9,"column":26},"end":{"line":9,"column":null}},"4":{"start":{"line":11,"column":4},"end":{"line":13,"column":null}},"5":{"start":{"line":12,"column":8},"end":{"line":12,"column":null}},"6":{"start":{"line":15,"column":23},"end":{"line":30,"column":null}},"7":{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},"8":{"start":{"line":17,"column":8},"end":{"line":29,"column":null}},"9":{"start":{"line":19,"column":16},"end":{"line":19,"column":null}},"10":{"start":{"line":19,"column":29},"end":{"line":19,"column":null}},"11":{"start":{"line":20,"column":16},"end":{"line":20,"column":null}},"12":{"start":{"line":23,"column":16},"end":{"line":23,"column":null}},"13":{"start":{"line":24,"column":16},"end":{"line":24,"column":null}},"14":{"start":{"line":27,"column":16},"end":{"line":27,"column":null}},"15":{"start":{"line":28,"column":16},"end":{"line":28,"column":null}},"16":{"start":{"line":32,"column":26},"end":{"line":54,"column":null}},"17":{"start":{"line":33,"column":8},"end":{"line":33,"column":null}},"18":{"start":{"line":34,"column":8},"end":{"line":34,"column":null}},"19":{"start":{"line":34,"column":25},"end":{"line":34,"column":null}},"20":{"start":{"line":36,"column":8},"end":{"line":36,"column":null}},"21":{"start":{"line":37,"column":8},"end":{"line":53,"column":null}},"22":{"start":{"line":43,"column":16},"end":{"line":43,"column":null}},"23":{"start":{"line":43,"column":29},"end":{"line":43,"column":null}},"24":{"start":{"line":44,"column":16},"end":{"line":44,"column":null}},"25":{"start":{"line":47,"column":16},"end":{"line":47,"column":null}},"26":{"start":{"line":48,"column":16},"end":{"line":48,"column":null}},"27":{"start":{"line":51,"column":16},"end":{"line":51,"column":null}},"28":{"start":{"line":52,"column":16},"end":{"line":52,"column":null}},"29":{"start":{"line":56,"column":29},"end":{"line":72,"column":null}},"30":{"start":{"line":57,"column":8},"end":{"line":57,"column":null}},"31":{"start":{"line":57,"column":79},"end":{"line":57,"column":null}},"32":{"start":{"line":59,"column":8},"end":{"line":59,"column":null}},"33":{"start":{"line":60,"column":8},"end":{"line":71,"column":null}},"34":{"start":{"line":64,"column":16},"end":{"line":64,"column":null}},"35":{"start":{"line":64,"column":29},"end":{"line":64,"column":null}},"36":{"start":{"line":65,"column":16},"end":{"line":65,"column":null}},"37":{"start":{"line":65,"column":45},"end":{"line":65,"column":57}},"38":{"start":{"line":66,"column":16},"end":{"line":66,"column":null}},"39":{"start":{"line":69,"column":16},"end":{"line":69,"column":null}},"40":{"start":{"line":70,"column":16},"end":{"line":70,"column":null}},"41":{"start":{"line":74,"column":4},"end":{"line":119,"column":null}},"42":{"start":{"line":84,"column":41},"end":{"line":84,"column":null}},"43":{"start":{"line":102,"column":24},"end":{"line":115,"column":null}},"44":{"start":{"line":108,"column":47},"end":{"line":108,"column":null}}},"fnMap":{"0":{"name":"Settings","decl":{"start":{"line":5,"column":24},"end":{"line":5,"column":35}},"loc":{"start":{"line":5,"column":35},"end":{"line":121,"column":null}},"line":5},"1":{"name":"(anonymous_1)","decl":{"start":{"line":11,"column":14},"end":{"line":11,"column":20}},"loc":{"start":{"line":11,"column":20},"end":{"line":13,"column":7}},"line":11},"2":{"name":"(anonymous_2)","decl":{"start":{"line":15,"column":23},"end":{"line":15,"column":29}},"loc":{"start":{"line":15,"column":29},"end":{"line":30,"column":null}},"line":15},"3":{"name":"(anonymous_3)","decl":{"start":{"line":18,"column":18},"end":{"line":18,"column":19}},"loc":{"start":{"line":18,"column":27},"end":{"line":21,"column":13}},"line":18},"4":{"name":"(anonymous_4)","decl":{"start":{"line":22,"column":18},"end":{"line":22,"column":19}},"loc":{"start":{"line":22,"column":28},"end":{"line":25,"column":13}},"line":22},"5":{"name":"(anonymous_5)","decl":{"start":{"line":26,"column":19},"end":{"line":26,"column":20}},"loc":{"start":{"line":26,"column":28},"end":{"line":29,"column":13}},"line":26},"6":{"name":"(anonymous_6)","decl":{"start":{"line":32,"column":26},"end":{"line":32,"column":27}},"loc":{"start":{"line":32,"column":50},"end":{"line":54,"column":null}},"line":32},"7":{"name":"(anonymous_7)","decl":{"start":{"line":42,"column":18},"end":{"line":42,"column":19}},"loc":{"start":{"line":42,"column":27},"end":{"line":45,"column":13}},"line":42},"8":{"name":"(anonymous_8)","decl":{"start":{"line":46,"column":18},"end":{"line":46,"column":24}},"loc":{"start":{"line":46,"column":24},"end":{"line":49,"column":13}},"line":46},"9":{"name":"(anonymous_9)","decl":{"start":{"line":50,"column":19},"end":{"line":50,"column":20}},"loc":{"start":{"line":50,"column":28},"end":{"line":53,"column":13}},"line":50},"10":{"name":"(anonymous_10)","decl":{"start":{"line":56,"column":29},"end":{"line":56,"column":30}},"loc":{"start":{"line":56,"column":45},"end":{"line":72,"column":null}},"line":56},"11":{"name":"(anonymous_11)","decl":{"start":{"line":63,"column":18},"end":{"line":63,"column":19}},"loc":{"start":{"line":63,"column":27},"end":{"line":67,"column":13}},"line":63},"12":{"name":"(anonymous_12)","decl":{"start":{"line":65,"column":38},"end":{"line":65,"column":39}},"loc":{"start":{"line":65,"column":45},"end":{"line":65,"column":57}},"line":65},"13":{"name":"(anonymous_13)","decl":{"start":{"line":68,"column":19},"end":{"line":68,"column":20}},"loc":{"start":{"line":68,"column":28},"end":{"line":71,"column":13}},"line":68},"14":{"name":"(anonymous_14)","decl":{"start":{"line":84,"column":34},"end":{"line":84,"column":35}},"loc":{"start":{"line":84,"column":41},"end":{"line":84,"column":null}},"line":84},"15":{"name":"(anonymous_15)","decl":{"start":{"line":101,"column":31},"end":{"line":101,"column":32}},"loc":{"start":{"line":102,"column":24},"end":{"line":115,"column":null}},"line":102},"16":{"name":"(anonymous_16)","decl":{"start":{"line":108,"column":41},"end":{"line":108,"column":47}},"loc":{"start":{"line":108,"column":47},"end":{"line":108,"column":null}},"line":108}},"branchMap":{"0":{"loc":{"start":{"line":19,"column":16},"end":{"line":19,"column":null}},"type":"if","locations":[{"start":{"line":19,"column":16},"end":{"line":19,"column":null}},{"start":{},"end":{}}],"line":19},"1":{"loc":{"start":{"line":34,"column":8},"end":{"line":34,"column":null}},"type":"if","locations":[{"start":{"line":34,"column":8},"end":{"line":34,"column":null}},{"start":{},"end":{}}],"line":34},"2":{"loc":{"start":{"line":43,"column":16},"end":{"line":43,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":16},"end":{"line":43,"column":null}},{"start":{},"end":{}}],"line":43},"3":{"loc":{"start":{"line":57,"column":8},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":57,"column":8},"end":{"line":57,"column":null}},{"start":{},"end":{}}],"line":57},"4":{"loc":{"start":{"line":64,"column":16},"end":{"line":64,"column":null}},"type":"if","locations":[{"start":{"line":64,"column":16},"end":{"line":64,"column":null}},{"start":{},"end":{}}],"line":64},"5":{"loc":{"start":{"line":94,"column":17},"end":{"line":94,"column":null}},"type":"binary-expr","locations":[{"start":{"line":94,"column":17},"end":{"line":94,"column":26}},{"start":{"line":94,"column":26},"end":{"line":94,"column":null}}],"line":94},"6":{"loc":{"start":{"line":99,"column":17},"end":{"line":99,"column":null}},"type":"binary-expr","locations":[{"start":{"line":99,"column":17},"end":{"line":99,"column":28}},{"start":{"line":99,"column":28},"end":{"line":99,"column":null}}],"line":99},"7":{"loc":{"start":{"line":104,"column":62},"end":{"line":104,"column":89}},"type":"binary-expr","locations":[{"start":{"line":104,"column":62},"end":{"line":104,"column":76}},{"start":{"line":104,"column":76},"end":{"line":104,"column":89}}],"line":104}},"s":{"0":14,"1":14,"2":14,"3":14,"4":14,"5":3,"6":14,"7":4,"8":4,"9":4,"10":0,"11":4,"12":4,"13":4,"14":0,"15":0,"16":14,"17":1,"18":1,"19":0,"20":1,"21":1,"22":1,"23":0,"24":1,"25":1,"26":1,"27":0,"28":0,"29":14,"30":1,"31":0,"32":1,"33":1,"34":1,"35":0,"36":1,"37":1,"38":1,"39":0,"40":0,"41":14,"42":1,"43":5,"44":1},"f":{"0":14,"1":3,"2":4,"3":4,"4":4,"5":0,"6":1,"7":1,"8":1,"9":0,"10":1,"11":1,"12":1,"13":0,"14":1,"15":5,"16":1},"b":{"0":[0,4],"1":[0,1],"2":[0,1],"3":[0,1],"4":[0,1],"5":[14,0],"6":[14,5],"7":[5,0]},"meta":{"lastBranch":8,"lastFunction":17,"lastStatement":45,"seen":{"f:5:24:5:35":0,"s:6:26:6:Infinity":0,"s:7:36:7:Infinity":1,"s:8:30:8:Infinity":2,"s:9:26:9:Infinity":3,"s:11:4:13:Infinity":4,"f:11:14:11:20":1,"s:12:8:12:Infinity":5,"s:15:23:30:Infinity":6,"f:15:23:15:29":2,"s:16:8:16:Infinity":7,"s:17:8:29:Infinity":8,"f:18:18:18:19":3,"b:19:16:19:Infinity:undefined:undefined:undefined:undefined":0,"s:19:16:19:Infinity":9,"s:19:29:19:Infinity":10,"s:20:16:20:Infinity":11,"f:22:18:22:19":4,"s:23:16:23:Infinity":12,"s:24:16:24:Infinity":13,"f:26:19:26:20":5,"s:27:16:27:Infinity":14,"s:28:16:28:Infinity":15,"s:32:26:54:Infinity":16,"f:32:26:32:27":6,"s:33:8:33:Infinity":17,"b:34:8:34:Infinity:undefined:undefined:undefined:undefined":1,"s:34:8:34:Infinity":18,"s:34:25:34:Infinity":19,"s:36:8:36:Infinity":20,"s:37:8:53:Infinity":21,"f:42:18:42:19":7,"b:43:16:43:Infinity:undefined:undefined:undefined:undefined":2,"s:43:16:43:Infinity":22,"s:43:29:43:Infinity":23,"s:44:16:44:Infinity":24,"f:46:18:46:24":8,"s:47:16:47:Infinity":25,"s:48:16:48:Infinity":26,"f:50:19:50:20":9,"s:51:16:51:Infinity":27,"s:52:16:52:Infinity":28,"s:56:29:72:Infinity":29,"f:56:29:56:30":10,"b:57:8:57:Infinity:undefined:undefined:undefined:undefined":3,"s:57:8:57:Infinity":30,"s:57:79:57:Infinity":31,"s:59:8:59:Infinity":32,"s:60:8:71:Infinity":33,"f:63:18:63:19":11,"b:64:16:64:Infinity:undefined:undefined:undefined:undefined":4,"s:64:16:64:Infinity":34,"s:64:29:64:Infinity":35,"s:65:16:65:Infinity":36,"f:65:38:65:39":12,"s:65:45:65:57":37,"s:66:16:66:Infinity":38,"f:68:19:68:20":13,"s:69:16:69:Infinity":39,"s:70:16:70:Infinity":40,"s:74:4:119:Infinity":41,"f:84:34:84:35":14,"s:84:41:84:Infinity":42,"b:94:17:94:26:94:26:94:Infinity":5,"b:99:17:99:28:99:28:99:Infinity":6,"f:101:31:101:32":15,"s:102:24:115:Infinity":43,"b:104:62:104:76:104:76:104:89":7,"f:108:41:108:47":16,"s:108:47:108:Infinity":44}}} } diff --git a/frontend/coverage/index.html b/frontend/coverage/index.html index 51ed5a6..279afdf 100644 --- a/frontend/coverage/index.html +++ b/frontend/coverage/index.html @@ -23,30 +23,30 @@
- 91.39% + 85% Statements - 85/93 + 119/140
- 81.03% + 75.67% Branches - 47/58 + 56/74
- 93.33% + 87.5% Functions - 28/30 + 42/48
- 91.01% + 87.69% Lines - 81/89 + 114/130
@@ -79,33 +79,33 @@ - src - -
+ src + +
- 82.35% - 14/17 + 73.68% + 14/19 66.66% 4/6 - 87.5% - 7/8 - 82.35% - 14/17 + 77.77% + 7/9 + 73.68% + 14/19 src/components - -
+ +
- 93.42% - 71/76 - 82.69% - 43/52 - 95.45% - 21/22 - 93.05% - 67/72 + 86.77% + 105/121 + 76.47% + 52/68 + 89.74% + 35/39 + 90.09% + 100/111 @@ -116,7 +116,7 @@ + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/Settings.tsx.html b/frontend/coverage/src/components/Settings.tsx.html new file mode 100644 index 0000000..eaed089 --- /dev/null +++ b/frontend/coverage/src/components/Settings.tsx.html @@ -0,0 +1,448 @@ + + + + + + Code coverage report for src/components/Settings.tsx + + + + + + + + + +
+
+

All files / src/components Settings.tsx

+
+ +
+ 75.55% + Statements + 34/45 +
+ + +
+ 56.25% + Branches + 9/16 +
+ + +
+ 82.35% + Functions + 14/17 +
+ + +
+ 84.61% + Lines + 33/39 +
+ + +
+

+ Press n or j to go to the next uncovered block, b, p or k for the previous block. +

+ +
+
+

+
1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122  +  +  +  +  +14x +14x +14x +14x +  +14x +3x +  +  +14x +4x +4x +  +4x +4x +  +  +4x +4x +  +  +  +  +  +  +  +14x +1x +1x +  +1x +1x +  +  +  +  +  +1x +1x +  +  +1x +1x +  +  +  +  +  +  +  +14x +1x +  +1x +1x +  +  +  +1x +1x +1x +  +  +  +  +  +  +  +14x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import React, { useEffect, useState } from 'react';
+import type { Feed } from '../types';
+import './Settings.css';
+ 
+export default function Settings() {
+    const [feeds, setFeeds] = useState<Feed[]>([]);
+    const [newFeedUrl, setNewFeedUrl] = useState('');
+    const [loading, setLoading] = useState(false);
+    const [error, setError] = useState<string | null>(null);
+ 
+    useEffect(() => {
+        fetchFeeds();
+    }, []);
+ 
+    const fetchFeeds = () => {
+        setLoading(true);
+        fetch('/api/feed/')
+            .then((res) => {
+                Iif (!res.ok) throw new Error('Failed to fetch feeds');
+                return res.json();
+            })
+            .then((data) => {
+                setFeeds(data);
+                setLoading(false);
+            })
+            .catch((err) => {
+                setError(err.message);
+                setLoading(false);
+            });
+    };
+ 
+    const handleAddFeed = (e: React.FormEvent) => {
+        e.preventDefault();
+        Iif (!newFeedUrl) return;
+ 
+        setLoading(true);
+        fetch('/api/feed/', {
+            method: 'POST',
+            headers: { 'Content-Type': 'application/json' },
+            body: JSON.stringify({ url: newFeedUrl }),
+        })
+            .then((res) => {
+                Iif (!res.ok) throw new Error('Failed to add feed');
+                return res.json();
+            })
+            .then(() => {
+                setNewFeedUrl('');
+                fetchFeeds(); // Refresh list (or we could append if server returns full feed object)
+            })
+            .catch((err) => {
+                setError(err.message);
+                setLoading(false);
+            });
+    };
+ 
+    const handleDeleteFeed = (id: number) => {
+        Iif (!globalThis.confirm('Are you sure you want to delete this feed?')) return;
+ 
+        setLoading(true);
+        fetch(`/api/feed/${id}`, {
+            method: 'DELETE',
+        })
+            .then((res) => {
+                Iif (!res.ok) throw new Error('Failed to delete feed');
+                setFeeds(feeds.filter((f) => f._id !== id));
+                setLoading(false);
+            })
+            .catch((err) => {
+                setError(err.message);
+                setLoading(false);
+            });
+    };
+ 
+    return (
+        <div className="settings-page">
+            <h2>Settings</h2>
+ 
+            <div className="add-feed-section">
+                <h3>Add New Feed</h3>
+                <form onSubmit={handleAddFeed} className="add-feed-form">
+                    <input
+                        type="url"
+                        value={newFeedUrl}
+                        onChange={(e) => setNewFeedUrl(e.target.value)}
+                        placeholder="https://example.com/feed.xml"
+                        required
+                        className="feed-input"
+                        disabled={loading}
+                    />
+                    <button type="submit" disabled={loading}>
+                        Add Feed
+                    </button>
+                </form>
+                {error && <p className="error-message">{error}</p>}
+            </div>
+ 
+            <div className="feed-list-section">
+                <h3>Manage Feeds</h3>
+                {loading && <p>Loading...</p>}
+                <ul className="settings-feed-list">
+                    {feeds.map((feed) => (
+                        <li key={feed._id} className="settings-feed-item">
+                            <div className="feed-info">
+                                <span className="feed-title">{feed.title || '(No Title)'}</span>
+                                <span className="feed-url">{feed.url}</span>
+                            </div>
+                            <button
+                                onClick={() => handleDeleteFeed(feed._id)}
+                                className="delete-btn"
+                                disabled={loading}
+                                title="Delete Feed"
+                            >
+                                Delete
+                            </button>
+                        </li>
+                    ))}
+                </ul>
+            </div>
+        </div>
+    );
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/index.html b/frontend/coverage/src/components/index.html index 6af23d0..ec5db40 100644 --- a/frontend/coverage/src/components/index.html +++ b/frontend/coverage/src/components/index.html @@ -23,30 +23,30 @@
- 93.42% + 86.77% Statements - 71/76 + 105/121
- 82.69% + 76.47% Branches - 43/52 + 52/68
- 95.45% + 89.74% Functions - 21/22 + 35/39
- 93.05% + 90.09% Lines - 67/72 + 100/111
@@ -198,6 +198,36 @@ 17/17 + + Settings.css + +
+ + 0% + 0/0 + 0% + 0/0 + 0% + 0/0 + 0% + 0/0 + + + + Settings.tsx + +
+ + 75.55% + 34/45 + 56.25% + 9/16 + 82.35% + 14/17 + 84.61% + 33/39 + +
@@ -206,7 +236,7 @@