From bd2508211760edbc1bad1d515587d08fd2ec99c9 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Fri, 13 Feb 2026 06:58:30 -0800 Subject: Implement Item Interactions (read/star) with tests --- frontend/coverage/clover.xml | 63 ++-- frontend/coverage/coverage-final.json | 4 +- frontend/coverage/index.html | 38 +-- frontend/coverage/src/App.css.html | 2 +- frontend/coverage/src/App.tsx.html | 2 +- frontend/coverage/src/components/FeedItem.css.html | 325 +++++++++++++++++++ frontend/coverage/src/components/FeedItem.tsx.html | 352 +++++++++++++++++++++ .../coverage/src/components/FeedItems.css.html | 142 +-------- .../coverage/src/components/FeedItems.tsx.html | 44 +-- 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/index.html | 52 ++- frontend/coverage/src/index.html | 2 +- frontend/src/components/FeedItem.css | 81 +++++ frontend/src/components/FeedItem.test.tsx | 91 ++++++ frontend/src/components/FeedItem.tsx | 89 ++++++ frontend/src/components/FeedItems.css | 46 --- frontend/src/components/FeedItems.tsx | 14 +- 20 files changed, 1063 insertions(+), 292 deletions(-) create mode 100644 frontend/coverage/src/components/FeedItem.css.html create mode 100644 frontend/coverage/src/components/FeedItem.tsx.html create mode 100644 frontend/src/components/FeedItem.css create mode 100644 frontend/src/components/FeedItem.test.tsx create mode 100644 frontend/src/components/FeedItem.tsx (limited to 'frontend') diff --git a/frontend/coverage/clover.xml b/frontend/coverage/clover.xml index 8251808..415b336 100644 --- a/frontend/coverage/clover.xml +++ b/frontend/coverage/clover.xml @@ -1,7 +1,7 @@ - - - + + + @@ -27,32 +27,57 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + + - - - - - - + + + + + + - + - - - - + + + + + diff --git a/frontend/coverage/coverage-final.json b/frontend/coverage/coverage-final.json index 8fc3ade..7ec3f92 100644 --- a/frontend/coverage/coverage-final.json +++ b/frontend/coverage/coverage-final.json @@ -1,7 +1,9 @@ {"/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":57,"column":null}},"14":{"start":{"line":62,"column":2},"end":{"line":75,"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":59,"column":null}},"line":37},"5":{"name":"App","decl":{"start":{"line":61,"column":9},"end":{"line":61,"column":15}},"loc":{"start":{"line":61,"column":15},"end":{"line":77,"column":null}},"line":61}},"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":2},"f":{"0":2,"1":1,"2":1,"3":0,"4":1,"5":2},"b":{"0":[1,0],"1":[1,1],"2":[0,1]},"meta":{"lastBranch":3,"lastFunction":6,"lastStatement":15,"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:57:Infinity":13,"f:61:9:61:15":5,"s:62:2:75:Infinity":14}}} +,"/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":{}}} -,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.tsx","statementMap":{"0":{"start":{"line":7,"column":19},"end":{"line":7,"column":null}},"1":{"start":{"line":8,"column":26},"end":{"line":8,"column":null}},"2":{"start":{"line":9,"column":30},"end":{"line":9,"column":null}},"3":{"start":{"line":10,"column":26},"end":{"line":10,"column":null}},"4":{"start":{"line":12,"column":4},"end":{"line":35,"column":null}},"5":{"start":{"line":13,"column":8},"end":{"line":13,"column":null}},"6":{"start":{"line":14,"column":8},"end":{"line":14,"column":null}},"7":{"start":{"line":16,"column":20},"end":{"line":18,"column":null}},"8":{"start":{"line":20,"column":8},"end":{"line":34,"column":null}},"9":{"start":{"line":22,"column":16},"end":{"line":24,"column":null}},"10":{"start":{"line":23,"column":20},"end":{"line":23,"column":null}},"11":{"start":{"line":25,"column":16},"end":{"line":25,"column":null}},"12":{"start":{"line":28,"column":16},"end":{"line":28,"column":null}},"13":{"start":{"line":29,"column":16},"end":{"line":29,"column":null}},"14":{"start":{"line":32,"column":16},"end":{"line":32,"column":null}},"15":{"start":{"line":33,"column":16},"end":{"line":33,"column":null}},"16":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"17":{"start":{"line":37,"column":17},"end":{"line":37,"column":null}},"18":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"19":{"start":{"line":38,"column":15},"end":{"line":38,"column":null}},"20":{"start":{"line":40,"column":4},"end":{"line":64,"column":null}},"21":{"start":{"line":49,"column":24},"end":{"line":60,"column":null}}},"fnMap":{"0":{"name":"FeedItems","decl":{"start":{"line":6,"column":24},"end":{"line":6,"column":36}},"loc":{"start":{"line":6,"column":36},"end":{"line":66,"column":null}},"line":6},"1":{"name":"(anonymous_1)","decl":{"start":{"line":12,"column":14},"end":{"line":12,"column":20}},"loc":{"start":{"line":12,"column":20},"end":{"line":35,"column":7}},"line":12},"2":{"name":"(anonymous_2)","decl":{"start":{"line":21,"column":18},"end":{"line":21,"column":19}},"loc":{"start":{"line":21,"column":27},"end":{"line":26,"column":13}},"line":21},"3":{"name":"(anonymous_3)","decl":{"start":{"line":27,"column":18},"end":{"line":27,"column":19}},"loc":{"start":{"line":27,"column":28},"end":{"line":30,"column":13}},"line":27},"4":{"name":"(anonymous_4)","decl":{"start":{"line":31,"column":19},"end":{"line":31,"column":20}},"loc":{"start":{"line":31,"column":28},"end":{"line":34,"column":13}},"line":31},"5":{"name":"(anonymous_5)","decl":{"start":{"line":48,"column":31},"end":{"line":48,"column":32}},"loc":{"start":{"line":49,"column":24},"end":{"line":60,"column":null}},"line":49}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":20},"end":{"line":18,"column":null}},"type":"cond-expr","locations":[{"start":{"line":17,"column":14},"end":{"line":17,"column":null}},{"start":{"line":18,"column":14},"end":{"line":18,"column":null}}],"line":16},"1":{"loc":{"start":{"line":22,"column":16},"end":{"line":24,"column":null}},"type":"if","locations":[{"start":{"line":22,"column":16},"end":{"line":24,"column":null}},{"start":{},"end":{}}],"line":22},"2":{"loc":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"type":"if","locations":[{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},{"start":{},"end":{}}],"line":37},"3":{"loc":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"type":"if","locations":[{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},{"start":{},"end":{}}],"line":38},"4":{"loc":{"start":{"line":44,"column":13},"end":{"line":62,"column":null}},"type":"cond-expr","locations":[{"start":{"line":45,"column":16},"end":{"line":45,"column":null}},{"start":{"line":47,"column":16},"end":{"line":62,"column":null}}],"line":44},"5":{"loc":{"start":{"line":49,"column":62},"end":{"line":49,"column":91}},"type":"cond-expr","locations":[{"start":{"line":49,"column":74},"end":{"line":49,"column":83}},{"start":{"line":49,"column":83},"end":{"line":49,"column":91}}],"line":49},"6":{"loc":{"start":{"line":51,"column":33},"end":{"line":51,"column":null}},"type":"binary-expr","locations":[{"start":{"line":51,"column":33},"end":{"line":51,"column":47}},{"start":{"line":51,"column":47},"end":{"line":51,"column":null}}],"line":51},"7":{"loc":{"start":{"line":55,"column":33},"end":{"line":55,"column":null}},"type":"binary-expr","locations":[{"start":{"line":55,"column":33},"end":{"line":55,"column":52}},{"start":{"line":55,"column":52},"end":{"line":55,"column":null}}],"line":55},"8":{"loc":{"start":{"line":57,"column":29},"end":{"line":58,"column":null}},"type":"binary-expr","locations":[{"start":{"line":57,"column":29},"end":{"line":57,"column":null}},{"start":{"line":58,"column":32},"end":{"line":58,"column":null}}],"line":57}},"s":{"0":3,"1":3,"2":3,"3":3,"4":3,"5":2,"6":2,"7":2,"8":2,"9":1,"10":0,"11":1,"12":1,"13":1,"14":0,"15":0,"16":3,"17":2,"18":1,"19":1,"20":1,"21":2},"f":{"0":3,"1":2,"2":1,"3":1,"4":0,"5":2},"b":{"0":[2,0],"1":[0,1],"2":[2,1],"3":[0,1],"4":[0,1],"5":[1,1],"6":[2,0],"7":[2,0],"8":[2,0]},"meta":{"lastBranch":9,"lastFunction":6,"lastStatement":22,"seen":{"f:6:24:6:36":0,"s:7:19:7:Infinity":0,"s:8:26:8:Infinity":1,"s:9:30:9:Infinity":2,"s:10:26:10:Infinity":3,"s:12:4:35:Infinity":4,"f:12:14:12:20":1,"s:13:8:13:Infinity":5,"s:14:8:14:Infinity":6,"s:16:20:18:Infinity":7,"b:17:14:17:Infinity:18:14:18:Infinity":0,"s:20:8:34:Infinity":8,"f:21:18:21:19":2,"b:22:16:24:Infinity:undefined:undefined:undefined:undefined":1,"s:22:16:24:Infinity":9,"s:23:20:23:Infinity":10,"s:25:16:25:Infinity":11,"f:27:18:27:19":3,"s:28:16:28:Infinity":12,"s:29:16:29:Infinity":13,"f:31:19:31:20":4,"s:32:16:32:Infinity":14,"s:33:16:33:Infinity":15,"b:37:4:37:Infinity:undefined:undefined:undefined:undefined":2,"s:37:4:37:Infinity":16,"s:37:17:37:Infinity":17,"b:38:4:38:Infinity:undefined:undefined:undefined:undefined":3,"s:38:4:38:Infinity":18,"s:38:15:38:Infinity":19,"s:40:4:64:Infinity":20,"b:45:16:45:Infinity:47:16:62:Infinity":4,"f:48:31:48:32":5,"s:49:24:60:Infinity":21,"b:49:74:49:83:49:83:49:91":5,"b:51:33:51:47:51:47:51:Infinity":6,"b:55:33:55:52:55:52:55:Infinity":7,"b:57:29:57:Infinity:58:32:58:Infinity":8}}} +,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.tsx": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedItems.tsx","statementMap":{"0":{"start":{"line":8,"column":19},"end":{"line":8,"column":null}},"1":{"start":{"line":9,"column":26},"end":{"line":9,"column":null}},"2":{"start":{"line":10,"column":30},"end":{"line":10,"column":null}},"3":{"start":{"line":11,"column":26},"end":{"line":11,"column":null}},"4":{"start":{"line":13,"column":4},"end":{"line":36,"column":null}},"5":{"start":{"line":14,"column":8},"end":{"line":14,"column":null}},"6":{"start":{"line":15,"column":8},"end":{"line":15,"column":null}},"7":{"start":{"line":17,"column":20},"end":{"line":19,"column":null}},"8":{"start":{"line":21,"column":8},"end":{"line":35,"column":null}},"9":{"start":{"line":23,"column":16},"end":{"line":25,"column":null}},"10":{"start":{"line":24,"column":20},"end":{"line":24,"column":null}},"11":{"start":{"line":26,"column":16},"end":{"line":26,"column":null}},"12":{"start":{"line":29,"column":16},"end":{"line":29,"column":null}},"13":{"start":{"line":30,"column":16},"end":{"line":30,"column":null}},"14":{"start":{"line":33,"column":16},"end":{"line":33,"column":null}},"15":{"start":{"line":34,"column":16},"end":{"line":34,"column":null}},"16":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"17":{"start":{"line":38,"column":17},"end":{"line":38,"column":null}},"18":{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},"19":{"start":{"line":39,"column":15},"end":{"line":39,"column":null}},"20":{"start":{"line":41,"column":4},"end":{"line":54,"column":null}},"21":{"start":{"line":50,"column":24},"end":{"line":50,"column":null}}},"fnMap":{"0":{"name":"FeedItems","decl":{"start":{"line":7,"column":24},"end":{"line":7,"column":36}},"loc":{"start":{"line":7,"column":36},"end":{"line":56,"column":null}},"line":7},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":14},"end":{"line":13,"column":20}},"loc":{"start":{"line":13,"column":20},"end":{"line":36,"column":7}},"line":13},"2":{"name":"(anonymous_2)","decl":{"start":{"line":22,"column":18},"end":{"line":22,"column":19}},"loc":{"start":{"line":22,"column":27},"end":{"line":27,"column":13}},"line":22},"3":{"name":"(anonymous_3)","decl":{"start":{"line":28,"column":18},"end":{"line":28,"column":19}},"loc":{"start":{"line":28,"column":28},"end":{"line":31,"column":13}},"line":28},"4":{"name":"(anonymous_4)","decl":{"start":{"line":32,"column":19},"end":{"line":32,"column":20}},"loc":{"start":{"line":32,"column":28},"end":{"line":35,"column":13}},"line":32},"5":{"name":"(anonymous_5)","decl":{"start":{"line":49,"column":31},"end":{"line":49,"column":32}},"loc":{"start":{"line":50,"column":24},"end":{"line":50,"column":null}},"line":50}},"branchMap":{"0":{"loc":{"start":{"line":17,"column":20},"end":{"line":19,"column":null}},"type":"cond-expr","locations":[{"start":{"line":18,"column":14},"end":{"line":18,"column":null}},{"start":{"line":19,"column":14},"end":{"line":19,"column":null}}],"line":17},"1":{"loc":{"start":{"line":23,"column":16},"end":{"line":25,"column":null}},"type":"if","locations":[{"start":{"line":23,"column":16},"end":{"line":25,"column":null}},{"start":{},"end":{}}],"line":23},"2":{"loc":{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},"type":"if","locations":[{"start":{"line":38,"column":4},"end":{"line":38,"column":null}},{"start":{},"end":{}}],"line":38},"3":{"loc":{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},"type":"if","locations":[{"start":{"line":39,"column":4},"end":{"line":39,"column":null}},{"start":{},"end":{}}],"line":39},"4":{"loc":{"start":{"line":45,"column":13},"end":{"line":52,"column":null}},"type":"cond-expr","locations":[{"start":{"line":46,"column":16},"end":{"line":46,"column":null}},{"start":{"line":48,"column":16},"end":{"line":52,"column":null}}],"line":45}},"s":{"0":3,"1":3,"2":3,"3":3,"4":3,"5":2,"6":2,"7":2,"8":2,"9":1,"10":0,"11":1,"12":1,"13":1,"14":0,"15":0,"16":3,"17":2,"18":1,"19":1,"20":1,"21":2},"f":{"0":3,"1":2,"2":1,"3":1,"4":0,"5":2},"b":{"0":[2,0],"1":[0,1],"2":[2,1],"3":[0,1],"4":[0,1]},"meta":{"lastBranch":5,"lastFunction":6,"lastStatement":22,"seen":{"f:7:24:7:36":0,"s:8:19:8:Infinity":0,"s:9:26:9:Infinity":1,"s:10:30:10:Infinity":2,"s:11:26:11:Infinity":3,"s:13:4:36:Infinity":4,"f:13:14:13:20":1,"s:14:8:14:Infinity":5,"s:15:8:15:Infinity":6,"s:17:20:19:Infinity":7,"b:18:14:18:Infinity:19:14:19:Infinity":0,"s:21:8:35:Infinity":8,"f:22:18:22:19":2,"b:23:16:25:Infinity:undefined:undefined:undefined:undefined":1,"s:23:16:25:Infinity":9,"s:24:20:24:Infinity":10,"s:26:16:26:Infinity":11,"f:28:18:28:19":3,"s:29:16:29:Infinity":12,"s:30:16:30:Infinity":13,"f:32:19:32:20":4,"s:33:16:33:Infinity":14,"s:34:16:34:Infinity":15,"b:38:4:38:Infinity:undefined:undefined:undefined:undefined":2,"s:38:4:38:Infinity":16,"s:38:17:38:Infinity":17,"b:39:4:39:Infinity:undefined:undefined:undefined:undefined":3,"s:39:4:39:Infinity":18,"s:39:15:39:Infinity":19,"s:41:4:54:Infinity":20,"b:46:16:46:Infinity:48:16:52:Infinity":4,"f:49:31:49:32":5,"s:50:24:50:Infinity":21}}} ,"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.css": {"path":"/Users/adam/workspace/vibecode/neko/frontend/src/components/FeedList.css","statementMap":{},"fnMap":{},"branchMap":{},"s":{},"f":{},"b":{},"meta":{"lastBranch":0,"lastFunction":0,"lastStatement":0,"seen":{}}} ,"/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":8,"1":8,"2":8,"3":8,"4":5,"5":3,"6":0,"7":3,"8":3,"9":3,"10":1,"11":1,"12":8,"13":5,"14":3,"15":3,"16":2,"17":2},"f":{"0":8,"1":5,"2":3,"3":3,"4":1,"5":2},"b":{"0":[0,3],"1":[5,3],"2":[1,2],"3":[1,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":{}}} diff --git a/frontend/coverage/index.html b/frontend/coverage/index.html index 8011000..b2f47b5 100644 --- a/frontend/coverage/index.html +++ b/frontend/coverage/index.html @@ -23,30 +23,30 @@
- 90.27% + 91.2% Statements - 65/72 + 83/91
- 71.42% + 81.03% Branches - 30/42 + 47/58
- 90.47% + 92.85% Functions - 19/21 + 26/28
- 89.7% + 90.8% Lines - 61/68 + 79/87
@@ -95,17 +95,17 @@ src/components - -
+ +
- 92.98% - 53/57 - 72.22% - 26/36 - 93.33% - 14/15 - 92.45% - 49/53 + 93.42% + 71/76 + 82.69% + 43/52 + 95.45% + 21/22 + 93.05% + 67/72 @@ -116,7 +116,7 @@ + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/FeedItem.tsx.html b/frontend/coverage/src/components/FeedItem.tsx.html new file mode 100644 index 0000000..418ab70 --- /dev/null +++ b/frontend/coverage/src/components/FeedItem.tsx.html @@ -0,0 +1,352 @@ + + + + + + Code coverage report for src/components/FeedItem.tsx + + + + + + + + + +
+
+

All files / src/components FeedItem.tsx

+
+ +
+ 94.73% + Statements + 18/19 +
+ + +
+ 91.66% + Branches + 22/24 +
+ + +
+ 100% + Functions + 7/7 +
+ + +
+ 94.73% + Lines + 18/19 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +12x +12x +  +12x +2x +  +  +12x +1x +  +  +12x +3x +  +3x +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +2x +  +  +  +  +2x +  +  +1x +  +1x +1x +  +  +  +12x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState } from 'react';
+import type { Item } from '../types';
+import './FeedItem.css';
+ 
+interface FeedItemProps {
+    item: Item;
+}
+ 
+export default function FeedItem({ item: initialItem }: FeedItemProps) {
+    const [item, setItem] = useState(initialItem);
+    const [loading, setLoading] = useState(false);
+ 
+    const toggleRead = () => {
+        updateItem({ ...item, read: !item.read });
+    };
+ 
+    const toggleStar = () => {
+        updateItem({ ...item, starred: !item.starred });
+    };
+ 
+    const updateItem = (newItem: Item) => {
+        setLoading(true);
+        // Optimistic update
+        const previousItem = item;
+        setItem(newItem);
+ 
+        fetch(`/api/item/${newItem._id}`, {
+            method: 'PUT',
+            headers: {
+                'Content-Type': 'application/json',
+            },
+            body: JSON.stringify({
+                _id: newItem._id,
+                read: newItem.read,
+                starred: newItem.starred,
+            }),
+        })
+            .then((res) => {
+                Iif (!res.ok) {
+                    throw new Error('Failed to update item');
+                }
+                return res.json();
+            })
+            .then(() => {
+                // Confirm with server response if needed, but for now we trust the optimistic update
+                // or we could setItem(updated) if the server returns the full object
+                setLoading(false);
+            })
+            .catch((err) => {
+                console.error('Error updating item:', err);
+                // Revert on error
+                setItem(previousItem);
+                setLoading(false);
+            });
+    };
+ 
+    return (
+        <li className={`feed-item ${item.read ? 'read' : 'unread'} ${loading ? 'loading' : ''}`}>
+            <div className="item-header">
+                <a href={item.url} target="_blank" rel="noopener noreferrer" className="item-title">
+                    {item.title || '(No Title)'}
+                </a>
+                <div className="item-actions">
+                    <button
+                        onClick={toggleRead}
+                        className={`action-btn ${item.read ? 'is-read' : 'is-unread'}`}
+                        title={item.read ? "Mark as unread" : "Mark as read"}
+                    >
+                        {item.read ? '📖' : 'uo'}
+                    </button>
+                    <button
+                        onClick={toggleStar}
+                        className={`action-btn ${item.starred ? 'is-starred' : 'is-unstarred'}`}
+                        title={item.starred ? "Unstar" : "Star"}
+                    >
+                        {item.starred ? '★' : '☆'}
+                    </button>
+                </div>
+            </div>
+            <div className="item-meta">
+                <span className="item-date">{new Date(item.publish_date).toLocaleDateString()}</span>
+                {item.feed_title && <span className="item-feed"> - {item.feed_title}</span>}
+            </div>
+            {item.description && (
+                <div className="item-description" dangerouslySetInnerHTML={{ __html: item.description }} />
+            )}
+        </li>
+    );
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/FeedItems.css.html b/frontend/coverage/src/components/FeedItems.css.html index 3951ead..2140fe0 100644 --- a/frontend/coverage/src/components/FeedItems.css.html +++ b/frontend/coverage/src/components/FeedItems.css.html @@ -76,99 +76,7 @@ 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  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  +14        @@ -194,52 +102,6 @@ .item-list { list-style: none; padding: 0; -} -  -.item { - border-bottom: 1px solid #f0f0f0; - padding: 1rem 0; -} -  -.item.read .item-title { - color: #888; - font-weight: normal; -} -  -.item.unread .item-title { - font-weight: bold; -} -  -.item-title { - font-size: 1.2rem; - text-decoration: none; - color: #333; - display: block; - margin-bottom: 0.5rem; -} -  -.item-title:hover { - text-decoration: underline; - color: #007bff; -} -  -.item-meta { - font-size: 0.85rem; - color: #666; - margin-bottom: 0.5rem; -} -  -.item-description { - color: #444; - line-height: 1.5; - font-size: 0.95rem; -} -  -.item-description img { - max-width: 100%; - height: auto; - display: block; - margin: 1rem 0; }
@@ -247,7 +109,7 @@