diff --git a/backend/src/coverage/clover.xml b/backend/src/coverage/clover.xml new file mode 100644 index 0000000..bcae853 --- /dev/null +++ b/backend/src/coverage/clover.xml @@ -0,0 +1,481 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/src/coverage/coverage-final.json b/backend/src/coverage/coverage-final.json new file mode 100644 index 0000000..08cd7f9 --- /dev/null +++ b/backend/src/coverage/coverage-final.json @@ -0,0 +1,9 @@ +{"/home/cecilia/Documents/CTable/backend/src/app.ts": {"path":"/home/cecilia/Documents/CTable/backend/src/app.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":24}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":30}},"3":{"start":{"line":4,"column":0},"end":{"line":4,"column":57}},"4":{"start":{"line":10,"column":8},"end":{"line":10,"column":32}},"5":{"start":{"line":11,"column":8},"end":{"line":11,"column":27}},"6":{"start":{"line":12,"column":8},"end":{"line":12,"column":22}},"7":{"start":{"line":13,"column":8},"end":{"line":13,"column":28}},"8":{"start":{"line":17,"column":8},"end":{"line":17,"column":40}},"9":{"start":{"line":18,"column":8},"end":{"line":18,"column":32}},"10":{"start":{"line":22,"column":8},"end":{"line":22,"column":32}},"11":{"start":{"line":26,"column":8},"end":{"line":26,"column":38}},"12":{"start":{"line":30,"column":0},"end":{"line":30,"column":32}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":9,"column":4},"end":{"line":9,"column":null}},"loc":{"start":{"line":9,"column":4},"end":{"line":14,"column":5}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":16,"column":12},"end":{"line":16,"column":23}},"loc":{"start":{"line":16,"column":23},"end":{"line":19,"column":5}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":21,"column":12},"end":{"line":21,"column":18}},"loc":{"start":{"line":21,"column":18},"end":{"line":23,"column":5}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":25,"column":12},"end":{"line":25,"column":24}},"loc":{"start":{"line":25,"column":24},"end":{"line":27,"column":5}}}},"branchMap":{},"s":{"0":5,"1":5,"2":5,"3":5,"4":5,"5":5,"6":5,"7":5,"8":5,"9":5,"10":5,"11":5,"12":5},"f":{"0":5,"1":5,"2":5,"3":5},"b":{}} +,"/home/cecilia/Documents/CTable/backend/src/routes.ts": {"path":"/home/cecilia/Documents/CTable/backend/src/routes.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":30}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":63}},"2":{"start":{"line":3,"column":0},"end":{"line":3,"column":47}},"3":{"start":{"line":7,"column":15},"end":{"line":7,"column":31}},"4":{"start":{"line":10,"column":0},"end":{"line":18,"column":3}},"5":{"start":{"line":11,"column":4},"end":{"line":11,"column":67}},"6":{"start":{"line":12,"column":26},"end":{"line":12,"column":74}},"7":{"start":{"line":13,"column":4},"end":{"line":17,"column":7}},"8":{"start":{"line":21,"column":0},"end":{"line":28,"column":3}},"9":{"start":{"line":22,"column":28},"end":{"line":22,"column":75}},"10":{"start":{"line":23,"column":4},"end":{"line":27,"column":7}},"11":{"start":{"line":32,"column":0},"end":{"line":36,"column":3}},"12":{"start":{"line":33,"column":17},"end":{"line":33,"column":54}},"13":{"start":{"line":35,"column":4},"end":{"line":35,"column":43}},"14":{"start":{"line":39,"column":0},"end":{"line":50,"column":3}},"15":{"start":{"line":40,"column":24},"end":{"line":40,"column":36}},"16":{"start":{"line":42,"column":22},"end":{"line":42,"column":37}},"17":{"start":{"line":44,"column":23},"end":{"line":44,"column":84}},"18":{"start":{"line":46,"column":4},"end":{"line":49,"column":7}},"19":{"start":{"line":54,"column":0},"end":{"line":60,"column":3}},"20":{"start":{"line":55,"column":24},"end":{"line":55,"column":39}},"21":{"start":{"line":56,"column":23},"end":{"line":56,"column":73}},"22":{"start":{"line":57,"column":6},"end":{"line":59,"column":null}},"23":{"start":{"line":63,"column":0},"end":{"line":74,"column":3}},"24":{"start":{"line":64,"column":26},"end":{"line":64,"column":40}},"25":{"start":{"line":65,"column":24},"end":{"line":65,"column":36}},"26":{"start":{"line":66,"column":22},"end":{"line":66,"column":37}},"27":{"start":{"line":68,"column":27},"end":{"line":68,"column":99}},"28":{"start":{"line":70,"column":4},"end":{"line":73,"column":7}},"29":{"start":{"line":76,"column":0},"end":{"line":83,"column":3}},"30":{"start":{"line":78,"column":26},"end":{"line":78,"column":40}},"31":{"start":{"line":80,"column":4},"end":{"line":80,"column":70}},"32":{"start":{"line":82,"column":4},"end":{"line":82,"column":83}},"33":{"start":{"line":86,"column":0},"end":{"line":93,"column":null}},"34":{"start":{"line":88,"column":28},"end":{"line":88,"column":42}},"35":{"start":{"line":90,"column":19},"end":{"line":90,"column":93}},"36":{"start":{"line":92,"column":4},"end":{"line":92,"column":45}},"37":{"start":{"line":96,"column":0},"end":{"line":103,"column":3}},"38":{"start":{"line":98,"column":25},"end":{"line":98,"column":92}},"39":{"start":{"line":99,"column":4},"end":{"line":101,"column":null}},"40":{"start":{"line":105,"column":0},"end":{"line":110,"column":3}},"41":{"start":{"line":107,"column":24},"end":{"line":107,"column":86}},"42":{"start":{"line":108,"column":4},"end":{"line":108,"column":50}},"43":{"start":{"line":112,"column":0},"end":{"line":120,"column":3}},"44":{"start":{"line":114,"column":28},"end":{"line":114,"column":42}},"45":{"start":{"line":115,"column":19},"end":{"line":115,"column":34}},"46":{"start":{"line":117,"column":17},"end":{"line":117,"column":78}},"47":{"start":{"line":119,"column":4},"end":{"line":119,"column":43}},"48":{"start":{"line":122,"column":0},"end":{"line":127,"column":3}},"49":{"start":{"line":124,"column":24},"end":{"line":124,"column":67}},"50":{"start":{"line":125,"column":4},"end":{"line":125,"column":50}},"51":{"start":{"line":129,"column":0},"end":{"line":137,"column":3}},"52":{"start":{"line":131,"column":19},"end":{"line":131,"column":34}},"53":{"start":{"line":132,"column":28},"end":{"line":132,"column":42}},"54":{"start":{"line":134,"column":19},"end":{"line":134,"column":82}},"55":{"start":{"line":136,"column":4},"end":{"line":136,"column":45}},"56":{"start":{"line":140,"column":0},"end":{"line":151,"column":3}},"57":{"start":{"line":141,"column":28},"end":{"line":141,"column":42}},"58":{"start":{"line":142,"column":17},"end":{"line":142,"column":29}},"59":{"start":{"line":144,"column":29},"end":{"line":144,"column":104}},"60":{"start":{"line":146,"column":4},"end":{"line":149,"column":7}},"61":{"start":{"line":154,"column":0},"end":{"line":161,"column":null}},"62":{"start":{"line":155,"column":28},"end":{"line":155,"column":42}},"63":{"start":{"line":157,"column":4},"end":{"line":157,"column":74}},"64":{"start":{"line":159,"column":4},"end":{"line":159,"column":86}},"65":{"start":{"line":164,"column":0},"end":{"line":173,"column":null}},"66":{"start":{"line":166,"column":26},"end":{"line":166,"column":40}},"67":{"start":{"line":167,"column":24},"end":{"line":167,"column":36}},"68":{"start":{"line":169,"column":20},"end":{"line":169,"column":91}},"69":{"start":{"line":171,"column":4},"end":{"line":171,"column":46}},"70":{"start":{"line":175,"column":0},"end":{"line":180,"column":null}},"71":{"start":{"line":177,"column":24},"end":{"line":177,"column":80}},"72":{"start":{"line":179,"column":4},"end":{"line":179,"column":50}},"73":{"start":{"line":182,"column":0},"end":{"line":190,"column":null}},"74":{"start":{"line":184,"column":26},"end":{"line":184,"column":40}},"75":{"start":{"line":186,"column":4},"end":{"line":186,"column":72}},"76":{"start":{"line":188,"column":4},"end":{"line":188,"column":85}},"77":{"start":{"line":192,"column":0},"end":{"line":200,"column":null}},"78":{"start":{"line":194,"column":26},"end":{"line":194,"column":40}},"79":{"start":{"line":196,"column":28},"end":{"line":196,"column":83}},"80":{"start":{"line":198,"column":4},"end":{"line":198,"column":54}},"81":{"start":{"line":203,"column":0},"end":{"line":208,"column":null}},"82":{"start":{"line":205,"column":27},"end":{"line":205,"column":95}},"83":{"start":{"line":207,"column":4},"end":{"line":207,"column":53}},"84":{"start":{"line":210,"column":0},"end":{"line":215,"column":null}},"85":{"start":{"line":212,"column":20},"end":{"line":212,"column":74}},"86":{"start":{"line":214,"column":4},"end":{"line":214,"column":46}},"87":{"start":{"line":217,"column":0},"end":{"line":222,"column":null}},"88":{"start":{"line":219,"column":21},"end":{"line":219,"column":73}},"89":{"start":{"line":221,"column":4},"end":{"line":221,"column":47}},"90":{"start":{"line":224,"column":0},"end":{"line":232,"column":3}},"91":{"start":{"line":225,"column":26},"end":{"line":225,"column":40}},"92":{"start":{"line":226,"column":4},"end":{"line":231,"column":5}},"93":{"start":{"line":227,"column":24},"end":{"line":227,"column":73}},"94":{"start":{"line":228,"column":8},"end":{"line":228,"column":50}},"95":{"start":{"line":230,"column":8},"end":{"line":230,"column":80}},"96":{"start":{"line":235,"column":0},"end":{"line":235,"column":22}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":10,"column":29},"end":{"line":10,"column":34}},"loc":{"start":{"line":10,"column":57},"end":{"line":18,"column":1}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":21,"column":26},"end":{"line":21,"column":31}},"loc":{"start":{"line":21,"column":53},"end":{"line":28,"column":1}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":32,"column":28},"end":{"line":32,"column":33}},"loc":{"start":{"line":32,"column":55},"end":{"line":36,"column":1}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":39,"column":53},"end":{"line":39,"column":58}},"loc":{"start":{"line":39,"column":80},"end":{"line":50,"column":1}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":54,"column":49},"end":{"line":54,"column":54}},"loc":{"start":{"line":54,"column":76},"end":{"line":60,"column":1}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":63,"column":65},"end":{"line":63,"column":70}},"loc":{"start":{"line":63,"column":92},"end":{"line":74,"column":1}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":76,"column":68},"end":{"line":76,"column":73}},"loc":{"start":{"line":76,"column":95},"end":{"line":83,"column":1}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":86,"column":71},"end":{"line":86,"column":76}},"loc":{"start":{"line":86,"column":98},"end":{"line":93,"column":1}}},"8":{"name":"(anonymous_9)","decl":{"start":{"line":96,"column":49},"end":{"line":96,"column":54}},"loc":{"start":{"line":96,"column":76},"end":{"line":103,"column":1}}},"9":{"name":"(anonymous_10)","decl":{"start":{"line":105,"column":52},"end":{"line":105,"column":57}},"loc":{"start":{"line":105,"column":80},"end":{"line":110,"column":1}}},"10":{"name":"(anonymous_11)","decl":{"start":{"line":112,"column":65},"end":{"line":112,"column":70}},"loc":{"start":{"line":112,"column":93},"end":{"line":120,"column":1}}},"11":{"name":"(anonymous_12)","decl":{"start":{"line":122,"column":31},"end":{"line":122,"column":36}},"loc":{"start":{"line":122,"column":58},"end":{"line":127,"column":1}}},"12":{"name":"(anonymous_13)","decl":{"start":{"line":129,"column":66},"end":{"line":129,"column":71}},"loc":{"start":{"line":129,"column":93},"end":{"line":137,"column":1}}},"13":{"name":"(anonymous_14)","decl":{"start":{"line":140,"column":76},"end":{"line":140,"column":81}},"loc":{"start":{"line":140,"column":103},"end":{"line":151,"column":1}}},"14":{"name":"(anonymous_15)","decl":{"start":{"line":154,"column":79},"end":{"line":154,"column":84}},"loc":{"start":{"line":154,"column":106},"end":{"line":161,"column":1}}},"15":{"name":"(anonymous_16)","decl":{"start":{"line":164,"column":64},"end":{"line":164,"column":69}},"loc":{"start":{"line":164,"column":91},"end":{"line":173,"column":1}}},"16":{"name":"(anonymous_17)","decl":{"start":{"line":175,"column":49},"end":{"line":175,"column":54}},"loc":{"start":{"line":175,"column":76},"end":{"line":180,"column":1}}},"17":{"name":"(anonymous_18)","decl":{"start":{"line":182,"column":71},"end":{"line":182,"column":76}},"loc":{"start":{"line":182,"column":98},"end":{"line":190,"column":1}}},"18":{"name":"(anonymous_19)","decl":{"start":{"line":192,"column":47},"end":{"line":192,"column":52}},"loc":{"start":{"line":192,"column":74},"end":{"line":200,"column":1}}},"19":{"name":"(anonymous_20)","decl":{"start":{"line":203,"column":52},"end":{"line":203,"column":57}},"loc":{"start":{"line":203,"column":79},"end":{"line":208,"column":1}}},"20":{"name":"(anonymous_21)","decl":{"start":{"line":210,"column":57},"end":{"line":210,"column":62}},"loc":{"start":{"line":210,"column":84},"end":{"line":215,"column":1}}},"21":{"name":"(anonymous_22)","decl":{"start":{"line":217,"column":45},"end":{"line":217,"column":50}},"loc":{"start":{"line":217,"column":72},"end":{"line":222,"column":1}}},"22":{"name":"(anonymous_23)","decl":{"start":{"line":224,"column":55},"end":{"line":224,"column":60}},"loc":{"start":{"line":224,"column":83},"end":{"line":232,"column":1}}}},"branchMap":{},"s":{"0":5,"1":5,"2":5,"3":5,"4":5,"5":82,"6":82,"7":80,"8":5,"9":77,"10":75,"11":5,"12":0,"13":0,"14":5,"15":17,"16":17,"17":17,"18":17,"19":5,"20":4,"21":4,"22":4,"23":5,"24":2,"25":2,"26":2,"27":2,"28":1,"29":5,"30":2,"31":2,"32":1,"33":5,"34":3,"35":3,"36":1,"37":5,"38":17,"39":15,"40":5,"41":0,"42":0,"43":5,"44":1,"45":1,"46":1,"47":1,"48":5,"49":1,"50":1,"51":5,"52":4,"53":4,"54":4,"55":3,"56":5,"57":3,"58":3,"59":3,"60":1,"61":5,"62":1,"63":1,"64":0,"65":5,"66":9,"67":9,"68":9,"69":9,"70":5,"71":3,"72":3,"73":5,"74":2,"75":2,"76":1,"77":5,"78":2,"79":2,"80":2,"81":5,"82":3,"83":2,"84":5,"85":2,"86":2,"87":5,"88":1,"89":1,"90":5,"91":3,"92":3,"93":3,"94":1,"95":2,"96":5},"f":{"0":82,"1":77,"2":0,"3":17,"4":4,"5":2,"6":2,"7":3,"8":17,"9":0,"10":1,"11":1,"12":4,"13":3,"14":1,"15":9,"16":3,"17":2,"18":2,"19":3,"20":2,"21":1,"22":3},"b":{}} +,"/home/cecilia/Documents/CTable/backend/src/business/businessLogicAuth.ts": {"path":"/home/cecilia/Documents/CTable/backend/src/business/businessLogicAuth.ts","statementMap":{"0":{"start":{"line":3,"column":0},"end":{"line":3,"column":55}},"1":{"start":{"line":4,"column":0},"end":{"line":4,"column":33}},"2":{"start":{"line":5,"column":0},"end":{"line":5,"column":30}},"3":{"start":{"line":13,"column":8},"end":{"line":13,"column":27}},"4":{"start":{"line":15,"column":29},"end":{"line":18,"column":24}},"5":{"start":{"line":20,"column":8},"end":{"line":27,"column":9}},"6":{"start":{"line":21,"column":12},"end":{"line":23,"column":13}},"7":{"start":{"line":22,"column":16},"end":{"line":22,"column":65}},"8":{"start":{"line":24,"column":12},"end":{"line":26,"column":13}},"9":{"start":{"line":25,"column":16},"end":{"line":25,"column":63}},"10":{"start":{"line":29,"column":21},"end":{"line":29,"column":45}},"11":{"start":{"line":31,"column":26},"end":{"line":31,"column":61}},"12":{"start":{"line":33,"column":76},"end":{"line":33,"column":80}},"13":{"start":{"line":36,"column":8},"end":{"line":43,"column":11}},"14":{"start":{"line":45,"column":21},"end":{"line":47,"column":28}},"15":{"start":{"line":49,"column":45},"end":{"line":49,"column":49}},"16":{"start":{"line":51,"column":8},"end":{"line":51,"column":24}},"17":{"start":{"line":56,"column":8},"end":{"line":82,"column":9}},"18":{"start":{"line":57,"column":25},"end":{"line":59,"column":28}},"19":{"start":{"line":61,"column":12},"end":{"line":63,"column":13}},"20":{"start":{"line":62,"column":16},"end":{"line":62,"column":64}},"21":{"start":{"line":65,"column":36},"end":{"line":67,"column":null}},"22":{"start":{"line":70,"column":12},"end":{"line":72,"column":13}},"23":{"start":{"line":71,"column":16},"end":{"line":71,"column":64}},"24":{"start":{"line":74,"column":50},"end":{"line":74,"column":54}},"25":{"start":{"line":76,"column":12},"end":{"line":76,"column":28}},"26":{"start":{"line":80,"column":12},"end":{"line":80,"column":24}},"27":{"start":{"line":88,"column":0},"end":{"line":88,"column":39}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":11,"column":4},"end":{"line":11,"column":9}},"loc":{"start":{"line":11,"column":32},"end":{"line":53,"column":5}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":55,"column":4},"end":{"line":55,"column":9}},"loc":{"start":{"line":55,"column":35},"end":{"line":83,"column":5}}}},"branchMap":{"0":{"loc":{"start":{"line":20,"column":8},"end":{"line":27,"column":9}},"type":"if","locations":[{"start":{"line":20,"column":8},"end":{"line":27,"column":9}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":21,"column":12},"end":{"line":23,"column":13}},"type":"if","locations":[{"start":{"line":21,"column":12},"end":{"line":23,"column":13}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":24,"column":12},"end":{"line":26,"column":13}},"type":"if","locations":[{"start":{"line":24,"column":12},"end":{"line":26,"column":13}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":61,"column":12},"end":{"line":63,"column":13}},"type":"if","locations":[{"start":{"line":61,"column":12},"end":{"line":63,"column":13}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":70,"column":12},"end":{"line":72,"column":13}},"type":"if","locations":[{"start":{"line":70,"column":12},"end":{"line":72,"column":13}},{"start":{},"end":{}}]}},"s":{"0":5,"1":5,"2":5,"3":82,"4":82,"5":82,"6":2,"7":1,"8":1,"9":1,"10":80,"11":80,"12":80,"13":80,"14":80,"15":80,"16":80,"17":77,"18":77,"19":77,"20":1,"21":76,"22":76,"23":1,"24":75,"25":75,"26":2,"27":5},"f":{"0":82,"1":77},"b":{"0":[2,80],"1":[1,1],"2":[1,0],"3":[1,76],"4":[1,75]}} +,"/home/cecilia/Documents/CTable/backend/src/business/businessLogicCommunity.ts": {"path":"/home/cecilia/Documents/CTable/backend/src/business/businessLogicCommunity.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":33}},"1":{"start":{"line":10,"column":34},"end":{"line":12,"column":20}},"2":{"start":{"line":14,"column":8},"end":{"line":16,"column":9}},"3":{"start":{"line":15,"column":12},"end":{"line":15,"column":71}},"4":{"start":{"line":18,"column":8},"end":{"line":60,"column":11}},"5":{"start":{"line":20,"column":38},"end":{"line":24,"column":14}},"6":{"start":{"line":26,"column":39},"end":{"line":28,"column":31}},"7":{"start":{"line":30,"column":12},"end":{"line":32,"column":13}},"8":{"start":{"line":31,"column":16},"end":{"line":31,"column":62}},"9":{"start":{"line":34,"column":12},"end":{"line":39,"column":15}},"10":{"start":{"line":41,"column":12},"end":{"line":57,"column":13}},"11":{"start":{"line":43,"column":35},"end":{"line":45,"column":60}},"12":{"start":{"line":47,"column":41},"end":{"line":52,"column":18}},"13":{"start":{"line":48,"column":20},"end":{"line":51,"column":22}},"14":{"start":{"line":54,"column":16},"end":{"line":56,"column":17}},"15":{"start":{"line":55,"column":20},"end":{"line":55,"column":78}},"16":{"start":{"line":59,"column":12},"end":{"line":59,"column":36}},"17":{"start":{"line":65,"column":26},"end":{"line":67,"column":20}},"18":{"start":{"line":69,"column":8},"end":{"line":71,"column":9}},"19":{"start":{"line":70,"column":12},"end":{"line":70,"column":58}},"20":{"start":{"line":73,"column":31},"end":{"line":76,"column":20}},"21":{"start":{"line":78,"column":8},"end":{"line":80,"column":9}},"22":{"start":{"line":79,"column":12},"end":{"line":79,"column":69}},"23":{"start":{"line":82,"column":8},"end":{"line":87,"column":11}},"24":{"start":{"line":89,"column":8},"end":{"line":89,"column":81}},"25":{"start":{"line":94,"column":26},"end":{"line":96,"column":20}},"26":{"start":{"line":98,"column":8},"end":{"line":100,"column":9}},"27":{"start":{"line":99,"column":12},"end":{"line":99,"column":58}},"28":{"start":{"line":102,"column":8},"end":{"line":104,"column":9}},"29":{"start":{"line":103,"column":12},"end":{"line":103,"column":119}},"30":{"start":{"line":106,"column":23},"end":{"line":108,"column":20}},"31":{"start":{"line":110,"column":8},"end":{"line":112,"column":9}},"32":{"start":{"line":111,"column":12},"end":{"line":111,"column":67}},"33":{"start":{"line":114,"column":8},"end":{"line":116,"column":19}},"34":{"start":{"line":118,"column":8},"end":{"line":118,"column":67}},"35":{"start":{"line":123,"column":32},"end":{"line":129,"column":null}},"36":{"start":{"line":132,"column":29},"end":{"line":132,"column":68}},"37":{"start":{"line":132,"column":54},"end":{"line":132,"column":67}},"38":{"start":{"line":134,"column":8},"end":{"line":134,"column":49}},"39":{"start":{"line":134,"column":39},"end":{"line":134,"column":49}},"40":{"start":{"line":136,"column":25},"end":{"line":139,"column":70}},"41":{"start":{"line":141,"column":23},"end":{"line":146,"column":11}},"42":{"start":{"line":141,"column":52},"end":{"line":146,"column":10}},"43":{"start":{"line":144,"column":36},"end":{"line":144,"column":70}},"44":{"start":{"line":145,"column":33},"end":{"line":145,"column":38}},"45":{"start":{"line":148,"column":8},"end":{"line":148,"column":22}},"46":{"start":{"line":152,"column":21},"end":{"line":170,"column":50}},"47":{"start":{"line":172,"column":8},"end":{"line":172,"column":20}},"48":{"start":{"line":176,"column":28},"end":{"line":176,"column":65}},"49":{"start":{"line":178,"column":29},"end":{"line":178,"column":64}},"50":{"start":{"line":178,"column":50},"end":{"line":178,"column":63}},"51":{"start":{"line":180,"column":8},"end":{"line":180,"column":49}},"52":{"start":{"line":180,"column":39},"end":{"line":180,"column":49}},"53":{"start":{"line":182,"column":25},"end":{"line":185,"column":70}},"54":{"start":{"line":187,"column":23},"end":{"line":192,"column":11}},"55":{"start":{"line":187,"column":48},"end":{"line":192,"column":10}},"56":{"start":{"line":190,"column":36},"end":{"line":190,"column":70}},"57":{"start":{"line":191,"column":33},"end":{"line":191,"column":38}},"58":{"start":{"line":194,"column":8},"end":{"line":194,"column":22}},"59":{"start":{"line":199,"column":26},"end":{"line":201,"column":20}},"60":{"start":{"line":203,"column":8},"end":{"line":205,"column":9}},"61":{"start":{"line":204,"column":12},"end":{"line":204,"column":58}},"62":{"start":{"line":207,"column":27},"end":{"line":209,"column":20}},"63":{"start":{"line":211,"column":25},"end":{"line":211,"column":37}},"64":{"start":{"line":212,"column":24},"end":{"line":212,"column":103}},"65":{"start":{"line":214,"column":25},"end":{"line":217,"column":31}},"66":{"start":{"line":219,"column":28},"end":{"line":222,"column":16}},"67":{"start":{"line":224,"column":25},"end":{"line":227,"column":33}},"68":{"start":{"line":229,"column":8},"end":{"line":238,"column":6}},"69":{"start":{"line":232,"column":51},"end":{"line":232,"column":56}},"70":{"start":{"line":243,"column":8},"end":{"line":290,"column":11}},"71":{"start":{"line":245,"column":30},"end":{"line":247,"column":24}},"72":{"start":{"line":249,"column":12},"end":{"line":251,"column":13}},"73":{"start":{"line":250,"column":16},"end":{"line":250,"column":62}},"74":{"start":{"line":253,"column":12},"end":{"line":255,"column":13}},"75":{"start":{"line":254,"column":16},"end":{"line":254,"column":87}},"76":{"start":{"line":257,"column":40},"end":{"line":257,"column":42}},"77":{"start":{"line":258,"column":12},"end":{"line":258,"column":59}},"78":{"start":{"line":258,"column":27},"end":{"line":258,"column":59}},"79":{"start":{"line":259,"column":12},"end":{"line":259,"column":80}},"80":{"start":{"line":259,"column":34},"end":{"line":259,"column":80}},"81":{"start":{"line":261,"column":12},"end":{"line":266,"column":13}},"82":{"start":{"line":262,"column":16},"end":{"line":262,"column":54}},"83":{"start":{"line":263,"column":16},"end":{"line":265,"column":44}},"84":{"start":{"line":268,"column":12},"end":{"line":287,"column":13}},"85":{"start":{"line":269,"column":17},"end":{"line":271,"column":27}},"86":{"start":{"line":273,"column":17},"end":{"line":286,"column":18}},"87":{"start":{"line":274,"column":39},"end":{"line":276,"column":44}},"88":{"start":{"line":278,"column":42},"end":{"line":281,"column":23}},"89":{"start":{"line":278,"column":70},"end":{"line":281,"column":22}},"90":{"start":{"line":283,"column":20},"end":{"line":285,"column":21}},"91":{"start":{"line":284,"column":24},"end":{"line":284,"column":79}},"92":{"start":{"line":289,"column":12},"end":{"line":289,"column":86}},"93":{"start":{"line":294,"column":26},"end":{"line":296,"column":20}},"94":{"start":{"line":298,"column":8},"end":{"line":300,"column":9}},"95":{"start":{"line":299,"column":12},"end":{"line":299,"column":58}},"96":{"start":{"line":302,"column":8},"end":{"line":304,"column":9}},"97":{"start":{"line":303,"column":12},"end":{"line":303,"column":84}},"98":{"start":{"line":306,"column":8},"end":{"line":308,"column":19}},"99":{"start":{"line":314,"column":0},"end":{"line":314,"column":44}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":8,"column":4},"end":{"line":8,"column":9}},"loc":{"start":{"line":8,"column":61},"end":{"line":61,"column":5}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":18,"column":32},"end":{"line":18,"column":37}},"loc":{"start":{"line":18,"column":46},"end":{"line":60,"column":9}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":47,"column":56},"end":{"line":47,"column":63}},"loc":{"start":{"line":47,"column":66},"end":{"line":52,"column":17}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":63,"column":4},"end":{"line":63,"column":9}},"loc":{"start":{"line":63,"column":64},"end":{"line":90,"column":5}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":92,"column":4},"end":{"line":92,"column":9}},"loc":{"start":{"line":92,"column":66},"end":{"line":119,"column":5}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":121,"column":4},"end":{"line":121,"column":9}},"loc":{"start":{"line":121,"column":46},"end":{"line":149,"column":5}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":132,"column":49},"end":{"line":132,"column":50}},"loc":{"start":{"line":132,"column":54},"end":{"line":132,"column":67}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":141,"column":43},"end":{"line":141,"column":47}},"loc":{"start":{"line":141,"column":52},"end":{"line":146,"column":10}}},"8":{"name":"(anonymous_9)","decl":{"start":{"line":144,"column":24},"end":{"line":144,"column":25}},"loc":{"start":{"line":144,"column":36},"end":{"line":144,"column":70}}},"9":{"name":"(anonymous_10)","decl":{"start":{"line":145,"column":21},"end":{"line":145,"column":22}},"loc":{"start":{"line":145,"column":33},"end":{"line":145,"column":38}}},"10":{"name":"(anonymous_11)","decl":{"start":{"line":151,"column":4},"end":{"line":151,"column":9}},"loc":{"start":{"line":151,"column":36},"end":{"line":173,"column":5}}},"11":{"name":"(anonymous_12)","decl":{"start":{"line":175,"column":4},"end":{"line":175,"column":9}},"loc":{"start":{"line":175,"column":27},"end":{"line":195,"column":5}}},"12":{"name":"(anonymous_13)","decl":{"start":{"line":178,"column":45},"end":{"line":178,"column":46}},"loc":{"start":{"line":178,"column":50},"end":{"line":178,"column":63}}},"13":{"name":"(anonymous_14)","decl":{"start":{"line":187,"column":39},"end":{"line":187,"column":43}},"loc":{"start":{"line":187,"column":48},"end":{"line":192,"column":10}}},"14":{"name":"(anonymous_15)","decl":{"start":{"line":190,"column":24},"end":{"line":190,"column":25}},"loc":{"start":{"line":190,"column":36},"end":{"line":190,"column":70}}},"15":{"name":"(anonymous_16)","decl":{"start":{"line":191,"column":21},"end":{"line":191,"column":22}},"loc":{"start":{"line":191,"column":33},"end":{"line":191,"column":38}}},"16":{"name":"(anonymous_17)","decl":{"start":{"line":197,"column":4},"end":{"line":197,"column":9}},"loc":{"start":{"line":197,"column":62},"end":{"line":239,"column":5}}},"17":{"name":"(anonymous_18)","decl":{"start":{"line":232,"column":39},"end":{"line":232,"column":40}},"loc":{"start":{"line":232,"column":51},"end":{"line":232,"column":56}}},"18":{"name":"(anonymous_19)","decl":{"start":{"line":241,"column":4},"end":{"line":241,"column":9}},"loc":{"start":{"line":241,"column":85},"end":{"line":291,"column":5}}},"19":{"name":"(anonymous_20)","decl":{"start":{"line":243,"column":32},"end":{"line":243,"column":37}},"loc":{"start":{"line":243,"column":46},"end":{"line":290,"column":9}}},"20":{"name":"(anonymous_21)","decl":{"start":{"line":278,"column":57},"end":{"line":278,"column":58}},"loc":{"start":{"line":278,"column":70},"end":{"line":281,"column":22}}},"21":{"name":"(anonymous_22)","decl":{"start":{"line":293,"column":4},"end":{"line":293,"column":9}},"loc":{"start":{"line":293,"column":64},"end":{"line":309,"column":5}}}},"branchMap":{"0":{"loc":{"start":{"line":14,"column":8},"end":{"line":16,"column":9}},"type":"if","locations":[{"start":{"line":14,"column":8},"end":{"line":16,"column":9}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":30,"column":12},"end":{"line":32,"column":13}},"type":"if","locations":[{"start":{"line":30,"column":12},"end":{"line":32,"column":13}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":41,"column":12},"end":{"line":57,"column":13}},"type":"if","locations":[{"start":{"line":41,"column":12},"end":{"line":57,"column":13}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":41,"column":16},"end":{"line":41,"column":65}},"type":"binary-expr","locations":[{"start":{"line":41,"column":16},"end":{"line":41,"column":33}},{"start":{"line":41,"column":37},"end":{"line":41,"column":65}}]},"4":{"loc":{"start":{"line":54,"column":16},"end":{"line":56,"column":17}},"type":"if","locations":[{"start":{"line":54,"column":16},"end":{"line":56,"column":17}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":69,"column":8},"end":{"line":71,"column":9}},"type":"if","locations":[{"start":{"line":69,"column":8},"end":{"line":71,"column":9}},{"start":{},"end":{}}]},"6":{"loc":{"start":{"line":78,"column":8},"end":{"line":80,"column":9}},"type":"if","locations":[{"start":{"line":78,"column":8},"end":{"line":80,"column":9}},{"start":{},"end":{}}]},"7":{"loc":{"start":{"line":98,"column":8},"end":{"line":100,"column":9}},"type":"if","locations":[{"start":{"line":98,"column":8},"end":{"line":100,"column":9}},{"start":{},"end":{}}]},"8":{"loc":{"start":{"line":102,"column":8},"end":{"line":104,"column":9}},"type":"if","locations":[{"start":{"line":102,"column":8},"end":{"line":104,"column":9}},{"start":{},"end":{}}]},"9":{"loc":{"start":{"line":110,"column":8},"end":{"line":112,"column":9}},"type":"if","locations":[{"start":{"line":110,"column":8},"end":{"line":112,"column":9}},{"start":{},"end":{}}]},"10":{"loc":{"start":{"line":134,"column":8},"end":{"line":134,"column":49}},"type":"if","locations":[{"start":{"line":134,"column":8},"end":{"line":134,"column":49}},{"start":{},"end":{}}]},"11":{"loc":{"start":{"line":180,"column":8},"end":{"line":180,"column":49}},"type":"if","locations":[{"start":{"line":180,"column":8},"end":{"line":180,"column":49}},{"start":{},"end":{}}]},"12":{"loc":{"start":{"line":203,"column":8},"end":{"line":205,"column":9}},"type":"if","locations":[{"start":{"line":203,"column":8},"end":{"line":205,"column":9}},{"start":{},"end":{}}]},"13":{"loc":{"start":{"line":212,"column":24},"end":{"line":212,"column":103}},"type":"binary-expr","locations":[{"start":{"line":212,"column":25},"end":{"line":212,"column":55}},{"start":{"line":212,"column":61},"end":{"line":212,"column":71}},{"start":{"line":212,"column":75},"end":{"line":212,"column":102}}]},"14":{"loc":{"start":{"line":233,"column":25},"end":{"line":233,"column":48}},"type":"binary-expr","locations":[{"start":{"line":233,"column":25},"end":{"line":233,"column":43}},{"start":{"line":233,"column":47},"end":{"line":233,"column":48}}]},"15":{"loc":{"start":{"line":237,"column":15},"end":{"line":237,"column":29}},"type":"binary-expr","locations":[{"start":{"line":237,"column":15},"end":{"line":237,"column":23}},{"start":{"line":237,"column":27},"end":{"line":237,"column":29}}]},"16":{"loc":{"start":{"line":249,"column":12},"end":{"line":251,"column":13}},"type":"if","locations":[{"start":{"line":249,"column":12},"end":{"line":251,"column":13}},{"start":{},"end":{}}]},"17":{"loc":{"start":{"line":253,"column":12},"end":{"line":255,"column":13}},"type":"if","locations":[{"start":{"line":253,"column":12},"end":{"line":255,"column":13}},{"start":{},"end":{}}]},"18":{"loc":{"start":{"line":258,"column":12},"end":{"line":258,"column":59}},"type":"if","locations":[{"start":{"line":258,"column":12},"end":{"line":258,"column":59}},{"start":{},"end":{}}]},"19":{"loc":{"start":{"line":259,"column":12},"end":{"line":259,"column":80}},"type":"if","locations":[{"start":{"line":259,"column":12},"end":{"line":259,"column":80}},{"start":{},"end":{}}]},"20":{"loc":{"start":{"line":261,"column":12},"end":{"line":266,"column":13}},"type":"if","locations":[{"start":{"line":261,"column":12},"end":{"line":266,"column":13}},{"start":{},"end":{}}]},"21":{"loc":{"start":{"line":268,"column":12},"end":{"line":287,"column":13}},"type":"if","locations":[{"start":{"line":268,"column":12},"end":{"line":287,"column":13}},{"start":{},"end":{}}]},"22":{"loc":{"start":{"line":273,"column":17},"end":{"line":286,"column":18}},"type":"if","locations":[{"start":{"line":273,"column":17},"end":{"line":286,"column":18}},{"start":{},"end":{}}]},"23":{"loc":{"start":{"line":273,"column":21},"end":{"line":273,"column":85}},"type":"binary-expr","locations":[{"start":{"line":273,"column":21},"end":{"line":273,"column":53}},{"start":{"line":273,"column":57},"end":{"line":273,"column":85}}]},"24":{"loc":{"start":{"line":283,"column":20},"end":{"line":285,"column":21}},"type":"if","locations":[{"start":{"line":283,"column":20},"end":{"line":285,"column":21}},{"start":{},"end":{}}]},"25":{"loc":{"start":{"line":298,"column":8},"end":{"line":300,"column":9}},"type":"if","locations":[{"start":{"line":298,"column":8},"end":{"line":300,"column":9}},{"start":{},"end":{}}]},"26":{"loc":{"start":{"line":302,"column":8},"end":{"line":304,"column":9}},"type":"if","locations":[{"start":{"line":302,"column":8},"end":{"line":304,"column":9}},{"start":{},"end":{}}]}},"s":{"0":5,"1":17,"2":17,"3":2,"4":15,"5":15,"6":15,"7":15,"8":0,"9":15,"10":15,"11":2,"12":2,"13":2,"14":2,"15":2,"16":15,"17":4,"18":4,"19":0,"20":4,"21":4,"22":1,"23":3,"24":3,"25":3,"26":3,"27":0,"28":3,"29":1,"30":2,"31":2,"32":1,"33":1,"34":1,"35":1,"36":1,"37":0,"38":1,"39":1,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":1,"47":1,"48":1,"49":1,"50":2,"51":1,"52":0,"53":1,"54":1,"55":2,"56":0,"57":0,"58":1,"59":1,"60":1,"61":0,"62":1,"63":1,"64":1,"65":1,"66":1,"67":1,"68":1,"69":0,"70":3,"71":3,"72":3,"73":1,"74":2,"75":1,"76":1,"77":1,"78":1,"79":1,"80":1,"81":1,"82":1,"83":1,"84":1,"85":1,"86":1,"87":1,"88":1,"89":1,"90":1,"91":1,"92":1,"93":1,"94":1,"95":0,"96":1,"97":1,"98":0,"99":5},"f":{"0":17,"1":15,"2":2,"3":4,"4":3,"5":1,"6":0,"7":0,"8":0,"9":0,"10":1,"11":1,"12":2,"13":2,"14":0,"15":0,"16":1,"17":0,"18":3,"19":3,"20":1,"21":1},"b":{"0":[2,15],"1":[0,15],"2":[2,13],"3":[15,3],"4":[2,0],"5":[0,4],"6":[1,3],"7":[0,3],"8":[1,2],"9":[1,1],"10":[1,0],"11":[0,1],"12":[0,1],"13":[1,0,0],"14":[1,0],"15":[1,0],"16":[1,2],"17":[1,1],"18":[1,0],"19":[1,0],"20":[1,0],"21":[1,0],"22":[1,0],"23":[1,1],"24":[1,0],"25":[0,1],"26":[1,0]}} +,"/home/cecilia/Documents/CTable/backend/src/business/businessLogicProfile.ts": {"path":"/home/cecilia/Documents/CTable/backend/src/business/businessLogicProfile.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":33}},"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":30}},"2":{"start":{"line":12,"column":36},"end":{"line":12,"column":38}},"3":{"start":{"line":14,"column":8},"end":{"line":14,"column":75}},"4":{"start":{"line":14,"column":31},"end":{"line":14,"column":75}},"5":{"start":{"line":15,"column":8},"end":{"line":15,"column":58}},"6":{"start":{"line":15,"column":24},"end":{"line":15,"column":58}},"7":{"start":{"line":16,"column":8},"end":{"line":16,"column":67}},"8":{"start":{"line":16,"column":27},"end":{"line":16,"column":67}},"9":{"start":{"line":17,"column":8},"end":{"line":17,"column":64}},"10":{"start":{"line":17,"column":27},"end":{"line":17,"column":64}},"11":{"start":{"line":18,"column":8},"end":{"line":18,"column":80}},"12":{"start":{"line":18,"column":33},"end":{"line":18,"column":80}},"13":{"start":{"line":20,"column":8},"end":{"line":23,"column":9}},"14":{"start":{"line":21,"column":25},"end":{"line":21,"column":49}},"15":{"start":{"line":22,"column":12},"end":{"line":22,"column":78}},"16":{"start":{"line":25,"column":8},"end":{"line":27,"column":9}},"17":{"start":{"line":26,"column":12},"end":{"line":26,"column":59}},"18":{"start":{"line":29,"column":8},"end":{"line":29,"column":46}},"19":{"start":{"line":31,"column":8},"end":{"line":33,"column":36}},"20":{"start":{"line":35,"column":28},"end":{"line":38,"column":20}},"21":{"start":{"line":40,"column":8},"end":{"line":40,"column":27}},"22":{"start":{"line":44,"column":21},"end":{"line":44,"column":67}},"23":{"start":{"line":46,"column":8},"end":{"line":48,"column":9}},"24":{"start":{"line":47,"column":12},"end":{"line":47,"column":55}},"25":{"start":{"line":50,"column":8},"end":{"line":52,"column":19}},"26":{"start":{"line":54,"column":8},"end":{"line":54,"column":59}},"27":{"start":{"line":60,"column":0},"end":{"line":60,"column":42}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":10,"column":4},"end":{"line":10,"column":9}},"loc":{"start":{"line":10,"column":54},"end":{"line":41,"column":5}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":43,"column":4},"end":{"line":43,"column":9}},"loc":{"start":{"line":43,"column":38},"end":{"line":55,"column":5}}}},"branchMap":{"0":{"loc":{"start":{"line":14,"column":8},"end":{"line":14,"column":75}},"type":"if","locations":[{"start":{"line":14,"column":8},"end":{"line":14,"column":75}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":15,"column":8},"end":{"line":15,"column":58}},"type":"if","locations":[{"start":{"line":15,"column":8},"end":{"line":15,"column":58}},{"start":{},"end":{}}]},"2":{"loc":{"start":{"line":16,"column":8},"end":{"line":16,"column":67}},"type":"if","locations":[{"start":{"line":16,"column":8},"end":{"line":16,"column":67}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":17,"column":8},"end":{"line":17,"column":64}},"type":"if","locations":[{"start":{"line":17,"column":8},"end":{"line":17,"column":64}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":18,"column":8},"end":{"line":18,"column":80}},"type":"if","locations":[{"start":{"line":18,"column":8},"end":{"line":18,"column":80}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":20,"column":8},"end":{"line":23,"column":9}},"type":"if","locations":[{"start":{"line":20,"column":8},"end":{"line":23,"column":9}},{"start":{},"end":{}}]},"6":{"loc":{"start":{"line":25,"column":8},"end":{"line":27,"column":9}},"type":"if","locations":[{"start":{"line":25,"column":8},"end":{"line":27,"column":9}},{"start":{},"end":{}}]},"7":{"loc":{"start":{"line":46,"column":8},"end":{"line":48,"column":9}},"type":"if","locations":[{"start":{"line":46,"column":8},"end":{"line":48,"column":9}},{"start":{},"end":{}}]}},"s":{"0":5,"1":5,"2":3,"3":3,"4":2,"5":3,"6":0,"7":3,"8":0,"9":3,"10":1,"11":3,"12":0,"13":3,"14":0,"15":0,"16":3,"17":1,"18":2,"19":2,"20":2,"21":2,"22":2,"23":2,"24":0,"25":2,"26":2,"27":5},"f":{"0":3,"1":2},"b":{"0":[2,1],"1":[0,3],"2":[0,3],"3":[1,2],"4":[0,3],"5":[0,3],"6":[1,2],"7":[0,2]}} +,"/home/cecilia/Documents/CTable/backend/src/business/businessLogicProject.ts": {"path":"/home/cecilia/Documents/CTable/backend/src/business/businessLogicProject.ts","statementMap":{"0":{"start":{"line":2,"column":0},"end":{"line":2,"column":33}},"1":{"start":{"line":9,"column":7},"end":{"line":60,"column":11}},"2":{"start":{"line":11,"column":36},"end":{"line":17,"column":14}},"3":{"start":{"line":19,"column":33},"end":{"line":21,"column":55}},"4":{"start":{"line":23,"column":12},"end":{"line":57,"column":13}},"5":{"start":{"line":25,"column":35},"end":{"line":27,"column":60}},"6":{"start":{"line":29,"column":41},"end":{"line":34,"column":18}},"7":{"start":{"line":30,"column":20},"end":{"line":33,"column":22}},"8":{"start":{"line":36,"column":16},"end":{"line":56,"column":17}},"9":{"start":{"line":37,"column":20},"end":{"line":37,"column":75}},"10":{"start":{"line":43,"column":48},"end":{"line":45,"column":48}},"11":{"start":{"line":44,"column":66},"end":{"line":44,"column":77}},"12":{"start":{"line":47,"column":20},"end":{"line":55,"column":21}},"13":{"start":{"line":48,"column":50},"end":{"line":52,"column":27}},"14":{"start":{"line":48,"column":83},"end":{"line":52,"column":26}},"15":{"start":{"line":54,"column":24},"end":{"line":54,"column":82}},"16":{"start":{"line":59,"column":12},"end":{"line":59,"column":30}},"17":{"start":{"line":65,"column":8},"end":{"line":134,"column":11}},"18":{"start":{"line":67,"column":36},"end":{"line":69,"column":24}},"19":{"start":{"line":71,"column":12},"end":{"line":73,"column":13}},"20":{"start":{"line":72,"column":16},"end":{"line":72,"column":59}},"21":{"start":{"line":75,"column":12},"end":{"line":77,"column":13}},"22":{"start":{"line":76,"column":16},"end":{"line":76,"column":84}},"23":{"start":{"line":79,"column":40},"end":{"line":79,"column":42}},"24":{"start":{"line":80,"column":12},"end":{"line":80,"column":90}},"25":{"start":{"line":80,"column":49},"end":{"line":80,"column":90}},"26":{"start":{"line":81,"column":12},"end":{"line":81,"column":108}},"27":{"start":{"line":81,"column":55},"end":{"line":81,"column":108}},"28":{"start":{"line":82,"column":12},"end":{"line":82,"column":93}},"29":{"start":{"line":82,"column":50},"end":{"line":82,"column":93}},"30":{"start":{"line":83,"column":12},"end":{"line":83,"column":102}},"31":{"start":{"line":83,"column":53},"end":{"line":83,"column":102}},"32":{"start":{"line":85,"column":12},"end":{"line":90,"column":13}},"33":{"start":{"line":86,"column":16},"end":{"line":86,"column":54}},"34":{"start":{"line":87,"column":16},"end":{"line":89,"column":44}},"35":{"start":{"line":92,"column":12},"end":{"line":131,"column":13}},"36":{"start":{"line":94,"column":16},"end":{"line":96,"column":27}},"37":{"start":{"line":98,"column":16},"end":{"line":100,"column":27}},"38":{"start":{"line":102,"column":16},"end":{"line":130,"column":17}},"39":{"start":{"line":104,"column":39},"end":{"line":106,"column":44}},"40":{"start":{"line":108,"column":45},"end":{"line":111,"column":23}},"41":{"start":{"line":108,"column":73},"end":{"line":111,"column":22}},"42":{"start":{"line":113,"column":20},"end":{"line":115,"column":21}},"43":{"start":{"line":114,"column":24},"end":{"line":114,"column":79}},"44":{"start":{"line":117,"column":48},"end":{"line":119,"column":48}},"45":{"start":{"line":118,"column":72},"end":{"line":118,"column":83}},"46":{"start":{"line":121,"column":20},"end":{"line":129,"column":21}},"47":{"start":{"line":122,"column":50},"end":{"line":126,"column":27}},"48":{"start":{"line":122,"column":89},"end":{"line":126,"column":26}},"49":{"start":{"line":128,"column":24},"end":{"line":128,"column":82}},"50":{"start":{"line":133,"column":12},"end":{"line":133,"column":81}},"51":{"start":{"line":139,"column":25},"end":{"line":140,"column":54}},"52":{"start":{"line":142,"column":8},"end":{"line":142,"column":24}},"53":{"start":{"line":147,"column":24},"end":{"line":147,"column":84}},"54":{"start":{"line":149,"column":8},"end":{"line":149,"column":65}},"55":{"start":{"line":149,"column":22},"end":{"line":149,"column":65}},"56":{"start":{"line":151,"column":29},"end":{"line":156,"column":25}},"57":{"start":{"line":158,"column":8},"end":{"line":158,"column":26}},"58":{"start":{"line":162,"column":25},"end":{"line":170,"column":50}},"59":{"start":{"line":172,"column":8},"end":{"line":172,"column":24}},"60":{"start":{"line":176,"column":25},"end":{"line":184,"column":50}},"61":{"start":{"line":186,"column":8},"end":{"line":186,"column":24}},"62":{"start":{"line":191,"column":24},"end":{"line":193,"column":20}},"63":{"start":{"line":195,"column":8},"end":{"line":197,"column":9}},"64":{"start":{"line":196,"column":12},"end":{"line":196,"column":58}},"65":{"start":{"line":199,"column":8},"end":{"line":201,"column":9}},"66":{"start":{"line":200,"column":12},"end":{"line":200,"column":84}},"67":{"start":{"line":203,"column":8},"end":{"line":205,"column":19}},"68":{"start":{"line":211,"column":24},"end":{"line":213,"column":20}},"69":{"start":{"line":215,"column":8},"end":{"line":217,"column":9}},"70":{"start":{"line":216,"column":12},"end":{"line":216,"column":55}},"71":{"start":{"line":219,"column":8},"end":{"line":221,"column":9}},"72":{"start":{"line":220,"column":12},"end":{"line":220,"column":81}},"73":{"start":{"line":223,"column":8},"end":{"line":225,"column":19}},"74":{"start":{"line":230,"column":24},"end":{"line":239,"column":20}},"75":{"start":{"line":241,"column":8},"end":{"line":243,"column":9}},"76":{"start":{"line":242,"column":12},"end":{"line":242,"column":55}},"77":{"start":{"line":246,"column":25},"end":{"line":249,"column":35}},"78":{"start":{"line":252,"column":8},"end":{"line":255,"column":10}},"79":{"start":{"line":254,"column":51},"end":{"line":254,"column":56}},"80":{"start":{"line":260,"column":0},"end":{"line":260,"column":42}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":7,"column":4},"end":{"line":7,"column":9}},"loc":{"start":{"line":7,"column":57},"end":{"line":61,"column":5}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":9,"column":31},"end":{"line":9,"column":36}},"loc":{"start":{"line":9,"column":45},"end":{"line":60,"column":9}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":29,"column":56},"end":{"line":29,"column":63}},"loc":{"start":{"line":29,"column":66},"end":{"line":34,"column":17}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":44,"column":61},"end":{"line":44,"column":62}},"loc":{"start":{"line":44,"column":66},"end":{"line":44,"column":77}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":48,"column":74},"end":{"line":48,"column":78}},"loc":{"start":{"line":48,"column":83},"end":{"line":52,"column":26}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":63,"column":4},"end":{"line":63,"column":9}},"loc":{"start":{"line":63,"column":84},"end":{"line":135,"column":5}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":65,"column":32},"end":{"line":65,"column":37}},"loc":{"start":{"line":65,"column":46},"end":{"line":134,"column":9}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":108,"column":60},"end":{"line":108,"column":61}},"loc":{"start":{"line":108,"column":73},"end":{"line":111,"column":22}}},"8":{"name":"(anonymous_9)","decl":{"start":{"line":118,"column":61},"end":{"line":118,"column":62}},"loc":{"start":{"line":118,"column":72},"end":{"line":118,"column":83}}},"9":{"name":"(anonymous_10)","decl":{"start":{"line":122,"column":74},"end":{"line":122,"column":75}},"loc":{"start":{"line":122,"column":89},"end":{"line":126,"column":26}}},"10":{"name":"(anonymous_11)","decl":{"start":{"line":137,"column":4},"end":{"line":137,"column":9}},"loc":{"start":{"line":137,"column":40},"end":{"line":143,"column":5}}},"11":{"name":"(anonymous_12)","decl":{"start":{"line":145,"column":4},"end":{"line":145,"column":9}},"loc":{"start":{"line":145,"column":71},"end":{"line":159,"column":5}}},"12":{"name":"(anonymous_13)","decl":{"start":{"line":161,"column":4},"end":{"line":161,"column":9}},"loc":{"start":{"line":161,"column":46},"end":{"line":173,"column":5}}},"13":{"name":"(anonymous_14)","decl":{"start":{"line":175,"column":4},"end":{"line":175,"column":9}},"loc":{"start":{"line":175,"column":40},"end":{"line":187,"column":5}}},"14":{"name":"(anonymous_15)","decl":{"start":{"line":189,"column":4},"end":{"line":189,"column":9}},"loc":{"start":{"line":189,"column":57},"end":{"line":207,"column":5}}},"15":{"name":"(anonymous_16)","decl":{"start":{"line":209,"column":4},"end":{"line":209,"column":9}},"loc":{"start":{"line":209,"column":60},"end":{"line":226,"column":5}}},"16":{"name":"(anonymous_17)","decl":{"start":{"line":228,"column":4},"end":{"line":228,"column":9}},"loc":{"start":{"line":228,"column":42},"end":{"line":256,"column":5}}},"17":{"name":"(anonymous_18)","decl":{"start":{"line":254,"column":39},"end":{"line":254,"column":40}},"loc":{"start":{"line":254,"column":51},"end":{"line":254,"column":56}}}},"branchMap":{"0":{"loc":{"start":{"line":23,"column":12},"end":{"line":57,"column":13}},"type":"if","locations":[{"start":{"line":23,"column":12},"end":{"line":57,"column":13}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":23,"column":16},"end":{"line":23,"column":65}},"type":"binary-expr","locations":[{"start":{"line":23,"column":16},"end":{"line":23,"column":33}},{"start":{"line":23,"column":37},"end":{"line":23,"column":65}}]},"2":{"loc":{"start":{"line":36,"column":16},"end":{"line":56,"column":17}},"type":"if","locations":[{"start":{"line":36,"column":16},"end":{"line":56,"column":17}},{"start":{},"end":{}}]},"3":{"loc":{"start":{"line":47,"column":20},"end":{"line":55,"column":21}},"type":"if","locations":[{"start":{"line":47,"column":20},"end":{"line":55,"column":21}},{"start":{},"end":{}}]},"4":{"loc":{"start":{"line":71,"column":12},"end":{"line":73,"column":13}},"type":"if","locations":[{"start":{"line":71,"column":12},"end":{"line":73,"column":13}},{"start":{},"end":{}}]},"5":{"loc":{"start":{"line":75,"column":12},"end":{"line":77,"column":13}},"type":"if","locations":[{"start":{"line":75,"column":12},"end":{"line":77,"column":13}},{"start":{},"end":{}}]},"6":{"loc":{"start":{"line":80,"column":12},"end":{"line":80,"column":90}},"type":"if","locations":[{"start":{"line":80,"column":12},"end":{"line":80,"column":90}},{"start":{},"end":{}}]},"7":{"loc":{"start":{"line":81,"column":12},"end":{"line":81,"column":108}},"type":"if","locations":[{"start":{"line":81,"column":12},"end":{"line":81,"column":108}},{"start":{},"end":{}}]},"8":{"loc":{"start":{"line":82,"column":12},"end":{"line":82,"column":93}},"type":"if","locations":[{"start":{"line":82,"column":12},"end":{"line":82,"column":93}},{"start":{},"end":{}}]},"9":{"loc":{"start":{"line":83,"column":12},"end":{"line":83,"column":102}},"type":"if","locations":[{"start":{"line":83,"column":12},"end":{"line":83,"column":102}},{"start":{},"end":{}}]},"10":{"loc":{"start":{"line":85,"column":12},"end":{"line":90,"column":13}},"type":"if","locations":[{"start":{"line":85,"column":12},"end":{"line":90,"column":13}},{"start":{},"end":{}}]},"11":{"loc":{"start":{"line":92,"column":12},"end":{"line":131,"column":13}},"type":"if","locations":[{"start":{"line":92,"column":12},"end":{"line":131,"column":13}},{"start":{},"end":{}}]},"12":{"loc":{"start":{"line":102,"column":16},"end":{"line":130,"column":17}},"type":"if","locations":[{"start":{"line":102,"column":16},"end":{"line":130,"column":17}},{"start":{},"end":{}}]},"13":{"loc":{"start":{"line":102,"column":20},"end":{"line":102,"column":98}},"type":"binary-expr","locations":[{"start":{"line":102,"column":20},"end":{"line":102,"column":59}},{"start":{"line":102,"column":63},"end":{"line":102,"column":98}}]},"14":{"loc":{"start":{"line":113,"column":20},"end":{"line":115,"column":21}},"type":"if","locations":[{"start":{"line":113,"column":20},"end":{"line":115,"column":21}},{"start":{},"end":{}}]},"15":{"loc":{"start":{"line":121,"column":20},"end":{"line":129,"column":21}},"type":"if","locations":[{"start":{"line":121,"column":20},"end":{"line":129,"column":21}},{"start":{},"end":{}}]},"16":{"loc":{"start":{"line":149,"column":8},"end":{"line":149,"column":65}},"type":"if","locations":[{"start":{"line":149,"column":8},"end":{"line":149,"column":65}},{"start":{},"end":{}}]},"17":{"loc":{"start":{"line":195,"column":8},"end":{"line":197,"column":9}},"type":"if","locations":[{"start":{"line":195,"column":8},"end":{"line":197,"column":9}},{"start":{},"end":{}}]},"18":{"loc":{"start":{"line":199,"column":8},"end":{"line":201,"column":9}},"type":"if","locations":[{"start":{"line":199,"column":8},"end":{"line":201,"column":9}},{"start":{},"end":{}}]},"19":{"loc":{"start":{"line":215,"column":8},"end":{"line":217,"column":9}},"type":"if","locations":[{"start":{"line":215,"column":8},"end":{"line":217,"column":9}},{"start":{},"end":{}}]},"20":{"loc":{"start":{"line":219,"column":8},"end":{"line":221,"column":9}},"type":"if","locations":[{"start":{"line":219,"column":8},"end":{"line":221,"column":9}},{"start":{},"end":{}}]},"21":{"loc":{"start":{"line":241,"column":8},"end":{"line":243,"column":9}},"type":"if","locations":[{"start":{"line":241,"column":8},"end":{"line":243,"column":9}},{"start":{},"end":{}}]}},"s":{"0":5,"1":17,"2":17,"3":17,"4":17,"5":3,"6":3,"7":5,"8":3,"9":3,"10":3,"11":5,"12":3,"13":1,"14":1,"15":1,"16":17,"17":2,"18":2,"19":2,"20":0,"21":2,"22":1,"23":1,"24":1,"25":1,"26":1,"27":1,"28":1,"29":0,"30":1,"31":0,"32":1,"33":1,"34":1,"35":1,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":1,"51":4,"52":4,"53":9,"54":9,"55":0,"56":9,"57":9,"58":2,"59":2,"60":3,"61":3,"62":2,"63":2,"64":0,"65":2,"66":1,"67":1,"68":2,"69":2,"70":0,"71":2,"72":1,"73":1,"74":3,"75":3,"76":2,"77":1,"78":1,"79":2,"80":5},"f":{"0":17,"1":17,"2":5,"3":5,"4":1,"5":2,"6":2,"7":0,"8":0,"9":0,"10":4,"11":9,"12":2,"13":3,"14":2,"15":2,"16":3,"17":2},"b":{"0":[3,14],"1":[17,3],"2":[3,0],"3":[1,2],"4":[0,2],"5":[1,1],"6":[1,0],"7":[1,0],"8":[0,1],"9":[0,1],"10":[1,0],"11":[0,1],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[0,9],"17":[0,2],"18":[1,1],"19":[0,2],"20":[1,1],"21":[2,1]}} +,"/home/cecilia/Documents/CTable/backend/src/controller/requestController.ts": {"path":"/home/cecilia/Documents/CTable/backend/src/controller/requestController.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":62}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":68}},"2":{"start":{"line":5,"column":0},"end":{"line":5,"column":31}},"3":{"start":{"line":6,"column":0},"end":{"line":6,"column":43}},"4":{"start":{"line":7,"column":0},"end":{"line":7,"column":27}},"5":{"start":{"line":9,"column":0},"end":{"line":9,"column":72}},"6":{"start":{"line":10,"column":0},"end":{"line":10,"column":68}},"7":{"start":{"line":11,"column":0},"end":{"line":11,"column":72}},"8":{"start":{"line":13,"column":0},"end":{"line":13,"column":68}},"9":{"start":{"line":18,"column":8},"end":{"line":34,"column":9}},"10":{"start":{"line":20,"column":29},"end":{"line":20,"column":66}},"11":{"start":{"line":22,"column":28},"end":{"line":22,"column":76}},"12":{"start":{"line":24,"column":26},"end":{"line":27,"column":null}},"13":{"start":{"line":30,"column":12},"end":{"line":30,"column":52}},"14":{"start":{"line":33,"column":12},"end":{"line":33,"column":24}},"15":{"start":{"line":38,"column":8},"end":{"line":55,"column":9}},"16":{"start":{"line":40,"column":29},"end":{"line":40,"column":68}},"17":{"start":{"line":42,"column":28},"end":{"line":42,"column":76}},"18":{"start":{"line":44,"column":26},"end":{"line":47,"column":null}},"19":{"start":{"line":50,"column":12},"end":{"line":50,"column":52}},"20":{"start":{"line":54,"column":12},"end":{"line":54,"column":24}},"21":{"start":{"line":59,"column":8},"end":{"line":69,"column":9}},"22":{"start":{"line":60,"column":12},"end":{"line":60,"column":30}},"23":{"start":{"line":61,"column":31},"end":{"line":61,"column":85}},"24":{"start":{"line":63,"column":12},"end":{"line":63,"column":30}},"25":{"start":{"line":67,"column":12},"end":{"line":67,"column":58}},"26":{"start":{"line":73,"column":8},"end":{"line":84,"column":9}},"27":{"start":{"line":75,"column":29},"end":{"line":75,"column":65}},"28":{"start":{"line":77,"column":25},"end":{"line":77,"column":51}},"29":{"start":{"line":77,"column":44},"end":{"line":77,"column":50}},"30":{"start":{"line":79,"column":12},"end":{"line":79,"column":24}},"31":{"start":{"line":82,"column":12},"end":{"line":82,"column":61}},"32":{"start":{"line":83,"column":12},"end":{"line":83,"column":68}},"33":{"start":{"line":88,"column":8},"end":{"line":96,"column":9}},"34":{"start":{"line":90,"column":29},"end":{"line":90,"column":79}},"35":{"start":{"line":92,"column":12},"end":{"line":92,"column":28}},"36":{"start":{"line":95,"column":12},"end":{"line":95,"column":70}},"37":{"start":{"line":100,"column":8},"end":{"line":108,"column":9}},"38":{"start":{"line":102,"column":35},"end":{"line":102,"column":100}},"39":{"start":{"line":104,"column":12},"end":{"line":104,"column":34}},"40":{"start":{"line":107,"column":12},"end":{"line":107,"column":60}},"41":{"start":{"line":112,"column":8},"end":{"line":118,"column":9}},"42":{"start":{"line":114,"column":12},"end":{"line":114,"column":72}},"43":{"start":{"line":117,"column":12},"end":{"line":117,"column":24}},"44":{"start":{"line":122,"column":8},"end":{"line":127,"column":9}},"45":{"start":{"line":123,"column":28},"end":{"line":123,"column":80}},"46":{"start":{"line":124,"column":12},"end":{"line":124,"column":27}},"47":{"start":{"line":126,"column":12},"end":{"line":126,"column":24}},"48":{"start":{"line":131,"column":8},"end":{"line":138,"column":9}},"49":{"start":{"line":133,"column":33},"end":{"line":133,"column":91}},"50":{"start":{"line":134,"column":12},"end":{"line":134,"column":32}},"51":{"start":{"line":137,"column":12},"end":{"line":137,"column":24}},"52":{"start":{"line":142,"column":8},"end":{"line":148,"column":9}},"53":{"start":{"line":143,"column":32},"end":{"line":143,"column":90}},"54":{"start":{"line":144,"column":12},"end":{"line":144,"column":31}},"55":{"start":{"line":146,"column":12},"end":{"line":146,"column":64}},"56":{"start":{"line":147,"column":12},"end":{"line":147,"column":64}},"57":{"start":{"line":152,"column":8},"end":{"line":164,"column":9}},"58":{"start":{"line":153,"column":32},"end":{"line":153,"column":90}},"59":{"start":{"line":155,"column":25},"end":{"line":155,"column":73}},"60":{"start":{"line":157,"column":12},"end":{"line":160,"column":14}},"61":{"start":{"line":163,"column":12},"end":{"line":163,"column":24}},"62":{"start":{"line":167,"column":8},"end":{"line":175,"column":9}},"63":{"start":{"line":169,"column":32},"end":{"line":169,"column":80}},"64":{"start":{"line":171,"column":12},"end":{"line":171,"column":31}},"65":{"start":{"line":174,"column":12},"end":{"line":174,"column":24}},"66":{"start":{"line":180,"column":8},"end":{"line":188,"column":9}},"67":{"start":{"line":182,"column":27},"end":{"line":182,"column":92}},"68":{"start":{"line":184,"column":12},"end":{"line":184,"column":26}},"69":{"start":{"line":187,"column":12},"end":{"line":187,"column":24}},"70":{"start":{"line":192,"column":8},"end":{"line":199,"column":9}},"71":{"start":{"line":194,"column":27},"end":{"line":194,"column":95}},"72":{"start":{"line":195,"column":12},"end":{"line":195,"column":26}},"73":{"start":{"line":198,"column":12},"end":{"line":198,"column":24}},"74":{"start":{"line":203,"column":8},"end":{"line":211,"column":9}},"75":{"start":{"line":205,"column":26},"end":{"line":205,"column":96}},"76":{"start":{"line":207,"column":12},"end":{"line":207,"column":26}},"77":{"start":{"line":210,"column":12},"end":{"line":210,"column":24}},"78":{"start":{"line":216,"column":8},"end":{"line":224,"column":9}},"79":{"start":{"line":218,"column":37},"end":{"line":218,"column":111}},"80":{"start":{"line":220,"column":12},"end":{"line":220,"column":36}},"81":{"start":{"line":223,"column":12},"end":{"line":223,"column":24}},"82":{"start":{"line":228,"column":8},"end":{"line":234,"column":9}},"83":{"start":{"line":230,"column":12},"end":{"line":230,"column":81}},"84":{"start":{"line":233,"column":12},"end":{"line":233,"column":24}},"85":{"start":{"line":238,"column":8},"end":{"line":250,"column":9}},"86":{"start":{"line":240,"column":12},"end":{"line":242,"column":13}},"87":{"start":{"line":241,"column":16},"end":{"line":241,"column":68}},"88":{"start":{"line":244,"column":28},"end":{"line":244,"column":93}},"89":{"start":{"line":246,"column":12},"end":{"line":246,"column":27}},"90":{"start":{"line":249,"column":12},"end":{"line":249,"column":24}},"91":{"start":{"line":254,"column":8},"end":{"line":262,"column":9}},"92":{"start":{"line":256,"column":36},"end":{"line":256,"column":92}},"93":{"start":{"line":258,"column":12},"end":{"line":258,"column":35}},"94":{"start":{"line":261,"column":12},"end":{"line":261,"column":24}},"95":{"start":{"line":266,"column":8},"end":{"line":274,"column":9}},"96":{"start":{"line":268,"column":27},"end":{"line":268,"column":81}},"97":{"start":{"line":270,"column":12},"end":{"line":270,"column":26}},"98":{"start":{"line":273,"column":12},"end":{"line":273,"column":24}},"99":{"start":{"line":279,"column":8},"end":{"line":286,"column":9}},"100":{"start":{"line":281,"column":28},"end":{"line":281,"column":76}},"101":{"start":{"line":282,"column":12},"end":{"line":282,"column":27}},"102":{"start":{"line":285,"column":12},"end":{"line":285,"column":24}},"103":{"start":{"line":291,"column":8},"end":{"line":297,"column":9}},"104":{"start":{"line":293,"column":12},"end":{"line":293,"column":72}},"105":{"start":{"line":296,"column":12},"end":{"line":296,"column":24}},"106":{"start":{"line":301,"column":8},"end":{"line":309,"column":9}},"107":{"start":{"line":303,"column":32},"end":{"line":303,"column":82}},"108":{"start":{"line":305,"column":12},"end":{"line":305,"column":31}},"109":{"start":{"line":308,"column":12},"end":{"line":308,"column":24}},"110":{"start":{"line":314,"column":0},"end":{"line":314,"column":39}}},"fnMap":{"0":{"name":"(anonymous_1)","decl":{"start":{"line":17,"column":4},"end":{"line":17,"column":9}},"loc":{"start":{"line":17,"column":35},"end":{"line":35,"column":5}}},"1":{"name":"(anonymous_2)","decl":{"start":{"line":37,"column":4},"end":{"line":37,"column":9}},"loc":{"start":{"line":37,"column":35},"end":{"line":56,"column":5}}},"2":{"name":"(anonymous_3)","decl":{"start":{"line":58,"column":4},"end":{"line":58,"column":9}},"loc":{"start":{"line":58,"column":60},"end":{"line":70,"column":5}}},"3":{"name":"(anonymous_4)","decl":{"start":{"line":72,"column":4},"end":{"line":72,"column":9}},"loc":{"start":{"line":72,"column":21},"end":{"line":85,"column":5}}},"4":{"name":"(anonymous_5)","decl":{"start":{"line":77,"column":38},"end":{"line":77,"column":40}},"loc":{"start":{"line":77,"column":44},"end":{"line":77,"column":50}}},"5":{"name":"(anonymous_6)","decl":{"start":{"line":87,"column":4},"end":{"line":87,"column":9}},"loc":{"start":{"line":87,"column":43},"end":{"line":97,"column":5}}},"6":{"name":"(anonymous_7)","decl":{"start":{"line":99,"column":4},"end":{"line":99,"column":9}},"loc":{"start":{"line":99,"column":76},"end":{"line":109,"column":5}}},"7":{"name":"(anonymous_8)","decl":{"start":{"line":111,"column":4},"end":{"line":111,"column":9}},"loc":{"start":{"line":111,"column":57},"end":{"line":119,"column":5}}},"8":{"name":"(anonymous_9)","decl":{"start":{"line":121,"column":4},"end":{"line":121,"column":9}},"loc":{"start":{"line":121,"column":42},"end":{"line":128,"column":5}}},"9":{"name":"(anonymous_10)","decl":{"start":{"line":130,"column":4},"end":{"line":130,"column":9}},"loc":{"start":{"line":130,"column":61},"end":{"line":139,"column":5}}},"10":{"name":"(anonymous_11)","decl":{"start":{"line":141,"column":4},"end":{"line":141,"column":9}},"loc":{"start":{"line":141,"column":46},"end":{"line":149,"column":5}}},"11":{"name":"(anonymous_12)","decl":{"start":{"line":151,"column":4},"end":{"line":151,"column":9}},"loc":{"start":{"line":151,"column":36},"end":{"line":165,"column":5}}},"12":{"name":"(anonymous_13)","decl":{"start":{"line":166,"column":4},"end":{"line":166,"column":9}},"loc":{"start":{"line":166,"column":27},"end":{"line":177,"column":5}}},"13":{"name":"(anonymous_14)","decl":{"start":{"line":179,"column":4},"end":{"line":179,"column":9}},"loc":{"start":{"line":179,"column":62},"end":{"line":189,"column":5}}},"14":{"name":"(anonymous_15)","decl":{"start":{"line":191,"column":4},"end":{"line":191,"column":9}},"loc":{"start":{"line":191,"column":64},"end":{"line":200,"column":5}}},"15":{"name":"(anonymous_16)","decl":{"start":{"line":202,"column":4},"end":{"line":202,"column":9}},"loc":{"start":{"line":202,"column":66},"end":{"line":213,"column":5}}},"16":{"name":"(anonymous_17)","decl":{"start":{"line":215,"column":4},"end":{"line":215,"column":9}},"loc":{"start":{"line":215,"column":85},"end":{"line":225,"column":5}}},"17":{"name":"(anonymous_18)","decl":{"start":{"line":227,"column":4},"end":{"line":227,"column":9}},"loc":{"start":{"line":227,"column":64},"end":{"line":235,"column":5}}},"18":{"name":"(anonymous_19)","decl":{"start":{"line":237,"column":4},"end":{"line":237,"column":9}},"loc":{"start":{"line":237,"column":71},"end":{"line":251,"column":5}}},"19":{"name":"(anonymous_20)","decl":{"start":{"line":253,"column":4},"end":{"line":253,"column":9}},"loc":{"start":{"line":253,"column":46},"end":{"line":263,"column":5}}},"20":{"name":"(anonymous_21)","decl":{"start":{"line":265,"column":4},"end":{"line":265,"column":9}},"loc":{"start":{"line":265,"column":54},"end":{"line":276,"column":5}}},"21":{"name":"(anonymous_22)","decl":{"start":{"line":278,"column":4},"end":{"line":278,"column":9}},"loc":{"start":{"line":278,"column":38},"end":{"line":288,"column":5}}},"22":{"name":"(anonymous_23)","decl":{"start":{"line":290,"column":4},"end":{"line":290,"column":9}},"loc":{"start":{"line":290,"column":57},"end":{"line":298,"column":5}}},"23":{"name":"(anonymous_24)","decl":{"start":{"line":300,"column":4},"end":{"line":300,"column":9}},"loc":{"start":{"line":300,"column":40},"end":{"line":310,"column":5}}}},"branchMap":{"0":{"loc":{"start":{"line":240,"column":12},"end":{"line":242,"column":13}},"type":"if","locations":[{"start":{"line":240,"column":12},"end":{"line":242,"column":13}},{"start":{},"end":{}}]},"1":{"loc":{"start":{"line":240,"column":16},"end":{"line":240,"column":49}},"type":"binary-expr","locations":[{"start":{"line":240,"column":16},"end":{"line":240,"column":24}},{"start":{"line":240,"column":28},"end":{"line":240,"column":49}}]}},"s":{"0":5,"1":5,"2":5,"3":5,"4":5,"5":5,"6":5,"7":5,"8":5,"9":82,"10":82,"11":80,"12":80,"13":80,"14":2,"15":77,"16":77,"17":75,"18":75,"19":75,"20":2,"21":17,"22":17,"23":17,"24":17,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":4,"34":4,"35":4,"36":0,"37":2,"38":2,"39":1,"40":1,"41":2,"42":2,"43":1,"44":3,"45":3,"46":1,"47":2,"48":17,"49":17,"50":15,"51":2,"52":0,"53":0,"54":0,"55":0,"56":0,"57":1,"58":1,"59":1,"60":1,"61":0,"62":1,"63":1,"64":1,"65":0,"66":1,"67":1,"68":1,"69":0,"70":4,"71":4,"72":3,"73":1,"74":3,"75":3,"76":1,"77":2,"78":3,"79":3,"80":1,"81":2,"82":1,"83":1,"84":1,"85":9,"86":9,"87":0,"88":9,"89":9,"90":0,"91":2,"92":2,"93":2,"94":0,"95":3,"96":3,"97":2,"98":1,"99":2,"100":2,"101":2,"102":0,"103":2,"104":2,"105":1,"106":3,"107":3,"108":3,"109":0,"110":5},"f":{"0":82,"1":77,"2":17,"3":0,"4":0,"5":4,"6":2,"7":2,"8":3,"9":17,"10":0,"11":1,"12":1,"13":1,"14":4,"15":3,"16":3,"17":1,"18":9,"19":2,"20":3,"21":2,"22":2,"23":3},"b":{"0":[0,9],"1":[9,9]}} +,"/home/cecilia/Documents/CTable/backend/src/utils/validationUser.ts": {"path":"/home/cecilia/Documents/CTable/backend/src/utils/validationUser.ts","statementMap":{"0":{"start":{"line":13,"column":0},"end":{"line":13,"column":16}},"1":{"start":{"line":1,"column":0},"end":{"line":1,"column":24}},"2":{"start":{"line":4,"column":19},"end":{"line":10,"column":2}},"3":{"start":{"line":14,"column":4},"end":{"line":14,"column":27}}},"fnMap":{"0":{"name":"userValidate","decl":{"start":{"line":13,"column":16},"end":{"line":13,"column":28}},"loc":{"start":{"line":13,"column":43},"end":{"line":15,"column":1}}}},"branchMap":{},"s":{"0":5,"1":5,"2":5,"3":82},"f":{"0":82},"b":{}} +} diff --git a/backend/src/coverage/lcov-report/index.html b/backend/src/coverage/lcov-report/index.html new file mode 100644 index 0000000..a96b1d5 --- /dev/null +++ b/backend/src/coverage/lcov-report/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 84.84% + Statements + 392/462 +
+ + +
+ 65.11% + Branches + 84/129 +
+ + +
+ 84.37% + Functions + 81/96 +
+ + +
+ 86.78% + Lines + 381/439 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src +
+
95.45%105/110100%0/092.59%25/2795.45%105/110
src/business +
+
81.85%194/23764.8%81/12577.27%34/4485.11%183/215
src/controller +
+
80.18%89/11175%3/487.5%21/2480.9%89/110
src/utils +
+
100%4/4100%0/0100%1/1100%4/4
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/app.ts.html b/backend/src/coverage/lcov-report/src/app.ts.html new file mode 100644 index 0000000..269496b --- /dev/null +++ b/backend/src/coverage/lcov-report/src/app.ts.html @@ -0,0 +1,172 @@ + + + + + + Code coverage report for src/app.ts + + + + + + + + + +
+
+

All files / src app.ts

+
+ +
+ 100% + Statements + 13/13 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 13/13 +
+ + +
+

+ 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 +305x +5x +5x +5x +  +  +  +  +  +5x +5x +5x +5x +  +  +  +5x +5x +  +  +  +5x +  +  +  +5x +  +  +  +5x
import express from 'express';
+import cors from 'cors';
+import routes from './routes';
+import { errorHandler } from './middleware/errorHandler';
+ 
+class App {
+    public server: express.Application;
+ 
+    constructor() {
+        this.server = express();
+        this.middlewares();
+        this.routes();
+        this.handleErrors();
+    }
+ 
+    private middlewares(): void {
+        this.server.use(express.json());
+        this.server.use(cors()); 
+    }
+ 
+    private routes(): void {
+        this.server.use(routes);
+    }
+ 
+    private handleErrors(): void {
+        this.server.use(errorHandler);
+    }
+}
+ 
+export default new App().server;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/business/businessLogicAuth.ts.html b/backend/src/coverage/lcov-report/src/business/businessLogicAuth.ts.html new file mode 100644 index 0000000..779a6e9 --- /dev/null +++ b/backend/src/coverage/lcov-report/src/business/businessLogicAuth.ts.html @@ -0,0 +1,346 @@ + + + + + + Code coverage report for src/business/businessLogicAuth.ts + + + + + + + + + +
+
+

All files / src/business businessLogicAuth.ts

+
+ +
+ 100% + Statements + 28/28 +
+ + +
+ 90% + Branches + 9/10 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 100% + Lines + 28/28 +
+ + +
+

+ 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  +  +5x +5x +5x +  +  +  +  +  +  +  +82x +  +82x +  +  +  +  +82x +2x +1x +  +1x +1x +  +  +  +80x +  +80x +  +80x +  +  +80x +  +  +  +  +  +  +  +  +80x +  +  +  +80x +  +80x +  +  +  +  +77x +77x +  +  +  +77x +1x +  +  +76x +  +  +  +  +76x +1x +  +  +75x +  +75x +  +  +  +2x +  +  +  +  +  +  +  +5x
 
+import { UserData, LoginData } from "../models/User";
+import { userValidate } from "../utils/validationUser";
+import knex from '../data/index'; 
+import bcrypt from 'bcryptjs';
+ 
+ 
+ 
+class BusinessLogicAuth{
+ 
+    async newUser(data: UserData){
+ 
+        userValidate(data);
+ 
+        const existingUser = await knex('User')
+                .where('username', data.username)
+                .orWhere('email', data.email)
+                .first();
+ 
+        if (existingUser) {
+            if (existingUser.username === data.username) {
+                throw new Error('Este username já está em uso.');
+            }
+            Eif (existingUser.email === data.email) {
+                throw new Error('Este e-mail já está em uso.');
+            }
+        }
+ 
+        const salt = await bcrypt.genSalt(10);
+ 
+        const senhaHash = await bcrypt.hash(data.senha, salt); 
+ 
+        const { nomeCompleto, username, email, telefone, dataNascimento } = data;
+ 
+ 
+        await knex('User').insert({
+            fullName: nomeCompleto,
+            username,
+            email,
+            phone: telefone,
+            birthDate: dataNascimento,
+            passwordHash: senhaHash
+        });
+ 
+        const user = await knex('User')
+                    .where('username', data.username)
+                    .first();
+ 
+        const { passwordHash, ...userData} = user;
+ 
+        return userData;
+ 
+    }
+ 
+    async enterUser(data: LoginData){
+        try{
+            const user = await knex('User')
+                    .where('username', data.username)
+                    .first();
+            
+            if(!user){
+                throw new Error('Usuário ou senha incorretos.');
+            }
+ 
+            const isPasswordValid = await bcrypt.compare(
+                data.senha,     
+                user.passwordHash  
+            );
+ 
+            if (!isPasswordValid) {
+                throw new Error('Usuário ou senha incorretos.');
+            }
+ 
+            const { passwordHash, ...userData } = user;
+            
+            return userData;
+ 
+        }catch(error){
+ 
+            throw error;
+            
+        }
+    }
+ 
+}
+ 
+ 
+export default new BusinessLogicAuth();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/business/businessLogicCommunity.ts.html b/backend/src/coverage/lcov-report/src/business/businessLogicCommunity.ts.html new file mode 100644 index 0000000..a46fe3f --- /dev/null +++ b/backend/src/coverage/lcov-report/src/business/businessLogicCommunity.ts.html @@ -0,0 +1,1024 @@ + + + + + + Code coverage report for src/business/businessLogicCommunity.ts + + + + + + + + + +
+
+

All files / src/business businessLogicCommunity.ts

+
+ +
+ 83% + Statements + 83/100 +
+ + +
+ 65.45% + Branches + 36/55 +
+ + +
+ 68.18% + Functions + 15/22 +
+ + +
+ 84.61% + Lines + 77/91 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +3145x +  +  +  +  +  +  +  +  +17x +  +  +  +17x +2x +  +  +15x +  +15x +  +  +  +  +  +15x +  +  +  +15x +  +  +  +15x +  +  +  +  +  +  +15x +  +2x +  +  +  +2x +2x +  +  +  +  +  +2x +2x +  +  +  +15x +  +  +  +  +  +4x +  +  +  +4x +  +  +  +4x +  +  +  +  +4x +1x +  +  +3x +  +  +  +  +  +  +3x +  +  +  +  +3x +  +  +  +3x +  +  +  +3x +1x +  +  +2x +  +  +  +2x +1x +  +  +1x +  +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +1x +  +2x +  +1x +  +1x +  +  +  +  +2x +  +  +  +  +  +  +1x +  +  +  +  +1x +  +  +  +1x +  +  +  +1x +  +  +  +1x +1x +  +1x +  +  +  +  +1x +  +  +  +  +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +3x +  +  +  +3x +1x +  +  +2x +1x +  +  +1x +1x +1x +  +1x +1x +1x +  +  +  +  +1x +1x +  +  +  +1x +1x +  +  +  +1x +  +  +  +  +1x +1x +  +  +  +  +1x +  +  +  +  +1x +  +  +  +1x +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +5x
import knex from '../data/index';
+import { CommunityData } from '../models/Community'
+ 
+ 
+ 
+class BusinessLogicCommunity{
+ 
+    async newCommunity(data: CommunityData, creatorID: number){
+ 
+        const existingCommunity = await knex('Communities')
+            .where('name', data.name)
+            .first();
+ 
+        if (existingCommunity) {
+            throw new Error("Já existe uma comunidade com este nome.");
+        }
+ 
+        return knex.transaction(async (trx) => {
+            
+            const communityToInsert = {
+                name: data.name,
+                description: data.description,
+                creatorID: creatorID 
+            };
+ 
+            const [createdCommunity] = await trx('Communities')
+                .insert(communityToInsert)
+                .returning('*');
+ 
+            Iif (!createdCommunity) {
+                throw new Error("Falha ao criar comunidade.");
+            }
+ 
+            await trx('CommunityMembers').insert({
+                communityID: createdCommunity.communityID, 
+                userID: creatorID,
+                role: 'admin',
+                joinedAt: new Date()
+            });
+ 
+            if (data.technologies && data.technologies.length > 0) {
+                
+                const keywordIDs = await trx('Keywords')
+                                        .whereIn('tag', data.technologies)
+                                        .select('keywordID');
+ 
+                const keywordsToInsert = keywordIDs.map(keyword => {
+                    return {
+                        communityID: createdCommunity.communityID, 
+                        keywordID: keyword.keywordID               
+                    };
+                });
+ 
+                Eif (keywordsToInsert.length > 0) {
+                    await trx('CommunitiesKeywords').insert(keywordsToInsert);
+                }
+            }
+ 
+            return createdCommunity;
+        });
+    }
+ 
+    async newMemberCommunity(userID: number, communityID: string){
+ 
+        const community = await knex('Communities')
+            .where('communityID', communityID) 
+            .first();
+ 
+        Iif (!community) {
+            throw new Error("Comunidade não encontrada.");
+        }
+ 
+        const existingMember = await knex('CommunityMembers')
+            .where('communityID', communityID)
+            .andWhere('userID', userID)
+            .first();
+ 
+        if (existingMember) {
+            throw new Error("Usuário já é membro desta comunidade.");
+        }
+ 
+        await knex('CommunityMembers').insert({
+            communityID: communityID,
+            userID: userID,
+            role: 'member',
+            joinedAt: new Date()
+        });
+ 
+        return { message: "Membro adicionado com sucesso", communityID, userID };
+    }
+ 
+    async leaveMemberCommunity(userID: number, communityID: string){
+        
+        const community = await knex('Communities')
+            .where('communityID', communityID)
+            .first();
+ 
+        Iif (!community) {
+            throw new Error("Comunidade não encontrada.");
+        }
+ 
+        if (community.creatorID === userID) {
+            throw new Error("O criador não pode sair da comunidade. Você deve deletá-la ou transferir a propriedade.");
+        }
+ 
+        const member = await knex('CommunityMembers')
+            .where({ communityID, userID })
+            .first();
+ 
+        if (!member) {
+            throw new Error("Você não é membro desta comunidade.");
+        }
+ 
+        await knex('CommunityMembers')
+            .where({ communityID, userID })
+            .del();
+            
+        return { message: "Você saiu da comunidade com sucesso." };
+    }
+ 
+    async getAllUserCommunities(userID: number) {
+ 
+        const userCommunities = await knex('Communities')
+            .join('CommunityMembers', 'Communities.communityID', '=', 'CommunityMembers.communityID')
+            .where('CommunityMembers.userID', userID)
+            .select(
+                'Communities.*', 
+                'CommunityMembers.role', 
+                'CommunityMembers.joinedAt'
+            );
+ 
+        const communityIds = userCommunities.map(c => c.communityID);
+ 
+        Eif (communityIds.length === 0) return [];
+ 
+        const keywords = await knex('CommunitiesKeywords')
+            .join('Keywords', 'CommunitiesKeywords.keywordID', '=', 'Keywords.keywordID')
+            .whereIn('CommunitiesKeywords.communityID', communityIds)
+            .select('CommunitiesKeywords.communityID', 'Keywords.tag');
+ 
+        const result = userCommunities.map(comm => ({
+            ...comm,
+            technologies: keywords
+                .filter((k: any) => k.communityID === comm.communityID) 
+                .map((k: any) => k.tag) 
+        }));
+ 
+        return result;
+    }
+ 
+    async getUserFeed(userID: number){
+        const feed = await knex('Projects')
+ 
+            .join('ProjectCommunities', 'Projects.projectID', '=', 'ProjectCommunities.projectID')
+            
+            .join('CommunityMembers', 'ProjectCommunities.communityID', '=', 'CommunityMembers.communityID')
+            
+            .join('User', 'Projects.creatorID', '=', 'User.id')
+            
+            .where('CommunityMembers.userID', userID)
+            
+            .distinct('Projects.projectID')
+            
+            .select(
+                'Projects.*',
+                'User.username as authorUsername',
+                'User.fullName as authorName'
+            )
+            
+            .orderBy('Projects.createdAt', 'desc');
+ 
+        return feed;
+    }
+ 
+    async getAllCommunities(){
+        const communities = await knex('Communities').select('*');
+ 
+        const communityIds = communities.map(c => c.communityID);
+ 
+        Iif (communityIds.length === 0) return [];
+ 
+        const keywords = await knex('CommunitiesKeywords')
+            .join('Keywords', 'CommunitiesKeywords.keywordID', '=', 'Keywords.keywordID')
+            .whereIn('CommunitiesKeywords.communityID', communityIds)
+            .select('CommunitiesKeywords.communityID', 'Keywords.tag');
+ 
+        const result = communities.map(comm => ({
+            ...comm,
+            technologies: keywords
+                .filter((k: any) => k.communityID === comm.communityID)
+                .map((k: any) => k.tag)
+        }));
+ 
+        return result;
+    }
+ 
+    async getCommunityData(communityID: string, userID: number) {
+ 
+        const community = await knex('Communities')
+            .where('communityID', communityID)
+            .first();
+ 
+        Iif (!community) {
+            throw new Error("Comunidade não encontrada.");
+        }
+ 
+        const membership = await knex('CommunityMembers')
+            .where({ communityID: communityID, userID: userID })
+            .first();
+        
+        const isMember = !!membership;
+        const isAdmin = (community.creatorID === userID) || (membership && membership.role === 'admin');
+ 
+        const keywords = await knex('CommunitiesKeywords')
+        .join('Keywords', 'CommunitiesKeywords.keywordID', '=', 'Keywords.keywordID')
+        .where('CommunitiesKeywords.communityID', communityID)
+        .select('Keywords.tag');
+ 
+        const memberCount = await knex('CommunityMembers')
+        .where('communityID', communityID)
+        .count('userID as count')
+        .first();
+ 
+        const projects = await knex('Projects')
+            .join('ProjectCommunities', 'Projects.projectID', '=', 'ProjectCommunities.projectID')
+            .where('ProjectCommunities.communityID', communityID)
+            .select('Projects.*');
+ 
+        return {
+        community: {
+            ...community,
+            technologies: keywords.map((k: any) => k.tag),
+            memberCount: memberCount?.count || 0,
+            isMember: isMember,
+            isAdmin: isAdmin
+        },
+        posts: projects || []
+    };
+    }   
+ 
+    async updateCommunity(creatorID: number, communityID: string, data: CommunityData){
+ 
+        return knex.transaction(async (trx) => {
+ 
+            const community = await trx('Communities')
+                .where('communityID', communityID)
+                .first();
+ 
+            if (!community) {
+                throw new Error("Comunidade não encontrada.");
+            }
+ 
+            if (community.creatorID !== creatorID) {
+                throw new Error("Você não tem permissão para editar esta comunidade.");
+            }
+ 
+            const fieldsToUpdate: any = {};
+            Eif (data.name) fieldsToUpdate.name = data.name;
+            Eif (data.description) fieldsToUpdate.description = data.description;
+            
+            Eif (Object.keys(fieldsToUpdate).length > 0) {
+                fieldsToUpdate.updatedAt = new Date();
+                await trx('Communities')
+                    .where('communityID', communityID)
+                    .update(fieldsToUpdate);
+            }
+ 
+            Eif (data.technologies !== undefined) { 
+                 await trx('CommunitiesKeywords')
+                    .where('communityID', communityID)
+                    .del();
+ 
+                 Eif (Array.isArray(data.technologies) && data.technologies.length > 0) {
+                    const keywordIDs = await trx('Keywords')
+                        .whereIn('tag', data.technologies)
+                        .select('keywordID');
+ 
+                    const linksToInsert = keywordIDs.map((k: any) => ({
+                        communityID: communityID,
+                        keywordID: k.keywordID
+                    }));
+ 
+                    Eif (linksToInsert.length > 0) {
+                        await trx('CommunitiesKeywords').insert(linksToInsert);
+                    }
+                 }
+            }
+ 
+            return await trx('Communities').where('communityID', communityID).first();
+        });
+    }
+ 
+    async removeCommunity(creatorID: number, communityID: string){
+        const community = await knex('Communities')
+            .where('communityID', communityID)
+            .first();
+ 
+        Iif (!community) {
+            throw new Error("Comunidade não encontrada.");
+        }
+ 
+        Eif (community.creatorID !== creatorID) {
+            throw new Error("Você não tem permissão para deletar esta comunidade.");
+        }
+ 
+        await knex('Communities')
+            .where('communityID', communityID)
+            .del();
+    }
+    
+}
+ 
+ 
+export default new BusinessLogicCommunity();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/business/businessLogicProfile.ts.html b/backend/src/coverage/lcov-report/src/business/businessLogicProfile.ts.html new file mode 100644 index 0000000..b6b0b8e --- /dev/null +++ b/backend/src/coverage/lcov-report/src/business/businessLogicProfile.ts.html @@ -0,0 +1,262 @@ + + + + + + Code coverage report for src/business/businessLogicProfile.ts + + + + + + + + + +
+
+

All files / src/business businessLogicProfile.ts

+
+ +
+ 78.57% + Statements + 22/28 +
+ + +
+ 68.75% + Branches + 11/16 +
+ + +
+ 100% + Functions + 2/2 +
+ + +
+ 86.95% + Lines + 20/23 +
+ + +
+

+ 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 +605x +  +5x +  +  +  +  +  +  +  +  +3x +  +3x +3x +3x +3x +3x +  +3x +  +  +  +  +3x +1x +  +  +2x +  +2x +  +  +  +2x +  +  +  +  +2x +  +  +  +2x +  +2x +  +  +  +2x +  +  +  +2x +  +  +  +  +  +5x
import knex from '../data/index';
+import { UserData } from '../models/User';
+import bcrypt from 'bcryptjs';
+ 
+ 
+ 
+class businessLogicProfile{
+ 
+ 
+    async updateProfile(data: UserData, userID: number){
+        
+        const fieldsToUpdate: any = {};
+        
+        if (data.nomeCompleto) fieldsToUpdate.fullName = data.nomeCompleto; 
+        Iif (data.email) fieldsToUpdate.email = data.email;
+        Iif (data.username) fieldsToUpdate.username = data.username;
+        if (data.telefone) fieldsToUpdate.phone = data.telefone;
+        Iif (data.dataNascimento) fieldsToUpdate.birthDate = data.dataNascimento;
+ 
+        Iif (data.senha) {
+            const salt = await bcrypt.genSalt(10);
+            fieldsToUpdate.passwordHash = await bcrypt.hash(data.senha, salt);
+        }
+ 
+        if (Object.keys(fieldsToUpdate).length === 0) {
+            throw new Error("Nenhum dado para atualizar.");
+        }
+ 
+        fieldsToUpdate.updatedAt = new Date();
+ 
+        await knex('User')
+            .where('id', userID)
+            .update(fieldsToUpdate);
+ 
+        const updatedUser = await knex('User')
+            .where('id', userID)
+            .select('id', 'fullName', 'username', 'email', 'phone', 'birthDate', 'createdAt')
+            .first();
+ 
+        return updatedUser;
+    }
+ 
+    async removeProfile(userID: number){
+        const user = await knex('User').where('id', userID).first();
+ 
+        Iif (!user) {
+            throw new Error("Usuário não encontrado.");
+        }
+ 
+        await knex('User')
+            .where('id', userID)
+            .del();
+            
+        return { message: "Perfil deletado com sucesso." };
+    }
+    
+}
+ 
+ 
+export default new businessLogicProfile();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/business/businessLogicProject.ts.html b/backend/src/coverage/lcov-report/src/business/businessLogicProject.ts.html new file mode 100644 index 0000000..dccf2bf --- /dev/null +++ b/backend/src/coverage/lcov-report/src/business/businessLogicProject.ts.html @@ -0,0 +1,862 @@ + + + + + + Code coverage report for src/business/businessLogicProject.ts + + + + + + + + + +
+
+

All files / src/business businessLogicProject.ts

+
+ +
+ 75.3% + Statements + 61/81 +
+ + +
+ 56.81% + Branches + 25/44 +
+ + +
+ 83.33% + Functions + 15/18 +
+ + +
+ 79.45% + Lines + 58/73 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260  +5x +  +  +  +  +  +  +17x +  +17x +  +  +  +  +  +  +  +17x +  +  +  +17x +  +3x +  +  +  +3x +5x +  +  +  +  +  +3x +3x +  +  +  +  +  +3x +5x +  +  +3x +1x +  +  +  +  +  +1x +  +  +  +  +17x +  +  +  +  +  +2x +  +2x +  +  +  +2x +  +  +  +2x +1x +  +  +1x +1x +1x +1x +1x +  +1x +1x +1x +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +4x +  +  +4x +  +  +  +  +9x +  +9x +  +9x +  +  +  +  +  +  +9x +  +  +  +2x +  +  +  +  +  +  +  +  +  +2x +  +  +  +3x +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +2x +  +  +  +2x +  +  +  +2x +1x +  +  +1x +  +  +  +  +  +  +  +2x +  +  +  +2x +  +  +  +2x +1x +  +  +1x +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +3x +2x +  +  +  +1x +  +  +  +  +  +1x +  +2x +  +  +  +  +  +5x
 
+import knex from '../data/index';
+import { ProjectData } from '../models/Project'; 
+ 
+class BusinessLogicProject{
+ 
+    async newProject(data: ProjectData, creatorID: number){
+ 
+       return knex.transaction(async (trx) => {
+            
+            const projectToInsert = {
+                title: data.title,
+                description: data.description,
+                status: data.status,
+                startDate: data.startDate,
+                creatorID: creatorID 
+            };
+ 
+            const [newProject] = await trx('Projects')
+                                        .insert(projectToInsert)
+                                        .returning('*'); 
+ 
+            if (data.technologies && data.technologies.length > 0) {
+                
+                const keywordIDs = await trx('Keywords')
+                                        .whereIn('tag', data.technologies)
+                                        .select('keywordID'); 
+ 
+                const keywordsToInsert = keywordIDs.map(keyword => {
+                    return {
+                        projectID: newProject.projectID, 
+                        keywordID: keyword.keywordID 
+                    };
+                });
+ 
+                Eif (keywordsToInsert.length > 0) {
+                    await trx('ProjectsKeywords').insert(keywordsToInsert); 
+                    
+                    // --- NOVA LÓGICA DE ASSOCIAÇÃO AUTOMÁTICA ---
+ 
+                    // 3. Busca Comunidades que usam essas mesmas Keywords
+                    // Usamos .distinct() para evitar duplicatas (caso uma comunidade tenha React E Node, por exemplo)
+                    const matchingCommunities = await trx('CommunitiesKeywords')
+                        .whereIn('keywordID', keywordIDs.map(k => k.keywordID))
+                        .distinct('communityID');
+ 
+                    if (matchingCommunities.length > 0) {
+                        const communitiesToLink = matchingCommunities.map(comm => ({
+                            projectID: newProject.projectID,
+                            communityID: comm.communityID,
+                            associatedAt: new Date() 
+                        }));
+ 
+                        await trx('ProjectCommunities').insert(communitiesToLink);
+                    }
+                }
+            }
+            
+            return newProject;
+        });
+    }
+ 
+    async updateProject(projectId: string, projectData: Partial<any>, userId: number) {
+        
+        return knex.transaction(async (trx) => {
+            
+            const existingProject = await trx('Projects') 
+                .where({ projectID: projectId })
+                .first();
+ 
+            Iif (!existingProject) {
+                throw new Error("Projeto não encontrado.");
+            }
+ 
+            if (existingProject.creatorID !== userId) {
+                throw new Error("Você não tem permissão para editar este projeto.");
+            }
+ 
+            const fieldsToUpdate: any = {};
+            Eif (projectData.title !== undefined) fieldsToUpdate.title = projectData.title;
+            Eif (projectData.description !== undefined) fieldsToUpdate.description = projectData.description;
+            Iif (projectData.status !== undefined) fieldsToUpdate.status = projectData.status;
+            Iif (projectData.startDate !== undefined) fieldsToUpdate.startDate = projectData.startDate;
+ 
+            Eif (Object.keys(fieldsToUpdate).length > 0) {
+                fieldsToUpdate.updatedAt = new Date();
+                await trx('Projects')
+                    .where({ projectID: projectId })
+                    .update(fieldsToUpdate);
+            }
+ 
+            Iif (projectData.technologies !== undefined) {
+                
+                await trx('ProjectsKeywords')
+                    .where({ projectID: projectId })
+                    .del();
+ 
+                await trx('ProjectCommunities')
+                    .where({ projectID: projectId })
+                    .del();
+ 
+                if (Array.isArray(projectData.technologies) && projectData.technologies.length > 0) {
+                    
+                    const keywordIDs = await trx('Keywords')
+                        .whereIn('tag', projectData.technologies)
+                        .select('keywordID');
+ 
+                    const keywordsToInsert = keywordIDs.map((k: any) => ({
+                        projectID: projectId,
+                        keywordID: k.keywordID
+                    }));
+ 
+                    if (keywordsToInsert.length > 0) {
+                        await trx('ProjectsKeywords').insert(keywordsToInsert);
+                    }
+ 
+                    const matchingCommunities = await trx('CommunitiesKeywords')
+                        .whereIn('keywordID', keywordIDs.map((k:any) => k.keywordID))
+                        .distinct('communityID');
+ 
+                    if (matchingCommunities.length > 0) {
+                        const communitiesToLink = matchingCommunities.map((comm:any) => ({
+                            projectID: projectId,
+                            communityID: comm.communityID,
+                            associatedAt: new Date()
+                        }));
+ 
+                        await trx('ProjectCommunities').insert(communitiesToLink);
+                    }
+                }
+            }
+ 
+            return await trx('Projects').where({ projectID: projectId }).first();
+        });
+    }
+ 
+    async userProjects(creatorID: number){
+ 
+        const projects = await knex('Projects')
+                        .where('creatorID', creatorID);
+        
+        return projects;
+    }
+ 
+    async newComment(userID: number, projectID: string, content: string){
+        
+        const project = await knex('Projects').where('projectID', projectID).first();
+        
+        Iif (!project) throw new Error("Projeto não encontrado.");
+ 
+        const [newComment] = await knex('Comments').insert({
+            authorID: userID,
+            projectID: projectID,
+            content: content,
+            createdAt: new Date()
+        }).returning('*');
+ 
+        return newComment;
+    }
+ 
+    async getProjectComments(projectID: string){
+        const comments = await knex('Comments')
+            .join('User', 'Comments.authorID', '=', 'User.id') 
+            .where('Comments.projectID', projectID)
+            .select(
+                'Comments.*',           
+                'User.fullName',        
+                'User.username'         
+            )
+            .orderBy('Comments.createdAt', 'desc'); 
+ 
+        return comments;
+    }
+ 
+    async getUserComments(userID: number){
+        const comments = await knex('Comments')
+            .join('Projects', 'Comments.projectID', '=', 'Projects.projectID')
+            .where('Comments.authorID', userID)
+            .select(
+                'Comments.*',           
+                'Projects.title as projectTitle' 
+            )
+            .orderBy('Comments.createdAt', 'desc')
+            .orderBy('Comments.commentID', 'desc');
+ 
+        return comments;
+    }
+ 
+    async removeComment(userID: number, commentID: string){
+ 
+        const comment = await knex('Comments')
+            .where('commentID', commentID)
+            .first();
+ 
+        Iif (!comment) {
+            throw new Error("Comentário não encontrado.");
+        }
+ 
+        if (comment.authorID !== userID) {
+            throw new Error("Você não tem permissão para deletar este comentário.");
+        }
+ 
+        await knex('Comments')
+            .where('commentID', commentID)
+            .del();
+        
+    }
+ 
+    async removeProject(creatorID: number, projectID: string){
+        
+        const project = await knex('Projects')
+            .where('projectID', projectID)
+            .first();
+ 
+        Iif (!project) {
+            throw new Error("Projeto não encontrado.");
+        }
+ 
+        if (project.creatorID !== creatorID) {
+            throw new Error("Você não tem permissão para deletar este projeto.");
+        }
+ 
+        await knex('Projects')
+            .where('projectID', projectID)
+            .del();
+    }
+ 
+    async getProjectById(projectId: string) {
+        // Busca o projeto com dados do autor (join)
+        const project = await knex('Projects')
+            .join('User', 'Projects.creatorID', '=', 'User.id')
+            .where('Projects.projectID', projectId)
+            .select(
+                'Projects.*',
+                'User.username as authorUsername',
+                'User.fullName as authorName',
+                'User.id as authorID'
+            )
+            .first();
+ 
+        if (!project) {
+            throw new Error("Projeto não encontrado.");
+        }
+ 
+        // Busca as tecnologias (keywords) associadas
+        const keywords = await knex('ProjectsKeywords')
+            .join('Keywords', 'ProjectsKeywords.keywordID', '=', 'Keywords.keywordID')
+            .where('ProjectsKeywords.projectID', projectId)
+            .select('Keywords.tag');
+ 
+        // Retorna o objeto formatado
+        return {
+            ...project,
+            technologies: keywords.map((k: any) => k.tag)
+        };
+    }
+    
+}
+ 
+export default new BusinessLogicProject();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/business/index.html b/backend/src/coverage/lcov-report/src/business/index.html new file mode 100644 index 0000000..b62b0d9 --- /dev/null +++ b/backend/src/coverage/lcov-report/src/business/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/business + + + + + + + + + +
+
+

All files src/business

+
+ +
+ 81.85% + Statements + 194/237 +
+ + +
+ 64.8% + Branches + 81/125 +
+ + +
+ 77.27% + Functions + 34/44 +
+ + +
+ 85.11% + Lines + 183/215 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
businessLogicAuth.ts +
+
100%28/2890%9/10100%2/2100%28/28
businessLogicCommunity.ts +
+
83%83/10065.45%36/5568.18%15/2284.61%77/91
businessLogicProfile.ts +
+
78.57%22/2868.75%11/16100%2/286.95%20/23
businessLogicProject.ts +
+
75.3%61/8156.81%25/4483.33%15/1879.45%58/73
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/controller/index.html b/backend/src/coverage/lcov-report/src/controller/index.html new file mode 100644 index 0000000..662dd1b --- /dev/null +++ b/backend/src/coverage/lcov-report/src/controller/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/controller + + + + + + + + + +
+
+

All files src/controller

+
+ +
+ 80.18% + Statements + 89/111 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 87.5% + Functions + 21/24 +
+ + +
+ 80.9% + Lines + 89/110 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
requestController.ts +
+
80.18%89/11175%3/487.5%21/2480.9%89/110
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/controller/requestController.ts.html b/backend/src/coverage/lcov-report/src/controller/requestController.ts.html new file mode 100644 index 0000000..51fd875 --- /dev/null +++ b/backend/src/coverage/lcov-report/src/controller/requestController.ts.html @@ -0,0 +1,1024 @@ + + + + + + Code coverage report for src/controller/requestController.ts + + + + + + + + + +
+
+

All files / src/controller requestController.ts

+
+ +
+ 80.18% + Statements + 89/111 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 87.5% + Functions + 21/24 +
+ + +
+ 80.9% + Lines + 89/110 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +3145x +5x +  +  +5x +5x +5x +  +5x +5x +5x +  +5x +  +  +  +  +82x +  +82x +  +80x +  +80x +  +  +  +  +  +80x +  +  +2x +  +  +  +  +77x +  +77x +  +75x +  +75x +  +  +  +  +  +75x +  +  +  +2x +  +  +  +  +17x +17x +17x +  +17x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +4x +  +4x +  +  +  +  +  +  +  +2x +  +2x +  +1x +  +  +1x +  +  +  +  +2x +  +2x +  +  +1x +  +  +  +  +3x +3x +1x +  +2x +  +  +  +  +17x +  +17x +15x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +  +1x +  +1x +  +1x +  +  +  +  +  +  +  +  +1x +  +1x +  +1x +  +  +  +  +  +  +  +4x +  +4x +3x +  +  +1x +  +  +  +  +3x +  +3x +  +1x +  +  +2x +  +  +  +  +  +3x +  +3x +  +1x +  +  +2x +  +  +  +  +1x +  +1x +  +  +1x +  +  +  +  +9x +  +9x +  +  +  +9x +  +9x +  +  +  +  +  +  +  +2x +  +2x +  +2x +  +  +  +  +  +  +  +3x +  +3x +  +2x +  +  +1x +  +  +  +  +  +2x +  +2x +2x +  +  +  +  +  +  +  +  +2x +  +2x +  +  +1x +  +  +  +  +3x +  +3x +  +3x +  +  +  +  +  +  +  +  +5x
import businessLogicUser  from '../business/businessLogicAuth'
+import BusinessLogicProject from '../business/businessLogicProject';
+import {UserData, LoginData } from '../models/User'
+import { ProjectData } from '../models/Project';
+import jwt from 'jsonwebtoken';
+import { authConfig } from '../config/auth'
+import knex from '../data';
+import { CommunityData } from '../models/Community';
+import BusinessLogicCommunity from '../business/businessLogicCommunity';
+import businessLogicProject from '../business/businessLogicProject';
+import businessLogicCommunity from '../business/businessLogicCommunity';
+import { error } from 'console';
+import businessLogicProfile from '../business/businessLogicProfile';
+ 
+class RequestController {
+ 
+    async createUser(data: UserData) { 
+        try{
+ 
+            const userData = await businessLogicUser.newUser(data);
+ 
+            const payload = { id: userData.id, username: userData.username };
+ 
+            const token = jwt.sign(
+                payload,        
+                authConfig.secret,   
+                { expiresIn: authConfig.expiresIn } 
+            );
+ 
+            return { user: userData, token: token };
+ 
+        } catch(error){
+            throw error;   
+        }
+    }
+ 
+    async enterUser(data: LoginData){
+        try{
+ 
+            const userData = await businessLogicUser.enterUser(data);
+ 
+            const payload = { id: userData.id, username: userData.username };
+            
+            const token = jwt.sign(
+                payload,        
+                authConfig.secret,   
+                { expiresIn: authConfig.expiresIn } 
+            );
+ 
+            return { user: userData, token: token };
+ 
+        }catch(error){
+ 
+            throw error;
+        }
+    }
+ 
+    async createProject(data: ProjectData, creatorID: number){
+        try{
+            console.log(data);
+            const newProject = await BusinessLogicProject.newProject(data, creatorID);
+            
+            return newProject;
+ 
+        }catch(error){
+ 
+            throw new Error("Erro nos dados do projeto.");
+ 
+        }
+    }
+ 
+    async getKeywords(){
+        try{
+ 
+            const keywords = await knex('Keywords').select('tag');
+ 
+            const tags = keywords.map(kw => kw.tag);
+            
+            return tags;
+ 
+        }catch(error){
+            console.error("Erro ao buscar keywords:", error);
+            throw new Error("Não foi possível buscar as keywords.");
+        }
+    }
+ 
+    async getUserProjects(creatorID: number){
+        try{
+ 
+            const projects = await BusinessLogicProject.userProjects(creatorID);
+ 
+            return projects;
+ 
+        }catch(error){
+            throw new Error("Erro ao buscar os projetos do usuário.");
+        }
+    }
+ 
+    async updateProject(projectId: string, data: ProjectData, userId: number){
+        try{
+ 
+            const updatedProject = await BusinessLogicProject.updateProject(projectId, data, userId);
+ 
+            return updatedProject;
+ 
+        }catch(error){
+            throw new Error("Erro ao atualizar o projeto.");
+        }
+    }
+ 
+    async removeProject(userID: number, projectID: string){
+        try{
+ 
+            await BusinessLogicProject.removeProject(userID, projectID);
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async getProjectById(projectId: string) {
+        try {
+            const project = await businessLogicProject.getProjectById(projectId);
+            return project;
+        } catch (error) {
+            throw error;
+        }
+    }
+ 
+    async newCommunity(data: CommunityData, creatorID: number){
+        try{
+ 
+            const newCommunity = await BusinessLogicCommunity.newCommunity(data, creatorID);
+            return newCommunity;
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async getAllUserCommunities(userID: number) {
+        try {
+            const communities = await BusinessLogicCommunity.getAllUserCommunities(userID);
+            return communities;
+        } catch (error) {
+            console.error("Erro ao buscar comunidades:", error);
+            throw new Error("Erro ao carregar as comunidades.");
+        }
+    }
+ 
+    async getUserHome(userID: number){
+        try{
+            const communities = await businessLogicCommunity.getAllUserCommunities(userID);
+ 
+            const feed = await businessLogicCommunity.getUserFeed(userID);
+    
+            return {
+                communities: communities,
+                feed: feed
+            };
+            
+        }catch(error){
+            throw error;
+        }
+    }
+    async getAllCommunities(){
+        try{
+ 
+            const communities = await BusinessLogicCommunity.getAllCommunities();
+            
+            return communities;
+ 
+        }catch(error){
+            throw error;
+        }
+ 
+    }
+ 
+    async getCommunityData(communityID: string, userID: number){
+        try{    
+ 
+            const result = await BusinessLogicCommunity.getCommunityData(communityID,userID);
+ 
+            return result;
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async newMemberCommunity(userID: number, communityID: string){
+        try{
+ 
+            const result = await BusinessLogicCommunity.newMemberCommunity(userID, communityID);
+            return result;
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async leaveMemberCommunity(userID: number, communityID: string){
+        try{
+ 
+           const result = await businessLogicCommunity.leaveMemberCommunity(userID, communityID);
+ 
+            return result;
+ 
+        }catch(error){
+            throw error;
+        }
+ 
+    }
+ 
+    async updateCommunity(creatorID: number, communityID: string, data: CommunityData){
+        try{
+ 
+            const updatedCommunity = await BusinessLogicCommunity.updateCommunity(creatorID, communityID, data);
+ 
+            return updatedCommunity;
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async removeCommunity(creatorID: number, communityID: string){
+        try{
+ 
+            await BusinessLogicCommunity.removeCommunity(creatorID, communityID);
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async newComment(userID: number, projectID: string, content: string){
+        try{
+ 
+            Iif (!content || content.trim() === "") {
+                throw new Error("O comentário não pode ser vazio.");
+            }
+ 
+            const comment = await businessLogicProject.newComment(userID, projectID, content);
+ 
+            return comment;
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async getProjectComments(projectID: string) {
+        try{
+ 
+            const projectComments = await businessLogicProject.getProjectComments(projectID);
+ 
+            return projectComments;
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async updateProfile(data: UserData, userID: number){
+        try{
+ 
+            const result = await businessLogicProfile.updateProfile(data, userID);
+ 
+            return result;
+ 
+        }catch(error){
+            throw error;
+        }
+ 
+    }
+ 
+    async deleteProfile(userID: number){
+        try{
+ 
+            const message = await businessLogicProfile.removeProfile(userID);
+            return message;
+ 
+        }catch(error){
+            throw error;
+        }
+ 
+    }
+ 
+    async deleteComment(userID: number, commentID: string){
+        try{
+ 
+            await businessLogicProject.removeComment(userID, commentID);
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+    async getUserComments(userID: number){
+        try{
+ 
+            const allComments = await businessLogicProject.getUserComments(userID);
+            
+            return allComments;
+ 
+        }catch(error){
+            throw error;
+        }
+    }
+ 
+}
+ 
+export default new RequestController();
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/index.html b/backend/src/coverage/lcov-report/src/index.html new file mode 100644 index 0000000..1fef4f6 --- /dev/null +++ b/backend/src/coverage/lcov-report/src/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 95.45% + Statements + 105/110 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 92.59% + Functions + 25/27 +
+ + +
+ 95.45% + Lines + 105/110 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
app.ts +
+
100%13/13100%0/0100%4/4100%13/13
routes.ts +
+
94.84%92/97100%0/091.3%21/2394.84%92/97
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/routes.ts.html b/backend/src/coverage/lcov-report/src/routes.ts.html new file mode 100644 index 0000000..57dad14 --- /dev/null +++ b/backend/src/coverage/lcov-report/src/routes.ts.html @@ -0,0 +1,787 @@ + + + + + + Code coverage report for src/routes.ts + + + + + + + + + +
+
+

All files / src routes.ts

+
+ +
+ 94.84% + Statements + 92/97 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 91.3% + Functions + 21/23 +
+ + +
+ 94.84% + Lines + 92/97 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +2355x +5x +5x +  +  +  +5x +  +  +5x +82x +82x +80x +  +  +  +  +  +  +  +5x +77x +75x +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +5x +17x +  +17x +  +17x +  +17x +  +  +  +  +  +  +  +5x +4x +4x +4x +  +  +  +  +  +5x +2x +2x +2x +  +2x +  +1x +  +  +  +  +  +5x +  +2x +  +2x +  +1x +  +  +  +5x +  +3x +  +3x +  +1x +  +  +  +5x +  +17x +15x +  +  +  +  +  +5x +  +  +  +  +  +  +5x +  +1x +1x +  +1x +  +1x +  +  +5x +  +1x +1x +  +  +  +5x +  +4x +4x +  +4x +  +3x +  +  +  +5x +3x +3x +  +3x +  +1x +  +  +  +  +  +  +  +5x +1x +  +1x +  +  +  +  +  +  +5x +  +9x +9x +  +9x +  +9x +  +  +  +5x +  +3x +  +3x +  +  +5x +  +2x +  +2x +  +1x +  +  +  +5x +  +2x +  +2x +  +2x +  +  +  +  +5x +  +3x +  +2x +  +  +5x +  +2x +  +2x +  +  +5x +  +1x +  +1x +  +  +5x +3x +3x +3x +1x +  +2x +  +  +  +  +5x
import express from 'express';
+import RequestController from './controller/requestController';
+import authMiddleware from './middleware/auth';
+import auth from './middleware/auth';
+import { request } from 'http';
+ 
+const routes = express.Router();
+ 
+// Endpoint para CADASTRAR um novo usuário
+routes.post('/api/register', async (request, response) => {
+    console.log("Recebendo requisição de cadastro:", request.body);
+    const {user, token} = await RequestController.createUser(request.body);
+    return response.status(201).json({ 
+      user, 
+      token, 
+      message: 'Usuário cadastrado com sucesso!' 
+    });
+});
+ 
+// Endpoint para verificar a existência de usuário
+routes.post('/api/login', async(request, response) => {
+    const { user, token } = await RequestController.enterUser(request.body);
+    return response.status(200).json({
+        user,
+        token,
+        message: 'Usuário autenticado com sucesso.'
+    });
+});
+ 
+ 
+// Endpoint para enviar ao fronend os keywords disponíveis
+routes.get('/api/keywords', async(request, response) => {
+    const tags = await RequestController.getKeywords();
+ 
+    return response.status(200).json(tags);
+});
+ 
+// Endpoint para criar projeto
+routes.post('/api/user/newproject', authMiddleware,  async(request, response) =>{
+    const projectData = request.body;
+        
+    const creatorID = request.user.id; 
+ 
+    const newProject = await RequestController.createProject(projectData, creatorID);
+        
+    return response.status(201).json({
+        message: "Projeto criado com sucesso!",
+        project: newProject
+    });
+});
+ 
+ 
+// Endpoint para enviar ao frontend os projetos de determinado usuário
+routes.get('/api/user/projects', authMiddleware, async(request, response) => {
+      const creatorID = request.user.id;
+      const projects = await RequestController.getUserProjects(creatorID);
+      return response.status(200).json({
+        projects
+      })
+});
+ 
+// Endpoint para atualizar um projeto existente
+routes.put('/api/user/updateproject/:projectId', authMiddleware, async(request, response) => {
+    const { projectId } = request.params;
+    const updatedData = request.body;
+    const creatorID = request.user.id;
+ 
+    const updatedProject = await RequestController.updateProject(projectId, updatedData, creatorID);
+ 
+    return response.status(200).json({
+      message: "Projeto atualizado com sucesso!",
+      project: updatedProject
+    });
+});
+ 
+routes.delete('/api/user/deleteproject/:projectId', authMiddleware, async(request, response) =>{
+ 
+    const { projectId } = request.params;
+ 
+    await RequestController.removeProject(request.user.id, projectId);
+ 
+    return response.status(200).json({ message: "Projeto deletado com sucesso." });
+});
+ 
+ 
+routes.delete('/api/user/leavecommunity/:communityID', authMiddleware, async(request, response) =>{
+ 
+    const { communityID } = request.params;
+ 
+    const result = await RequestController.leaveMemberCommunity(request.user.id, communityID);
+ 
+    return response.status(200).json(result);
+})
+ 
+// Endpoint para criar uma comunidade
+routes.post('/api/newcommunity', authMiddleware, async(request, response) => {
+ 
+    const newCommunity = await RequestController.newCommunity(request.body, request.user.id);
+    return response.status(201).json({
+      community: newCommunity
+    })
+    
+});
+ 
+routes.get('/api/user/communities', authMiddleware, async (request, response) => {
+ 
+    const communities = await RequestController.getAllUserCommunities(request.user.id);
+    return response.status(200).json(communities);
+ 
+});
+ 
+routes.get('/api/communities/data/:communityId', authMiddleware, async (request, response) =>{
+ 
+    const { communityId } = request.params;
+    const userID = request.user.id;
+ 
+    const data = await RequestController.getCommunityData(communityId, userID);
+ 
+    return response.status(200).json(data);
+});
+ 
+routes.get('/api/communities', async(request, response) => {
+ 
+    const communities = await RequestController.getAllCommunities();
+    return response.status(200).json(communities);
+ 
+});
+ 
+routes.post('/api/communities/:communityId/join', authMiddleware, async(request, response) =>{
+ 
+    const userID = request.user.id;
+    const { communityId } = request.params;
+ 
+    const result = await RequestController.newMemberCommunity(userID, communityId);
+ 
+    return response.status(201).json(result);
+});
+ 
+ 
+routes.put('/api/communities/updatecommunity/:communityId', authMiddleware, async(request, response) => {
+    const { communityId } = request.params;
+    const data = request.body;
+ 
+    const updatedCommunity = await RequestController.updateCommunity(request.user.id, communityId, data);
+ 
+    return response.status(200).json({
+      message: "Comunidade atualizada com sucesso!",
+      community: updatedCommunity
+    });
+ 
+});
+ 
+ 
+routes.delete('/api/communities/deletecommunity/:communityId', authMiddleware, async(request, response) => {
+    const { communityId } = request.params;
+ 
+    await RequestController.removeCommunity(request.user.id, communityId);
+ 
+    return response.status(200).json({ message: "Comunidade deletada com sucesso." });
+ 
+})
+ 
+ 
+routes.post('/api/project/:projectID/comments', authMiddleware, async(request, response) =>{
+ 
+    const { projectID } = request.params;
+    const { content } = request.body;
+ 
+    const comment = await RequestController.newComment(request.user.id, projectID, content);
+ 
+    return response.status(201).json(comment);
+ 
+})
+ 
+routes.get('/api/user/comments', authMiddleware, async(request, response) => {
+    
+    const allComments = await RequestController.getUserComments(request.user.id);
+ 
+    return response.status(200).json(allComments);
+})
+ 
+routes.delete('/api/project/:commentID/deletecomment', authMiddleware, async(request, response) =>{
+ 
+    const { commentID } = request.params;    
+ 
+    await RequestController.deleteComment( request.user.id, commentID );
+ 
+    return response.status(200).json({ message: "Comentário deletado com sucesso."});
+ 
+})
+ 
+routes.get('/api/project/:projectID/comments', async(request, response) => {
+ 
+    const { projectID } = request.params;
+ 
+    const projectComments = await RequestController.getProjectComments( projectID );
+ 
+    return response.status(200).json(projectComments);
+ 
+})
+ 
+ 
+routes.put('/api/user/editprofile', authMiddleware, async(request, response) =>{
+ 
+    const updatedProfile = await RequestController.updateProfile(request.body, request.user.id);
+ 
+    return response.status(200).json(updatedProfile);
+})
+ 
+routes.delete('/api/user/deleteprofile', authMiddleware, async(request, response) =>{
+   
+    const message = await RequestController.deleteProfile(request.user.id);
+ 
+    return response.status(200).json(message);
+})
+ 
+routes.get('/api/user/home', authMiddleware, async(request, response) => {
+    
+    const homeData = await RequestController.getUserHome(request.user.id);
+    
+    return response.status(200).json(homeData);
+})
+ 
+routes.get('/api/projects/:projectId', authMiddleware, async (request, response) => {
+    const { projectId } = request.params;
+    try {
+        const project = await RequestController.getProjectById(projectId);
+        return response.status(200).json(project);
+    } catch (error) {
+        return response.status(404).json({ message: "Projeto não encontrado" });
+    }
+});
+ 
+ 
+export default routes;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/utils/index.html b/backend/src/coverage/lcov-report/src/utils/index.html new file mode 100644 index 0000000..8233700 --- /dev/null +++ b/backend/src/coverage/lcov-report/src/utils/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/utils + + + + + + + + + +
+
+

All files src/utils

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
validationUser.ts +
+
100%4/4100%0/0100%1/1100%4/4
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/backend/src/coverage/lcov-report/src/utils/validationUser.ts.html b/backend/src/coverage/lcov-report/src/utils/validationUser.ts.html new file mode 100644 index 0000000..30210d7 --- /dev/null +++ b/backend/src/coverage/lcov-report/src/utils/validationUser.ts.html @@ -0,0 +1,127 @@ + + + + + + Code coverage report for src/utils/validationUser.ts + + + + + + + + + +
+
+

All files / src/utils validationUser.ts

+
+ +
+ 100% + Statements + 4/4 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 4/4 +
+ + +
+

+ 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 +155x +  +  +5x +  +  +  +  +  +  +  +  +5x +82x + 
import { z } from 'zod';
+import { UserData } from '../models/User';
+ 
+const userSchema = z.object({
+  nomeCompleto: z.string().min(3, "Nome muito curto"),
+  username: z.string().min(4, "Username muito curto"),
+  email: z.string().email("Formato de e-mail inválido"),
+  telefone: z.string().optional(), 
+  dataNascimento: z.string() 
+});
+ 
+ 
+export function userValidate(data: UserData){
+    userSchema.parse(data);
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/coverage-final.json b/frontend/coverage/coverage-final.json new file mode 100644 index 0000000..da55b7f --- /dev/null +++ b/frontend/coverage/coverage-final.json @@ -0,0 +1,29 @@ +{"/home/cecilia/Documents/CTable/frontend/src/App.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/App.tsx","statementMap":{"0":{"start":{"line":9,"column":2},"end":{"line":15,"column":null}}},"fnMap":{"0":{"name":"App","decl":{"start":{"line":7,"column":9},"end":{"line":7,"column":15}},"loc":{"start":{"line":7,"column":15},"end":{"line":17,"column":null}},"line":7}},"branchMap":{},"s":{"0":2},"f":{"0":2},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:7:9:7:15":0,"s:9:2:15:Infinity":0}}} +,"/home/cecilia/Documents/CTable/frontend/src/API/Comment.ts": {"path":"/home/cecilia/Documents/CTable/frontend/src/API/Comment.ts","statementMap":{"0":{"start":{"line":14,"column":22},"end":{"line":20,"column":null}},"1":{"start":{"line":15,"column":2},"end":{"line":19,"column":null}},"2":{"start":{"line":23,"column":2},"end":{"line":39,"column":null}},"3":{"start":{"line":25,"column":21},"end":{"line":28,"column":null}},"4":{"start":{"line":30,"column":4},"end":{"line":30,"column":null}},"5":{"start":{"line":34,"column":4},"end":{"line":36,"column":null}},"6":{"start":{"line":35,"column":6},"end":{"line":35,"column":null}},"7":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"8":{"start":{"line":43,"column":2},"end":{"line":51,"column":null}},"9":{"start":{"line":45,"column":21},"end":{"line":45,"column":null}},"10":{"start":{"line":47,"column":4},"end":{"line":47,"column":null}},"11":{"start":{"line":49,"column":4},"end":{"line":49,"column":null}},"12":{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},"13":{"start":{"line":57,"column":2},"end":{"line":64,"column":null}},"14":{"start":{"line":58,"column":21},"end":{"line":58,"column":null}},"15":{"start":{"line":60,"column":4},"end":{"line":60,"column":null}},"16":{"start":{"line":62,"column":4},"end":{"line":62,"column":null}},"17":{"start":{"line":63,"column":4},"end":{"line":63,"column":null}},"18":{"start":{"line":68,"column":2},"end":{"line":78,"column":null}},"19":{"start":{"line":70,"column":21},"end":{"line":70,"column":null}},"20":{"start":{"line":72,"column":4},"end":{"line":72,"column":null}},"21":{"start":{"line":74,"column":4},"end":{"line":76,"column":null}},"22":{"start":{"line":75,"column":6},"end":{"line":75,"column":null}},"23":{"start":{"line":77,"column":4},"end":{"line":77,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":14,"column":22},"end":{"line":14,"column":28}},"loc":{"start":{"line":14,"column":28},"end":{"line":20,"column":null}},"line":14},"1":{"name":"CreateComment","decl":{"start":{"line":22,"column":22},"end":{"line":22,"column":36}},"loc":{"start":{"line":22,"column":72},"end":{"line":40,"column":null}},"line":22},"2":{"name":"GetComments","decl":{"start":{"line":42,"column":22},"end":{"line":42,"column":34}},"loc":{"start":{"line":42,"column":78},"end":{"line":54,"column":null}},"line":42},"3":{"name":"GetUserComments","decl":{"start":{"line":56,"column":22},"end":{"line":56,"column":65}},"loc":{"start":{"line":56,"column":65},"end":{"line":65,"column":null}},"line":56},"4":{"name":"DeleteComment","decl":{"start":{"line":67,"column":22},"end":{"line":67,"column":36}},"loc":{"start":{"line":67,"column":55},"end":{"line":79,"column":null}},"line":67}},"branchMap":{"0":{"loc":{"start":{"line":34,"column":4},"end":{"line":36,"column":null}},"type":"if","locations":[{"start":{"line":34,"column":4},"end":{"line":36,"column":null}},{"start":{},"end":{}}],"line":34},"1":{"loc":{"start":{"line":34,"column":4},"end":{"line":34,"column":47}},"type":"binary-expr","locations":[{"start":{"line":34,"column":4},"end":{"line":34,"column":31}},{"start":{"line":34,"column":31},"end":{"line":34,"column":47}}],"line":34},"2":{"loc":{"start":{"line":74,"column":4},"end":{"line":76,"column":null}},"type":"if","locations":[{"start":{"line":74,"column":4},"end":{"line":76,"column":null}},{"start":{},"end":{}}],"line":74},"3":{"loc":{"start":{"line":74,"column":4},"end":{"line":74,"column":47}},"type":"binary-expr","locations":[{"start":{"line":74,"column":4},"end":{"line":74,"column":31}},{"start":{"line":74,"column":31},"end":{"line":74,"column":47}}],"line":74}},"s":{"0":1,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0]},"meta":{"lastBranch":4,"lastFunction":5,"lastStatement":24,"seen":{"s:14:22:20:Infinity":0,"f:14:22:14:28":0,"s:15:2:19:Infinity":1,"f:22:22:22:36":1,"s:23:2:39:Infinity":2,"s:25:21:28:Infinity":3,"s:30:4:30:Infinity":4,"b:34:4:36:Infinity:undefined:undefined:undefined:undefined":0,"s:34:4:36:Infinity":5,"b:34:4:34:31:34:31:34:47":1,"s:35:6:35:Infinity":6,"s:37:4:37:Infinity":7,"f:42:22:42:34":2,"s:43:2:51:Infinity":8,"s:45:21:45:Infinity":9,"s:47:4:47:Infinity":10,"s:49:4:49:Infinity":11,"s:50:4:50:Infinity":12,"f:56:22:56:65":3,"s:57:2:64:Infinity":13,"s:58:21:58:Infinity":14,"s:60:4:60:Infinity":15,"s:62:4:62:Infinity":16,"s:63:4:63:Infinity":17,"f:67:22:67:36":4,"s:68:2:78:Infinity":18,"s:70:21:70:Infinity":19,"s:72:4:72:Infinity":20,"b:74:4:76:Infinity:undefined:undefined:undefined:undefined":2,"s:74:4:76:Infinity":21,"b:74:4:74:31:74:31:74:47":3,"s:75:6:75:Infinity":22,"s:77:4:77:Infinity":23}}} +,"/home/cecilia/Documents/CTable/frontend/src/API/Community.ts": {"path":"/home/cecilia/Documents/CTable/frontend/src/API/Community.ts","statementMap":{"0":{"start":{"line":16,"column":22},"end":{"line":22,"column":null}},"1":{"start":{"line":17,"column":2},"end":{"line":21,"column":null}},"2":{"start":{"line":26,"column":4},"end":{"line":35,"column":null}},"3":{"start":{"line":27,"column":6},"end":{"line":27,"column":null}},"4":{"start":{"line":28,"column":23},"end":{"line":28,"column":null}},"5":{"start":{"line":29,"column":6},"end":{"line":29,"column":null}},"6":{"start":{"line":31,"column":6},"end":{"line":33,"column":null}},"7":{"start":{"line":32,"column":10},"end":{"line":32,"column":null}},"8":{"start":{"line":34,"column":6},"end":{"line":34,"column":null}},"9":{"start":{"line":39,"column":2},"end":{"line":45,"column":null}},"10":{"start":{"line":40,"column":19},"end":{"line":40,"column":null}},"11":{"start":{"line":41,"column":2},"end":{"line":41,"column":null}},"12":{"start":{"line":43,"column":4},"end":{"line":43,"column":null}},"13":{"start":{"line":44,"column":4},"end":{"line":44,"column":null}},"14":{"start":{"line":49,"column":2},"end":{"line":58,"column":null}},"15":{"start":{"line":50,"column":21},"end":{"line":50,"column":null}},"16":{"start":{"line":52,"column":4},"end":{"line":52,"column":null}},"17":{"start":{"line":54,"column":4},"end":{"line":56,"column":null}},"18":{"start":{"line":55,"column":10},"end":{"line":55,"column":null}},"19":{"start":{"line":57,"column":4},"end":{"line":57,"column":null}},"20":{"start":{"line":62,"column":2},"end":{"line":71,"column":null}},"21":{"start":{"line":63,"column":21},"end":{"line":63,"column":null}},"22":{"start":{"line":65,"column":4},"end":{"line":65,"column":null}},"23":{"start":{"line":67,"column":4},"end":{"line":69,"column":null}},"24":{"start":{"line":68,"column":10},"end":{"line":68,"column":null}},"25":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"26":{"start":{"line":75,"column":2},"end":{"line":83,"column":null}},"27":{"start":{"line":76,"column":21},"end":{"line":76,"column":null}},"28":{"start":{"line":77,"column":4},"end":{"line":77,"column":null}},"29":{"start":{"line":79,"column":4},"end":{"line":81,"column":null}},"30":{"start":{"line":80,"column":10},"end":{"line":80,"column":null}},"31":{"start":{"line":82,"column":4},"end":{"line":82,"column":null}},"32":{"start":{"line":87,"column":2},"end":{"line":99,"column":null}},"33":{"start":{"line":88,"column":21},"end":{"line":91,"column":null}},"34":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"35":{"start":{"line":95,"column":4},"end":{"line":97,"column":null}},"36":{"start":{"line":96,"column":8},"end":{"line":96,"column":null}},"37":{"start":{"line":98,"column":4},"end":{"line":98,"column":null}},"38":{"start":{"line":103,"column":2},"end":{"line":112,"column":null}},"39":{"start":{"line":104,"column":21},"end":{"line":104,"column":null}},"40":{"start":{"line":106,"column":4},"end":{"line":106,"column":null}},"41":{"start":{"line":108,"column":4},"end":{"line":110,"column":null}},"42":{"start":{"line":109,"column":8},"end":{"line":109,"column":null}},"43":{"start":{"line":111,"column":4},"end":{"line":111,"column":null}},"44":{"start":{"line":116,"column":2},"end":{"line":122,"column":null}},"45":{"start":{"line":117,"column":21},"end":{"line":117,"column":null}},"46":{"start":{"line":118,"column":4},"end":{"line":118,"column":null}},"47":{"start":{"line":120,"column":4},"end":{"line":120,"column":null}},"48":{"start":{"line":121,"column":4},"end":{"line":121,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":16,"column":22},"end":{"line":16,"column":28}},"loc":{"start":{"line":16,"column":28},"end":{"line":22,"column":null}},"line":16},"1":{"name":"NewCommunity","decl":{"start":{"line":24,"column":22},"end":{"line":24,"column":35}},"loc":{"start":{"line":24,"column":57},"end":{"line":36,"column":null}},"line":24},"2":{"name":"GetUserCommunities","decl":{"start":{"line":38,"column":22},"end":{"line":38,"column":70}},"loc":{"start":{"line":38,"column":70},"end":{"line":46,"column":null}},"line":38},"3":{"name":"GetCommunityById","decl":{"start":{"line":48,"column":22},"end":{"line":48,"column":39}},"loc":{"start":{"line":48,"column":60},"end":{"line":59,"column":null}},"line":48},"4":{"name":"JoinCommunity","decl":{"start":{"line":61,"column":22},"end":{"line":61,"column":36}},"loc":{"start":{"line":61,"column":57},"end":{"line":72,"column":null}},"line":61},"5":{"name":"DeleteCommunity","decl":{"start":{"line":74,"column":22},"end":{"line":74,"column":38}},"loc":{"start":{"line":74,"column":59},"end":{"line":84,"column":null}},"line":74},"6":{"name":"UpdateCommunity","decl":{"start":{"line":86,"column":22},"end":{"line":86,"column":38}},"loc":{"start":{"line":86,"column":81},"end":{"line":100,"column":null}},"line":86},"7":{"name":"LeaveCommunity","decl":{"start":{"line":102,"column":22},"end":{"line":102,"column":37}},"loc":{"start":{"line":102,"column":58},"end":{"line":113,"column":null}},"line":102},"8":{"name":"GetAllCommunities","decl":{"start":{"line":115,"column":22},"end":{"line":115,"column":69}},"loc":{"start":{"line":115,"column":69},"end":{"line":123,"column":null}},"line":115}},"branchMap":{"0":{"loc":{"start":{"line":31,"column":6},"end":{"line":33,"column":null}},"type":"if","locations":[{"start":{"line":31,"column":6},"end":{"line":33,"column":null}},{"start":{},"end":{}}],"line":31},"1":{"loc":{"start":{"line":31,"column":6},"end":{"line":31,"column":49}},"type":"binary-expr","locations":[{"start":{"line":31,"column":6},"end":{"line":31,"column":33}},{"start":{"line":31,"column":33},"end":{"line":31,"column":49}}],"line":31},"2":{"loc":{"start":{"line":54,"column":4},"end":{"line":56,"column":null}},"type":"if","locations":[{"start":{"line":54,"column":4},"end":{"line":56,"column":null}},{"start":{},"end":{}}],"line":54},"3":{"loc":{"start":{"line":54,"column":4},"end":{"line":54,"column":63}},"type":"binary-expr","locations":[{"start":{"line":54,"column":4},"end":{"line":54,"column":31}},{"start":{"line":54,"column":31},"end":{"line":54,"column":63}}],"line":54},"4":{"loc":{"start":{"line":67,"column":4},"end":{"line":69,"column":null}},"type":"if","locations":[{"start":{"line":67,"column":4},"end":{"line":69,"column":null}},{"start":{},"end":{}}],"line":67},"5":{"loc":{"start":{"line":67,"column":4},"end":{"line":67,"column":47}},"type":"binary-expr","locations":[{"start":{"line":67,"column":4},"end":{"line":67,"column":31}},{"start":{"line":67,"column":31},"end":{"line":67,"column":47}}],"line":67},"6":{"loc":{"start":{"line":79,"column":4},"end":{"line":81,"column":null}},"type":"if","locations":[{"start":{"line":79,"column":4},"end":{"line":81,"column":null}},{"start":{},"end":{}}],"line":79},"7":{"loc":{"start":{"line":79,"column":4},"end":{"line":79,"column":47}},"type":"binary-expr","locations":[{"start":{"line":79,"column":4},"end":{"line":79,"column":31}},{"start":{"line":79,"column":31},"end":{"line":79,"column":47}}],"line":79},"8":{"loc":{"start":{"line":95,"column":4},"end":{"line":97,"column":null}},"type":"if","locations":[{"start":{"line":95,"column":4},"end":{"line":97,"column":null}},{"start":{},"end":{}}],"line":95},"9":{"loc":{"start":{"line":95,"column":4},"end":{"line":95,"column":47}},"type":"binary-expr","locations":[{"start":{"line":95,"column":4},"end":{"line":95,"column":31}},{"start":{"line":95,"column":31},"end":{"line":95,"column":47}}],"line":95},"10":{"loc":{"start":{"line":108,"column":4},"end":{"line":110,"column":null}},"type":"if","locations":[{"start":{"line":108,"column":4},"end":{"line":110,"column":null}},{"start":{},"end":{}}],"line":108},"11":{"loc":{"start":{"line":108,"column":4},"end":{"line":108,"column":47}},"type":"binary-expr","locations":[{"start":{"line":108,"column":4},"end":{"line":108,"column":31}},{"start":{"line":108,"column":31},"end":{"line":108,"column":47}}],"line":108}},"s":{"0":2,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0]},"meta":{"lastBranch":12,"lastFunction":9,"lastStatement":49,"seen":{"s:16:22:22:Infinity":0,"f:16:22:16:28":0,"s:17:2:21:Infinity":1,"f:24:22:24:35":1,"s:26:4:35:Infinity":2,"s:27:6:27:Infinity":3,"s:28:23:28:Infinity":4,"s:29:6:29:Infinity":5,"b:31:6:33:Infinity:undefined:undefined:undefined:undefined":0,"s:31:6:33:Infinity":6,"b:31:6:31:33:31:33:31:49":1,"s:32:10:32:Infinity":7,"s:34:6:34:Infinity":8,"f:38:22:38:70":2,"s:39:2:45:Infinity":9,"s:40:19:40:Infinity":10,"s:41:2:41:Infinity":11,"s:43:4:43:Infinity":12,"s:44:4:44:Infinity":13,"f:48:22:48:39":3,"s:49:2:58:Infinity":14,"s:50:21:50:Infinity":15,"s:52:4:52:Infinity":16,"b:54:4:56:Infinity:undefined:undefined:undefined:undefined":2,"s:54:4:56:Infinity":17,"b:54:4:54:31:54:31:54:63":3,"s:55:10:55:Infinity":18,"s:57:4:57:Infinity":19,"f:61:22:61:36":4,"s:62:2:71:Infinity":20,"s:63:21:63:Infinity":21,"s:65:4:65:Infinity":22,"b:67:4:69:Infinity:undefined:undefined:undefined:undefined":4,"s:67:4:69:Infinity":23,"b:67:4:67:31:67:31:67:47":5,"s:68:10:68:Infinity":24,"s:70:4:70:Infinity":25,"f:74:22:74:38":5,"s:75:2:83:Infinity":26,"s:76:21:76:Infinity":27,"s:77:4:77:Infinity":28,"b:79:4:81:Infinity:undefined:undefined:undefined:undefined":6,"s:79:4:81:Infinity":29,"b:79:4:79:31:79:31:79:47":7,"s:80:10:80:Infinity":30,"s:82:4:82:Infinity":31,"f:86:22:86:38":6,"s:87:2:99:Infinity":32,"s:88:21:91:Infinity":33,"s:93:4:93:Infinity":34,"b:95:4:97:Infinity:undefined:undefined:undefined:undefined":8,"s:95:4:97:Infinity":35,"b:95:4:95:31:95:31:95:47":9,"s:96:8:96:Infinity":36,"s:98:4:98:Infinity":37,"f:102:22:102:37":7,"s:103:2:112:Infinity":38,"s:104:21:104:Infinity":39,"s:106:4:106:Infinity":40,"b:108:4:110:Infinity:undefined:undefined:undefined:undefined":10,"s:108:4:110:Infinity":41,"b:108:4:108:31:108:31:108:47":11,"s:109:8:109:Infinity":42,"s:111:4:111:Infinity":43,"f:115:22:115:69":8,"s:116:2:122:Infinity":44,"s:117:21:117:Infinity":45,"s:118:4:118:Infinity":46,"s:120:4:120:Infinity":47,"s:121:4:121:Infinity":48}}} +,"/home/cecilia/Documents/CTable/frontend/src/API/Project.ts": {"path":"/home/cecilia/Documents/CTable/frontend/src/API/Project.ts","statementMap":{"0":{"start":{"line":18,"column":26},"end":{"line":18,"column":null}},"1":{"start":{"line":21,"column":2},"end":{"line":21,"column":null}},"2":{"start":{"line":24,"column":22},"end":{"line":30,"column":null}},"3":{"start":{"line":25,"column":2},"end":{"line":29,"column":null}},"4":{"start":{"line":33,"column":2},"end":{"line":42,"column":null}},"5":{"start":{"line":34,"column":21},"end":{"line":34,"column":null}},"6":{"start":{"line":36,"column":4},"end":{"line":36,"column":null}},"7":{"start":{"line":38,"column":4},"end":{"line":40,"column":null}},"8":{"start":{"line":39,"column":6},"end":{"line":39,"column":null}},"9":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"10":{"start":{"line":46,"column":2},"end":{"line":57,"column":null}},"11":{"start":{"line":47,"column":21},"end":{"line":50,"column":null}},"12":{"start":{"line":51,"column":4},"end":{"line":51,"column":null}},"13":{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},"14":{"start":{"line":54,"column":6},"end":{"line":54,"column":null}},"15":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"16":{"start":{"line":63,"column":2},"end":{"line":72,"column":null}},"17":{"start":{"line":64,"column":21},"end":{"line":64,"column":null}},"18":{"start":{"line":66,"column":4},"end":{"line":66,"column":null}},"19":{"start":{"line":68,"column":4},"end":{"line":68,"column":null}},"20":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"21":{"start":{"line":71,"column":4},"end":{"line":71,"column":null}},"22":{"start":{"line":76,"column":2},"end":{"line":84,"column":null}},"23":{"start":{"line":77,"column":4},"end":{"line":77,"column":null}},"24":{"start":{"line":80,"column":4},"end":{"line":82,"column":null}},"25":{"start":{"line":81,"column":6},"end":{"line":81,"column":null}},"26":{"start":{"line":83,"column":4},"end":{"line":83,"column":null}},"27":{"start":{"line":88,"column":2},"end":{"line":99,"column":null}},"28":{"start":{"line":89,"column":21},"end":{"line":89,"column":null}},"29":{"start":{"line":91,"column":4},"end":{"line":91,"column":null}},"30":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"31":{"start":{"line":95,"column":4},"end":{"line":97,"column":null}},"32":{"start":{"line":96,"column":6},"end":{"line":96,"column":null}},"33":{"start":{"line":98,"column":4},"end":{"line":98,"column":null}},"34":{"start":{"line":103,"column":2},"end":{"line":110,"column":null}},"35":{"start":{"line":104,"column":21},"end":{"line":104,"column":null}},"36":{"start":{"line":106,"column":4},"end":{"line":106,"column":null}},"37":{"start":{"line":108,"column":4},"end":{"line":108,"column":null}},"38":{"start":{"line":109,"column":4},"end":{"line":109,"column":null}}},"fnMap":{"0":{"name":"parseDate","decl":{"start":{"line":16,"column":16},"end":{"line":16,"column":26}},"loc":{"start":{"line":16,"column":52},"end":{"line":22,"column":null}},"line":16},"1":{"name":"(anonymous_1)","decl":{"start":{"line":24,"column":22},"end":{"line":24,"column":28}},"loc":{"start":{"line":24,"column":28},"end":{"line":30,"column":null}},"line":24},"2":{"name":"NewProject","decl":{"start":{"line":32,"column":22},"end":{"line":32,"column":33}},"loc":{"start":{"line":32,"column":53},"end":{"line":43,"column":null}},"line":32},"3":{"name":"UpdateProject","decl":{"start":{"line":45,"column":22},"end":{"line":45,"column":36}},"loc":{"start":{"line":45,"column":75},"end":{"line":59,"column":null}},"line":45},"4":{"name":"GetFeedProjects","decl":{"start":{"line":61,"column":22},"end":{"line":61,"column":65}},"loc":{"start":{"line":61,"column":65},"end":{"line":73,"column":null}},"line":61},"5":{"name":"DeleteProject","decl":{"start":{"line":75,"column":22},"end":{"line":75,"column":36}},"loc":{"start":{"line":75,"column":55},"end":{"line":85,"column":null}},"line":75},"6":{"name":"GetUserProjects","decl":{"start":{"line":87,"column":22},"end":{"line":87,"column":65}},"loc":{"start":{"line":87,"column":65},"end":{"line":100,"column":null}},"line":87},"7":{"name":"GetProjectById","decl":{"start":{"line":102,"column":22},"end":{"line":102,"column":37}},"loc":{"start":{"line":102,"column":79},"end":{"line":111,"column":null}},"line":102}},"branchMap":{"0":{"loc":{"start":{"line":38,"column":4},"end":{"line":40,"column":null}},"type":"if","locations":[{"start":{"line":38,"column":4},"end":{"line":40,"column":null}},{"start":{},"end":{}}],"line":38},"1":{"loc":{"start":{"line":38,"column":4},"end":{"line":38,"column":47}},"type":"binary-expr","locations":[{"start":{"line":38,"column":4},"end":{"line":38,"column":31}},{"start":{"line":38,"column":31},"end":{"line":38,"column":47}}],"line":38},"2":{"loc":{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":53,"column":4},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":53},"3":{"loc":{"start":{"line":53,"column":4},"end":{"line":53,"column":47}},"type":"binary-expr","locations":[{"start":{"line":53,"column":4},"end":{"line":53,"column":31}},{"start":{"line":53,"column":31},"end":{"line":53,"column":47}}],"line":53},"4":{"loc":{"start":{"line":80,"column":4},"end":{"line":82,"column":null}},"type":"if","locations":[{"start":{"line":80,"column":4},"end":{"line":82,"column":null}},{"start":{},"end":{}}],"line":80},"5":{"loc":{"start":{"line":80,"column":4},"end":{"line":80,"column":47}},"type":"binary-expr","locations":[{"start":{"line":80,"column":4},"end":{"line":80,"column":31}},{"start":{"line":80,"column":31},"end":{"line":80,"column":47}}],"line":80},"6":{"loc":{"start":{"line":95,"column":4},"end":{"line":97,"column":null}},"type":"if","locations":[{"start":{"line":95,"column":4},"end":{"line":97,"column":null}},{"start":{},"end":{}}],"line":95},"7":{"loc":{"start":{"line":95,"column":4},"end":{"line":95,"column":47}},"type":"binary-expr","locations":[{"start":{"line":95,"column":4},"end":{"line":95,"column":31}},{"start":{"line":95,"column":31},"end":{"line":95,"column":47}}],"line":95}},"s":{"0":2,"1":2,"2":4,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0},"f":{"0":2,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0]},"meta":{"lastBranch":8,"lastFunction":8,"lastStatement":39,"seen":{"f:16:16:16:26":0,"s:18:26:18:Infinity":0,"s:21:2:21:Infinity":1,"s:24:22:30:Infinity":2,"f:24:22:24:28":1,"s:25:2:29:Infinity":3,"f:32:22:32:33":2,"s:33:2:42:Infinity":4,"s:34:21:34:Infinity":5,"s:36:4:36:Infinity":6,"b:38:4:40:Infinity:undefined:undefined:undefined:undefined":0,"s:38:4:40:Infinity":7,"b:38:4:38:31:38:31:38:47":1,"s:39:6:39:Infinity":8,"s:41:4:41:Infinity":9,"f:45:22:45:36":3,"s:46:2:57:Infinity":10,"s:47:21:50:Infinity":11,"s:51:4:51:Infinity":12,"b:53:4:55:Infinity:undefined:undefined:undefined:undefined":2,"s:53:4:55:Infinity":13,"b:53:4:53:31:53:31:53:47":3,"s:54:6:54:Infinity":14,"s:56:4:56:Infinity":15,"f:61:22:61:65":4,"s:63:2:72:Infinity":16,"s:64:21:64:Infinity":17,"s:66:4:66:Infinity":18,"s:68:4:68:Infinity":19,"s:70:4:70:Infinity":20,"s:71:4:71:Infinity":21,"f:75:22:75:36":5,"s:76:2:84:Infinity":22,"s:77:4:77:Infinity":23,"b:80:4:82:Infinity:undefined:undefined:undefined:undefined":4,"s:80:4:82:Infinity":24,"b:80:4:80:31:80:31:80:47":5,"s:81:6:81:Infinity":25,"s:83:4:83:Infinity":26,"f:87:22:87:65":6,"s:88:2:99:Infinity":27,"s:89:21:89:Infinity":28,"s:91:4:91:Infinity":29,"s:93:4:93:Infinity":30,"b:95:4:97:Infinity:undefined:undefined:undefined:undefined":6,"s:95:4:97:Infinity":31,"b:95:4:95:31:95:31:95:47":7,"s:96:6:96:Infinity":32,"s:98:4:98:Infinity":33,"f:102:22:102:37":7,"s:103:2:110:Infinity":34,"s:104:21:104:Infinity":35,"s:106:4:106:Infinity":36,"s:108:4:108:Infinity":37,"s:109:4:109:Infinity":38}}} +,"/home/cecilia/Documents/CTable/frontend/src/API/api.ts": {"path":"/home/cecilia/Documents/CTable/frontend/src/API/api.ts","statementMap":{"0":{"start":{"line":3,"column":12},"end":{"line":5,"column":null}}},"fnMap":{},"branchMap":{"0":{"loc":{"start":{"line":4,"column":11},"end":{"line":4,"column":null}},"type":"binary-expr","locations":[{"start":{"line":4,"column":11},"end":{"line":4,"column":43}},{"start":{"line":4,"column":43},"end":{"line":4,"column":null}}],"line":4}},"s":{"0":5},"f":{},"b":{"0":[5,5]},"meta":{"lastBranch":1,"lastFunction":0,"lastStatement":1,"seen":{"s:3:12:5:Infinity":0,"b:4:11:4:43:4:43:4:Infinity":0}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/common/Keyword/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/common/Keyword/index.tsx","statementMap":{"0":{"start":{"line":10,"column":47},"end":{"line":19,"column":null}},"1":{"start":{"line":11,"column":2},"end":{"line":17,"column":null}},"2":{"start":{"line":21,"column":32},"end":{"line":21,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":10,"column":47},"end":{"line":10,"column":48}},"loc":{"start":{"line":10,"column":75},"end":{"line":19,"column":null}},"line":10}},"branchMap":{},"s":{"0":1,"1":2,"2":1},"f":{"0":2},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":3,"seen":{"s:10:47:19:Infinity":0,"f:10:47:10:48":0,"s:11:2:17:Infinity":1,"s:21:32:21:Infinity":2}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/common/Modal/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/common/Modal/index.tsx","statementMap":{"0":{"start":{"line":12,"column":36},"end":{"line":45,"column":null}},"1":{"start":{"line":14,"column":2},"end":{"line":24,"column":null}},"2":{"start":{"line":15,"column":4},"end":{"line":19,"column":null}},"3":{"start":{"line":16,"column":6},"end":{"line":16,"column":null}},"4":{"start":{"line":18,"column":6},"end":{"line":18,"column":null}},"5":{"start":{"line":21,"column":4},"end":{"line":23,"column":null}},"6":{"start":{"line":22,"column":6},"end":{"line":22,"column":null}},"7":{"start":{"line":26,"column":2},"end":{"line":28,"column":null}},"8":{"start":{"line":27,"column":4},"end":{"line":27,"column":null}},"9":{"start":{"line":31,"column":29},"end":{"line":33,"column":null}},"10":{"start":{"line":32,"column":4},"end":{"line":32,"column":null}},"11":{"start":{"line":35,"column":2},"end":{"line":44,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":12,"column":36},"end":{"line":12,"column":37}},"loc":{"start":{"line":12,"column":78},"end":{"line":45,"column":null}},"line":12},"1":{"name":"(anonymous_1)","decl":{"start":{"line":14,"column":12},"end":{"line":14,"column":18}},"loc":{"start":{"line":14,"column":18},"end":{"line":24,"column":5}},"line":14},"2":{"name":"(anonymous_2)","decl":{"start":{"line":21,"column":11},"end":{"line":21,"column":17}},"loc":{"start":{"line":21,"column":17},"end":{"line":23,"column":null}},"line":21},"3":{"name":"(anonymous_3)","decl":{"start":{"line":31,"column":29},"end":{"line":31,"column":30}},"loc":{"start":{"line":31,"column":54},"end":{"line":33,"column":null}},"line":31}},"branchMap":{"0":{"loc":{"start":{"line":15,"column":4},"end":{"line":19,"column":null}},"type":"if","locations":[{"start":{"line":15,"column":4},"end":{"line":19,"column":null}},{"start":{"line":17,"column":11},"end":{"line":19,"column":null}}],"line":15},"1":{"loc":{"start":{"line":26,"column":2},"end":{"line":28,"column":null}},"type":"if","locations":[{"start":{"line":26,"column":2},"end":{"line":28,"column":null}},{"start":{},"end":{}}],"line":26}},"s":{"0":1,"1":5,"2":5,"3":4,"4":1,"5":5,"6":5,"7":5,"8":1,"9":4,"10":2,"11":4},"f":{"0":5,"1":5,"2":5,"3":2},"b":{"0":[4,1],"1":[1,4]},"meta":{"lastBranch":2,"lastFunction":4,"lastStatement":12,"seen":{"s:12:36:45:Infinity":0,"f:12:36:12:37":0,"s:14:2:24:Infinity":1,"f:14:12:14:18":1,"b:15:4:19:Infinity:17:11:19:Infinity":0,"s:15:4:19:Infinity":2,"s:16:6:16:Infinity":3,"s:18:6:18:Infinity":4,"s:21:4:23:Infinity":5,"f:21:11:21:17":2,"s:22:6:22:Infinity":6,"b:26:2:28:Infinity:undefined:undefined:undefined:undefined":1,"s:26:2:28:Infinity":7,"s:27:4:27:Infinity":8,"s:31:29:33:Infinity":9,"f:31:29:31:30":3,"s:32:4:32:Infinity":10,"s:35:2:44:Infinity":11}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/common/Toast/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/common/Toast/index.tsx","statementMap":{"0":{"start":{"line":15,"column":36},"end":{"line":37,"column":null}},"1":{"start":{"line":18,"column":2},"end":{"line":27,"column":null}},"2":{"start":{"line":19,"column":18},"end":{"line":21,"column":null}},"3":{"start":{"line":20,"column":6},"end":{"line":20,"column":null}},"4":{"start":{"line":24,"column":4},"end":{"line":26,"column":null}},"5":{"start":{"line":25,"column":6},"end":{"line":25,"column":null}},"6":{"start":{"line":29,"column":2},"end":{"line":35,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":15,"column":36},"end":{"line":15,"column":37}},"loc":{"start":{"line":15,"column":68},"end":{"line":37,"column":null}},"line":15},"1":{"name":"(anonymous_1)","decl":{"start":{"line":18,"column":12},"end":{"line":18,"column":18}},"loc":{"start":{"line":18,"column":18},"end":{"line":27,"column":5}},"line":18},"2":{"name":"(anonymous_2)","decl":{"start":{"line":19,"column":29},"end":{"line":19,"column":35}},"loc":{"start":{"line":19,"column":35},"end":{"line":21,"column":7}},"line":19},"3":{"name":"(anonymous_3)","decl":{"start":{"line":24,"column":11},"end":{"line":24,"column":17}},"loc":{"start":{"line":24,"column":17},"end":{"line":26,"column":null}},"line":24}},"branchMap":{},"s":{"0":1,"1":4,"2":4,"3":1,"4":4,"5":4,"6":4},"f":{"0":4,"1":4,"2":1,"3":4},"b":{},"meta":{"lastBranch":0,"lastFunction":4,"lastStatement":7,"seen":{"s:15:36:37:Infinity":0,"f:15:36:15:37":0,"s:18:2:27:Infinity":1,"f:18:12:18:18":1,"s:19:18:21:Infinity":2,"f:19:29:19:35":2,"s:20:6:20:Infinity":3,"s:24:4:26:Infinity":4,"f:24:11:24:17":3,"s:25:6:25:Infinity":5,"s:29:2:35:Infinity":6}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/domain/CreationForm/styles.ts": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/domain/CreationForm/styles.ts","statementMap":{"0":{"start":{"line":4,"column":29},"end":{"line":13,"column":null}},"1":{"start":{"line":5,"column":25},"end":{"line":5,"column":42}},"2":{"start":{"line":13,"column":31},"end":{"line":13,"column":54}},"3":{"start":{"line":30,"column":26},"end":{"line":30,"column":null}},"4":{"start":{"line":50,"column":21},"end":{"line":78,"column":null}},"5":{"start":{"line":54,"column":20},"end":{"line":54,"column":37}},"6":{"start":{"line":72,"column":51},"end":{"line":72,"column":69}},"7":{"start":{"line":72,"column":86},"end":{"line":72,"column":135}},"8":{"start":{"line":84,"column":21},"end":{"line":111,"column":null}},"9":{"start":{"line":89,"column":31},"end":{"line":89,"column":54}},"10":{"start":{"line":92,"column":20},"end":{"line":92,"column":37}},"11":{"start":{"line":98,"column":22},"end":{"line":98,"column":45}},"12":{"start":{"line":103,"column":33},"end":{"line":103,"column":50}},"13":{"start":{"line":104,"column":29},"end":{"line":104,"column":52}},"14":{"start":{"line":109,"column":33},"end":{"line":109,"column":50}},"15":{"start":{"line":110,"column":29},"end":{"line":110,"column":47}},"16":{"start":{"line":111,"column":37},"end":{"line":111,"column":55}},"17":{"start":{"line":117,"column":29},"end":{"line":139,"column":null}},"18":{"start":{"line":125,"column":22},"end":{"line":125,"column":45}},"19":{"start":{"line":135,"column":22},"end":{"line":135,"column":40}},"20":{"start":{"line":139,"column":22},"end":{"line":139,"column":40}},"21":{"start":{"line":145,"column":22},"end":{"line":186,"column":null}},"22":{"start":{"line":150,"column":31},"end":{"line":150,"column":54}},"23":{"start":{"line":153,"column":20},"end":{"line":153,"column":37}},"24":{"start":{"line":166,"column":33},"end":{"line":166,"column":50}},"25":{"start":{"line":167,"column":29},"end":{"line":167,"column":52}},"26":{"start":{"line":172,"column":33},"end":{"line":172,"column":50}},"27":{"start":{"line":173,"column":29},"end":{"line":173,"column":47}},"28":{"start":{"line":174,"column":37},"end":{"line":174,"column":55}},"29":{"start":{"line":180,"column":22},"end":{"line":180,"column":45}},"30":{"start":{"line":185,"column":27},"end":{"line":185,"column":44}},"31":{"start":{"line":186,"column":22},"end":{"line":186,"column":39}},"32":{"start":{"line":191,"column":29},"end":{"line":191,"column":null}},"33":{"start":{"line":197,"column":33},"end":{"line":242,"column":null}},"34":{"start":{"line":202,"column":25},"end":{"line":202,"column":42}},"35":{"start":{"line":203,"column":31},"end":{"line":203,"column":49}},"36":{"start":{"line":237,"column":27},"end":{"line":237,"column":50}},"37":{"start":{"line":242,"column":27},"end":{"line":242,"column":50}},"38":{"start":{"line":247,"column":32},"end":{"line":280,"column":null}},"39":{"start":{"line":251,"column":20},"end":{"line":251,"column":37}},"40":{"start":{"line":264,"column":27},"end":{"line":264,"column":45}},"41":{"start":{"line":271,"column":33},"end":{"line":271,"column":56}},"42":{"start":{"line":280,"column":33},"end":{"line":280,"column":56}},"43":{"start":{"line":285,"column":28},"end":{"line":288,"column":null}},"44":{"start":{"line":288,"column":20},"end":{"line":288,"column":55}},"45":{"start":{"line":303,"column":28},"end":{"line":347,"column":null}},"46":{"start":{"line":307,"column":20},"end":{"line":307,"column":37}},"47":{"start":{"line":308,"column":49},"end":{"line":308,"column":67}},"48":{"start":{"line":308,"column":84},"end":{"line":308,"column":133}},"49":{"start":{"line":314,"column":36},"end":{"line":314,"column":54}},"50":{"start":{"line":336,"column":38},"end":{"line":336,"column":56}},"51":{"start":{"line":347,"column":37},"end":{"line":347,"column":55}},"52":{"start":{"line":356,"column":24},"end":{"line":408,"column":null}},"53":{"start":{"line":363,"column":31},"end":{"line":363,"column":54}},"54":{"start":{"line":366,"column":20},"end":{"line":366,"column":37}},"55":{"start":{"line":374,"column":22},"end":{"line":374,"column":45}},"56":{"start":{"line":379,"column":33},"end":{"line":379,"column":50}},"57":{"start":{"line":380,"column":29},"end":{"line":380,"column":52}},"58":{"start":{"line":385,"column":33},"end":{"line":385,"column":50}},"59":{"start":{"line":386,"column":29},"end":{"line":386,"column":47}},"60":{"start":{"line":387,"column":37},"end":{"line":387,"column":55}},"61":{"start":{"line":398,"column":27},"end":{"line":398,"column":50}},"62":{"start":{"line":403,"column":27},"end":{"line":403,"column":50}},"63":{"start":{"line":408,"column":27},"end":{"line":408,"column":45}},"64":{"start":{"line":413,"column":30},"end":{"line":434,"column":null}},"65":{"start":{"line":416,"column":20},"end":{"line":416,"column":70}},"66":{"start":{"line":421,"column":25},"end":{"line":421,"column":48}},"67":{"start":{"line":428,"column":22},"end":{"line":428,"column":60}},"68":{"start":{"line":429,"column":27},"end":{"line":429,"column":64}},"69":{"start":{"line":433,"column":22},"end":{"line":433,"column":57}},"70":{"start":{"line":434,"column":28},"end":{"line":434,"column":37}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":5,"column":16},"end":{"line":5,"column":25}},"loc":{"start":{"line":5,"column":25},"end":{"line":5,"column":42}},"line":5},"1":{"name":"(anonymous_1)","decl":{"start":{"line":13,"column":22},"end":{"line":13,"column":31}},"loc":{"start":{"line":13,"column":31},"end":{"line":13,"column":54}},"line":13},"2":{"name":"(anonymous_2)","decl":{"start":{"line":54,"column":11},"end":{"line":54,"column":20}},"loc":{"start":{"line":54,"column":20},"end":{"line":54,"column":37}},"line":54},"3":{"name":"(anonymous_3)","decl":{"start":{"line":72,"column":42},"end":{"line":72,"column":51}},"loc":{"start":{"line":72,"column":51},"end":{"line":72,"column":69}},"line":72},"4":{"name":"(anonymous_4)","decl":{"start":{"line":72,"column":77},"end":{"line":72,"column":86}},"loc":{"start":{"line":72,"column":86},"end":{"line":72,"column":135}},"line":72},"5":{"name":"(anonymous_5)","decl":{"start":{"line":89,"column":22},"end":{"line":89,"column":31}},"loc":{"start":{"line":89,"column":31},"end":{"line":89,"column":54}},"line":89},"6":{"name":"(anonymous_6)","decl":{"start":{"line":92,"column":11},"end":{"line":92,"column":20}},"loc":{"start":{"line":92,"column":20},"end":{"line":92,"column":37}},"line":92},"7":{"name":"(anonymous_7)","decl":{"start":{"line":98,"column":13},"end":{"line":98,"column":22}},"loc":{"start":{"line":98,"column":22},"end":{"line":98,"column":45}},"line":98},"8":{"name":"(anonymous_8)","decl":{"start":{"line":103,"column":24},"end":{"line":103,"column":33}},"loc":{"start":{"line":103,"column":33},"end":{"line":103,"column":50}},"line":103},"9":{"name":"(anonymous_9)","decl":{"start":{"line":104,"column":20},"end":{"line":104,"column":29}},"loc":{"start":{"line":104,"column":29},"end":{"line":104,"column":52}},"line":104},"10":{"name":"(anonymous_10)","decl":{"start":{"line":109,"column":24},"end":{"line":109,"column":33}},"loc":{"start":{"line":109,"column":33},"end":{"line":109,"column":50}},"line":109},"11":{"name":"(anonymous_11)","decl":{"start":{"line":110,"column":20},"end":{"line":110,"column":29}},"loc":{"start":{"line":110,"column":29},"end":{"line":110,"column":47}},"line":110},"12":{"name":"(anonymous_12)","decl":{"start":{"line":111,"column":28},"end":{"line":111,"column":37}},"loc":{"start":{"line":111,"column":37},"end":{"line":111,"column":55}},"line":111},"13":{"name":"(anonymous_13)","decl":{"start":{"line":125,"column":13},"end":{"line":125,"column":22}},"loc":{"start":{"line":125,"column":22},"end":{"line":125,"column":45}},"line":125},"14":{"name":"(anonymous_14)","decl":{"start":{"line":135,"column":13},"end":{"line":135,"column":22}},"loc":{"start":{"line":135,"column":22},"end":{"line":135,"column":40}},"line":135},"15":{"name":"(anonymous_15)","decl":{"start":{"line":139,"column":13},"end":{"line":139,"column":22}},"loc":{"start":{"line":139,"column":22},"end":{"line":139,"column":40}},"line":139},"16":{"name":"(anonymous_16)","decl":{"start":{"line":150,"column":22},"end":{"line":150,"column":31}},"loc":{"start":{"line":150,"column":31},"end":{"line":150,"column":54}},"line":150},"17":{"name":"(anonymous_17)","decl":{"start":{"line":153,"column":11},"end":{"line":153,"column":20}},"loc":{"start":{"line":153,"column":20},"end":{"line":153,"column":37}},"line":153},"18":{"name":"(anonymous_18)","decl":{"start":{"line":166,"column":24},"end":{"line":166,"column":33}},"loc":{"start":{"line":166,"column":33},"end":{"line":166,"column":50}},"line":166},"19":{"name":"(anonymous_19)","decl":{"start":{"line":167,"column":20},"end":{"line":167,"column":29}},"loc":{"start":{"line":167,"column":29},"end":{"line":167,"column":52}},"line":167},"20":{"name":"(anonymous_20)","decl":{"start":{"line":172,"column":24},"end":{"line":172,"column":33}},"loc":{"start":{"line":172,"column":33},"end":{"line":172,"column":50}},"line":172},"21":{"name":"(anonymous_21)","decl":{"start":{"line":173,"column":20},"end":{"line":173,"column":29}},"loc":{"start":{"line":173,"column":29},"end":{"line":173,"column":47}},"line":173},"22":{"name":"(anonymous_22)","decl":{"start":{"line":174,"column":28},"end":{"line":174,"column":37}},"loc":{"start":{"line":174,"column":37},"end":{"line":174,"column":55}},"line":174},"23":{"name":"(anonymous_23)","decl":{"start":{"line":180,"column":13},"end":{"line":180,"column":22}},"loc":{"start":{"line":180,"column":22},"end":{"line":180,"column":45}},"line":180},"24":{"name":"(anonymous_24)","decl":{"start":{"line":185,"column":18},"end":{"line":185,"column":27}},"loc":{"start":{"line":185,"column":27},"end":{"line":185,"column":44}},"line":185},"25":{"name":"(anonymous_25)","decl":{"start":{"line":186,"column":13},"end":{"line":186,"column":22}},"loc":{"start":{"line":186,"column":22},"end":{"line":186,"column":39}},"line":186},"26":{"name":"(anonymous_26)","decl":{"start":{"line":202,"column":16},"end":{"line":202,"column":25}},"loc":{"start":{"line":202,"column":25},"end":{"line":202,"column":42}},"line":202},"27":{"name":"(anonymous_27)","decl":{"start":{"line":203,"column":22},"end":{"line":203,"column":31}},"loc":{"start":{"line":203,"column":31},"end":{"line":203,"column":49}},"line":203},"28":{"name":"(anonymous_28)","decl":{"start":{"line":237,"column":18},"end":{"line":237,"column":27}},"loc":{"start":{"line":237,"column":27},"end":{"line":237,"column":50}},"line":237},"29":{"name":"(anonymous_29)","decl":{"start":{"line":242,"column":18},"end":{"line":242,"column":27}},"loc":{"start":{"line":242,"column":27},"end":{"line":242,"column":50}},"line":242},"30":{"name":"(anonymous_30)","decl":{"start":{"line":251,"column":11},"end":{"line":251,"column":20}},"loc":{"start":{"line":251,"column":20},"end":{"line":251,"column":37}},"line":251},"31":{"name":"(anonymous_31)","decl":{"start":{"line":264,"column":18},"end":{"line":264,"column":27}},"loc":{"start":{"line":264,"column":27},"end":{"line":264,"column":45}},"line":264},"32":{"name":"(anonymous_32)","decl":{"start":{"line":271,"column":24},"end":{"line":271,"column":33}},"loc":{"start":{"line":271,"column":33},"end":{"line":271,"column":56}},"line":271},"33":{"name":"(anonymous_33)","decl":{"start":{"line":280,"column":24},"end":{"line":280,"column":33}},"loc":{"start":{"line":280,"column":33},"end":{"line":280,"column":56}},"line":280},"34":{"name":"(anonymous_34)","decl":{"start":{"line":288,"column":11},"end":{"line":288,"column":20}},"loc":{"start":{"line":288,"column":20},"end":{"line":288,"column":55}},"line":288},"35":{"name":"(anonymous_35)","decl":{"start":{"line":307,"column":11},"end":{"line":307,"column":20}},"loc":{"start":{"line":307,"column":20},"end":{"line":307,"column":37}},"line":307},"36":{"name":"(anonymous_36)","decl":{"start":{"line":308,"column":40},"end":{"line":308,"column":49}},"loc":{"start":{"line":308,"column":49},"end":{"line":308,"column":67}},"line":308},"37":{"name":"(anonymous_37)","decl":{"start":{"line":308,"column":75},"end":{"line":308,"column":84}},"loc":{"start":{"line":308,"column":84},"end":{"line":308,"column":133}},"line":308},"38":{"name":"(anonymous_38)","decl":{"start":{"line":314,"column":27},"end":{"line":314,"column":36}},"loc":{"start":{"line":314,"column":36},"end":{"line":314,"column":54}},"line":314},"39":{"name":"(anonymous_39)","decl":{"start":{"line":336,"column":29},"end":{"line":336,"column":38}},"loc":{"start":{"line":336,"column":38},"end":{"line":336,"column":56}},"line":336},"40":{"name":"(anonymous_40)","decl":{"start":{"line":347,"column":28},"end":{"line":347,"column":37}},"loc":{"start":{"line":347,"column":37},"end":{"line":347,"column":55}},"line":347},"41":{"name":"(anonymous_41)","decl":{"start":{"line":363,"column":22},"end":{"line":363,"column":31}},"loc":{"start":{"line":363,"column":31},"end":{"line":363,"column":54}},"line":363},"42":{"name":"(anonymous_42)","decl":{"start":{"line":366,"column":11},"end":{"line":366,"column":20}},"loc":{"start":{"line":366,"column":20},"end":{"line":366,"column":37}},"line":366},"43":{"name":"(anonymous_43)","decl":{"start":{"line":374,"column":13},"end":{"line":374,"column":22}},"loc":{"start":{"line":374,"column":22},"end":{"line":374,"column":45}},"line":374},"44":{"name":"(anonymous_44)","decl":{"start":{"line":379,"column":24},"end":{"line":379,"column":33}},"loc":{"start":{"line":379,"column":33},"end":{"line":379,"column":50}},"line":379},"45":{"name":"(anonymous_45)","decl":{"start":{"line":380,"column":20},"end":{"line":380,"column":29}},"loc":{"start":{"line":380,"column":29},"end":{"line":380,"column":52}},"line":380},"46":{"name":"(anonymous_46)","decl":{"start":{"line":385,"column":24},"end":{"line":385,"column":33}},"loc":{"start":{"line":385,"column":33},"end":{"line":385,"column":50}},"line":385},"47":{"name":"(anonymous_47)","decl":{"start":{"line":386,"column":20},"end":{"line":386,"column":29}},"loc":{"start":{"line":386,"column":29},"end":{"line":386,"column":47}},"line":386},"48":{"name":"(anonymous_48)","decl":{"start":{"line":387,"column":28},"end":{"line":387,"column":37}},"loc":{"start":{"line":387,"column":37},"end":{"line":387,"column":55}},"line":387},"49":{"name":"(anonymous_49)","decl":{"start":{"line":398,"column":18},"end":{"line":398,"column":27}},"loc":{"start":{"line":398,"column":27},"end":{"line":398,"column":50}},"line":398},"50":{"name":"(anonymous_50)","decl":{"start":{"line":403,"column":18},"end":{"line":403,"column":27}},"loc":{"start":{"line":403,"column":27},"end":{"line":403,"column":50}},"line":403},"51":{"name":"(anonymous_51)","decl":{"start":{"line":408,"column":18},"end":{"line":408,"column":27}},"loc":{"start":{"line":408,"column":27},"end":{"line":408,"column":45}},"line":408},"52":{"name":"(anonymous_52)","decl":{"start":{"line":416,"column":11},"end":{"line":416,"column":20}},"loc":{"start":{"line":416,"column":20},"end":{"line":416,"column":70}},"line":416},"53":{"name":"(anonymous_53)","decl":{"start":{"line":421,"column":16},"end":{"line":421,"column":25}},"loc":{"start":{"line":421,"column":25},"end":{"line":421,"column":48}},"line":421},"54":{"name":"(anonymous_54)","decl":{"start":{"line":428,"column":13},"end":{"line":428,"column":22}},"loc":{"start":{"line":428,"column":22},"end":{"line":428,"column":60}},"line":428},"55":{"name":"(anonymous_55)","decl":{"start":{"line":429,"column":18},"end":{"line":429,"column":27}},"loc":{"start":{"line":429,"column":27},"end":{"line":429,"column":64}},"line":429},"56":{"name":"(anonymous_56)","decl":{"start":{"line":433,"column":13},"end":{"line":433,"column":22}},"loc":{"start":{"line":433,"column":22},"end":{"line":433,"column":57}},"line":433},"57":{"name":"(anonymous_57)","decl":{"start":{"line":434,"column":18},"end":{"line":434,"column":28}},"loc":{"start":{"line":434,"column":28},"end":{"line":434,"column":37}},"line":434}},"branchMap":{"0":{"loc":{"start":{"line":72,"column":86},"end":{"line":72,"column":135}},"type":"binary-expr","locations":[{"start":{"line":72,"column":86},"end":{"line":72,"column":117}},{"start":{"line":72,"column":117},"end":{"line":72,"column":135}}],"line":72},"1":{"loc":{"start":{"line":288,"column":20},"end":{"line":288,"column":55}},"type":"binary-expr","locations":[{"start":{"line":288,"column":20},"end":{"line":288,"column":46}},{"start":{"line":288,"column":46},"end":{"line":288,"column":55}}],"line":288},"2":{"loc":{"start":{"line":308,"column":84},"end":{"line":308,"column":133}},"type":"binary-expr","locations":[{"start":{"line":308,"column":84},"end":{"line":308,"column":115}},{"start":{"line":308,"column":115},"end":{"line":308,"column":133}}],"line":308},"3":{"loc":{"start":{"line":416,"column":20},"end":{"line":416,"column":70}},"type":"binary-expr","locations":[{"start":{"line":416,"column":20},"end":{"line":416,"column":47}},{"start":{"line":416,"column":47},"end":{"line":416,"column":70}}],"line":416},"4":{"loc":{"start":{"line":428,"column":22},"end":{"line":428,"column":60}},"type":"binary-expr","locations":[{"start":{"line":428,"column":22},"end":{"line":428,"column":51}},{"start":{"line":428,"column":51},"end":{"line":428,"column":60}}],"line":428},"5":{"loc":{"start":{"line":429,"column":27},"end":{"line":429,"column":64}},"type":"binary-expr","locations":[{"start":{"line":429,"column":27},"end":{"line":429,"column":55}},{"start":{"line":429,"column":55},"end":{"line":429,"column":64}}],"line":429},"6":{"loc":{"start":{"line":433,"column":22},"end":{"line":433,"column":57}},"type":"binary-expr","locations":[{"start":{"line":433,"column":22},"end":{"line":433,"column":48}},{"start":{"line":433,"column":48},"end":{"line":433,"column":57}}],"line":433}},"s":{"0":2,"1":20,"2":20,"3":2,"4":2,"5":86,"6":86,"7":86,"8":2,"9":33,"10":33,"11":33,"12":33,"13":33,"14":33,"15":33,"16":33,"17":2,"18":13,"19":13,"20":13,"21":2,"22":13,"23":13,"24":13,"25":13,"26":13,"27":13,"28":13,"29":13,"30":13,"31":13,"32":2,"33":2,"34":0,"35":0,"36":0,"37":0,"38":2,"39":0,"40":0,"41":0,"42":0,"43":2,"44":0,"45":2,"46":20,"47":20,"48":20,"49":20,"50":20,"51":20,"52":2,"53":20,"54":20,"55":20,"56":20,"57":20,"58":20,"59":20,"60":20,"61":20,"62":20,"63":20,"64":2,"65":20,"66":20,"67":20,"68":20,"69":20,"70":20},"f":{"0":20,"1":20,"2":86,"3":86,"4":86,"5":33,"6":33,"7":33,"8":33,"9":33,"10":33,"11":33,"12":33,"13":13,"14":13,"15":13,"16":13,"17":13,"18":13,"19":13,"20":13,"21":13,"22":13,"23":13,"24":13,"25":13,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":20,"36":20,"37":20,"38":20,"39":20,"40":20,"41":20,"42":20,"43":20,"44":20,"45":20,"46":20,"47":20,"48":20,"49":20,"50":20,"51":20,"52":20,"53":20,"54":20,"55":20,"56":20,"57":20},"b":{"0":[86,86],"1":[0,0],"2":[20,20],"3":[20,20],"4":[20,20],"5":[20,20],"6":[20,20]},"meta":{"lastBranch":7,"lastFunction":58,"lastStatement":71,"seen":{"s:4:29:13:Infinity":0,"f:5:16:5:25":0,"s:5:25:5:42":1,"f:13:22:13:31":1,"s:13:31:13:54":2,"s:30:26:30:Infinity":3,"s:50:21:78:Infinity":4,"f:54:11:54:20":2,"s:54:20:54:37":5,"f:72:42:72:51":3,"s:72:51:72:69":6,"f:72:77:72:86":4,"s:72:86:72:135":7,"b:72:86:72:117:72:117:72:135":0,"s:84:21:111:Infinity":8,"f:89:22:89:31":5,"s:89:31:89:54":9,"f:92:11:92:20":6,"s:92:20:92:37":10,"f:98:13:98:22":7,"s:98:22:98:45":11,"f:103:24:103:33":8,"s:103:33:103:50":12,"f:104:20:104:29":9,"s:104:29:104:52":13,"f:109:24:109:33":10,"s:109:33:109:50":14,"f:110:20:110:29":11,"s:110:29:110:47":15,"f:111:28:111:37":12,"s:111:37:111:55":16,"s:117:29:139:Infinity":17,"f:125:13:125:22":13,"s:125:22:125:45":18,"f:135:13:135:22":14,"s:135:22:135:40":19,"f:139:13:139:22":15,"s:139:22:139:40":20,"s:145:22:186:Infinity":21,"f:150:22:150:31":16,"s:150:31:150:54":22,"f:153:11:153:20":17,"s:153:20:153:37":23,"f:166:24:166:33":18,"s:166:33:166:50":24,"f:167:20:167:29":19,"s:167:29:167:52":25,"f:172:24:172:33":20,"s:172:33:172:50":26,"f:173:20:173:29":21,"s:173:29:173:47":27,"f:174:28:174:37":22,"s:174:37:174:55":28,"f:180:13:180:22":23,"s:180:22:180:45":29,"f:185:18:185:27":24,"s:185:27:185:44":30,"f:186:13:186:22":25,"s:186:22:186:39":31,"s:191:29:191:Infinity":32,"s:197:33:242:Infinity":33,"f:202:16:202:25":26,"s:202:25:202:42":34,"f:203:22:203:31":27,"s:203:31:203:49":35,"f:237:18:237:27":28,"s:237:27:237:50":36,"f:242:18:242:27":29,"s:242:27:242:50":37,"s:247:32:280:Infinity":38,"f:251:11:251:20":30,"s:251:20:251:37":39,"f:264:18:264:27":31,"s:264:27:264:45":40,"f:271:24:271:33":32,"s:271:33:271:56":41,"f:280:24:280:33":33,"s:280:33:280:56":42,"s:285:28:288:Infinity":43,"f:288:11:288:20":34,"s:288:20:288:55":44,"b:288:20:288:46:288:46:288:55":1,"s:303:28:347:Infinity":45,"f:307:11:307:20":35,"s:307:20:307:37":46,"f:308:40:308:49":36,"s:308:49:308:67":47,"f:308:75:308:84":37,"s:308:84:308:133":48,"b:308:84:308:115:308:115:308:133":2,"f:314:27:314:36":38,"s:314:36:314:54":49,"f:336:29:336:38":39,"s:336:38:336:56":50,"f:347:28:347:37":40,"s:347:37:347:55":51,"s:356:24:408:Infinity":52,"f:363:22:363:31":41,"s:363:31:363:54":53,"f:366:11:366:20":42,"s:366:20:366:37":54,"f:374:13:374:22":43,"s:374:22:374:45":55,"f:379:24:379:33":44,"s:379:33:379:50":56,"f:380:20:380:29":45,"s:380:29:380:52":57,"f:385:24:385:33":46,"s:385:33:385:50":58,"f:386:20:386:29":47,"s:386:29:386:47":59,"f:387:28:387:37":48,"s:387:37:387:55":60,"f:398:18:398:27":49,"s:398:27:398:50":61,"f:403:18:403:27":50,"s:403:27:403:50":62,"f:408:18:408:27":51,"s:408:27:408:45":63,"s:413:30:434:Infinity":64,"f:416:11:416:20":52,"s:416:20:416:70":65,"b:416:20:416:47:416:47:416:70":3,"f:421:16:421:25":53,"s:421:25:421:48":66,"f:428:13:428:22":54,"s:428:22:428:60":67,"b:428:22:428:51:428:51:428:60":4,"f:429:18:429:27":55,"s:429:27:429:64":68,"b:429:27:429:55:429:55:429:64":5,"f:433:13:433:22":56,"s:433:22:433:57":69,"b:433:22:433:48:433:48:433:57":6,"f:434:18:434:28":57,"s:434:28:434:37":70}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/domain/Postcard/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/domain/Postcard/index.tsx","statementMap":{"0":{"start":{"line":15,"column":18},"end":{"line":19,"column":null}},"1":{"start":{"line":16,"column":2},"end":{"line":19,"column":null}},"2":{"start":{"line":23,"column":20},"end":{"line":26,"column":null}},"3":{"start":{"line":24,"column":2},"end":{"line":26,"column":null}},"4":{"start":{"line":31,"column":21},"end":{"line":34,"column":null}},"5":{"start":{"line":32,"column":2},"end":{"line":34,"column":null}},"6":{"start":{"line":46,"column":22},"end":{"line":46,"column":null}},"7":{"start":{"line":48,"column":34},"end":{"line":48,"column":null}},"8":{"start":{"line":49,"column":8},"end":{"line":49,"column":null}},"9":{"start":{"line":50,"column":8},"end":{"line":50,"column":null}},"10":{"start":{"line":51,"column":48},"end":{"line":51,"column":null}},"11":{"start":{"line":52,"column":38},"end":{"line":52,"column":null}},"12":{"start":{"line":55,"column":46},"end":{"line":55,"column":null}},"13":{"start":{"line":56,"column":36},"end":{"line":56,"column":null}},"14":{"start":{"line":57,"column":52},"end":{"line":57,"column":null}},"15":{"start":{"line":58,"column":28},"end":{"line":58,"column":null}},"16":{"start":{"line":59,"column":30},"end":{"line":59,"column":null}},"17":{"start":{"line":61,"column":44},"end":{"line":61,"column":null}},"18":{"start":{"line":63,"column":21},"end":{"line":63,"column":null}},"19":{"start":{"line":65,"column":2},"end":{"line":69,"column":null}},"20":{"start":{"line":66,"column":4},"end":{"line":68,"column":null}},"21":{"start":{"line":67,"column":8},"end":{"line":67,"column":null}},"22":{"start":{"line":72,"column":6},"end":{"line":77,"column":null}},"23":{"start":{"line":73,"column":23},"end":{"line":73,"column":null}},"24":{"start":{"line":74,"column":10},"end":{"line":74,"column":null}},"25":{"start":{"line":76,"column":10},"end":{"line":76,"column":null}},"26":{"start":{"line":81,"column":2},"end":{"line":93,"column":null}},"27":{"start":{"line":83,"column":6},"end":{"line":85,"column":null}},"28":{"start":{"line":84,"column":8},"end":{"line":84,"column":null}},"29":{"start":{"line":87,"column":4},"end":{"line":89,"column":null}},"30":{"start":{"line":88,"column":6},"end":{"line":88,"column":null}},"31":{"start":{"line":90,"column":4},"end":{"line":92,"column":null}},"32":{"start":{"line":91,"column":6},"end":{"line":91,"column":null}},"33":{"start":{"line":95,"column":26},"end":{"line":103,"column":null}},"34":{"start":{"line":96,"column":23},"end":{"line":96,"column":null}},"35":{"start":{"line":98,"column":4},"end":{"line":102,"column":null}},"36":{"start":{"line":99,"column":8},"end":{"line":99,"column":null}},"37":{"start":{"line":101,"column":8},"end":{"line":101,"column":null}},"38":{"start":{"line":105,"column":31},"end":{"line":124,"column":null}},"39":{"start":{"line":106,"column":4},"end":{"line":123,"column":null}},"40":{"start":{"line":107,"column":19},"end":{"line":107,"column":null}},"41":{"start":{"line":109,"column":7},"end":{"line":109,"column":null}},"42":{"start":{"line":109,"column":16},"end":{"line":109,"column":null}},"43":{"start":{"line":111,"column":7},"end":{"line":116,"column":null}},"44":{"start":{"line":112,"column":11},"end":{"line":112,"column":null}},"45":{"start":{"line":114,"column":11},"end":{"line":114,"column":null}},"46":{"start":{"line":115,"column":11},"end":{"line":115,"column":null}},"47":{"start":{"line":115,"column":28},"end":{"line":115,"column":47}},"48":{"start":{"line":118,"column":7},"end":{"line":118,"column":null}},"49":{"start":{"line":119,"column":7},"end":{"line":119,"column":null}},"50":{"start":{"line":122,"column":6},"end":{"line":122,"column":null}},"51":{"start":{"line":126,"column":30},"end":{"line":151,"column":null}},"52":{"start":{"line":127,"column":4},"end":{"line":127,"column":null}},"53":{"start":{"line":129,"column":4},"end":{"line":132,"column":null}},"54":{"start":{"line":130,"column":8},"end":{"line":130,"column":null}},"55":{"start":{"line":131,"column":8},"end":{"line":131,"column":null}},"56":{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},"57":{"start":{"line":134,"column":29},"end":{"line":134,"column":null}},"58":{"start":{"line":136,"column":4},"end":{"line":150,"column":null}},"59":{"start":{"line":137,"column":8},"end":{"line":137,"column":null}},"60":{"start":{"line":138,"column":8},"end":{"line":138,"column":null}},"61":{"start":{"line":140,"column":8},"end":{"line":140,"column":null}},"62":{"start":{"line":141,"column":8},"end":{"line":141,"column":null}},"63":{"start":{"line":142,"column":8},"end":{"line":142,"column":null}},"64":{"start":{"line":145,"column":8},"end":{"line":147,"column":null}},"65":{"start":{"line":146,"column":12},"end":{"line":146,"column":null}},"66":{"start":{"line":149,"column":8},"end":{"line":149,"column":null}},"67":{"start":{"line":153,"column":45},"end":{"line":164,"column":null}},"68":{"start":{"line":154,"column":4},"end":{"line":154,"column":null}},"69":{"start":{"line":154,"column":26},"end":{"line":154,"column":null}},"70":{"start":{"line":155,"column":4},"end":{"line":163,"column":null}},"71":{"start":{"line":156,"column":8},"end":{"line":156,"column":null}},"72":{"start":{"line":157,"column":8},"end":{"line":157,"column":null}},"73":{"start":{"line":158,"column":8},"end":{"line":158,"column":null}},"74":{"start":{"line":159,"column":8},"end":{"line":159,"column":null}},"75":{"start":{"line":161,"column":8},"end":{"line":161,"column":null}},"76":{"start":{"line":162,"column":8},"end":{"line":162,"column":null}},"77":{"start":{"line":166,"column":26},"end":{"line":188,"column":null}},"78":{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},"79":{"start":{"line":168,"column":35},"end":{"line":168,"column":null}},"80":{"start":{"line":171,"column":19},"end":{"line":171,"column":null}},"81":{"start":{"line":174,"column":4},"end":{"line":182,"column":null}},"82":{"start":{"line":181,"column":8},"end":{"line":181,"column":null}},"83":{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},"84":{"start":{"line":186,"column":8},"end":{"line":186,"column":null}},"85":{"start":{"line":190,"column":21},"end":{"line":195,"column":null}},"86":{"start":{"line":191,"column":6},"end":{"line":191,"column":null}},"87":{"start":{"line":191,"column":23},"end":{"line":191,"column":null}},"88":{"start":{"line":192,"column":6},"end":{"line":194,"column":null}},"89":{"start":{"line":197,"column":2},"end":{"line":348,"column":null}},"90":{"start":{"line":203,"column":25},"end":{"line":203,"column":null}},"91":{"start":{"line":216,"column":41},"end":{"line":216,"column":null}},"92":{"start":{"line":216,"column":63},"end":{"line":216,"column":68}},"93":{"start":{"line":226,"column":20},"end":{"line":226,"column":null}},"94":{"start":{"line":227,"column":20},"end":{"line":227,"column":47}},"95":{"start":{"line":238,"column":43},"end":{"line":238,"column":null}},"96":{"start":{"line":250,"column":41},"end":{"line":250,"column":null}},"97":{"start":{"line":272,"column":45},"end":{"line":272,"column":null}},"98":{"start":{"line":274,"column":28},"end":{"line":296,"column":null}},"99":{"start":{"line":287,"column":67},"end":{"line":287,"column":null}},"100":{"start":{"line":307,"column":23},"end":{"line":307,"column":null}},"101":{"start":{"line":315,"column":52},"end":{"line":315,"column":81}},"102":{"start":{"line":327,"column":23},"end":{"line":327,"column":null}},"103":{"start":{"line":335,"column":52},"end":{"line":335,"column":78}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":15,"column":18},"end":{"line":15,"column":null}},"loc":{"start":{"line":16,"column":2},"end":{"line":19,"column":null}},"line":16},"1":{"name":"(anonymous_1)","decl":{"start":{"line":23,"column":20},"end":{"line":23,"column":null}},"loc":{"start":{"line":24,"column":2},"end":{"line":26,"column":null}},"line":24},"2":{"name":"(anonymous_2)","decl":{"start":{"line":31,"column":21},"end":{"line":31,"column":null}},"loc":{"start":{"line":32,"column":2},"end":{"line":34,"column":null}},"line":32},"3":{"name":"Postcard","decl":{"start":{"line":45,"column":24},"end":{"line":45,"column":33}},"loc":{"start":{"line":45,"column":103},"end":{"line":350,"column":null}},"line":45},"4":{"name":"(anonymous_4)","decl":{"start":{"line":65,"column":12},"end":{"line":65,"column":18}},"loc":{"start":{"line":65,"column":18},"end":{"line":69,"column":5}},"line":65},"5":{"name":"loadComments","decl":{"start":{"line":71,"column":17},"end":{"line":71,"column":32}},"loc":{"start":{"line":71,"column":32},"end":{"line":78,"column":null}},"line":71},"6":{"name":"(anonymous_6)","decl":{"start":{"line":81,"column":12},"end":{"line":81,"column":18}},"loc":{"start":{"line":81,"column":18},"end":{"line":93,"column":5}},"line":81},"7":{"name":"handleClickOutside","decl":{"start":{"line":82,"column":13},"end":{"line":82,"column":32}},"loc":{"start":{"line":82,"column":51},"end":{"line":86,"column":null}},"line":82},"8":{"name":"(anonymous_8)","decl":{"start":{"line":90,"column":11},"end":{"line":90,"column":17}},"loc":{"start":{"line":90,"column":17},"end":{"line":92,"column":null}},"line":90},"9":{"name":"(anonymous_9)","decl":{"start":{"line":95,"column":26},"end":{"line":95,"column":32}},"loc":{"start":{"line":95,"column":32},"end":{"line":103,"column":null}},"line":95},"10":{"name":"(anonymous_10)","decl":{"start":{"line":105,"column":31},"end":{"line":105,"column":43}},"loc":{"start":{"line":105,"column":43},"end":{"line":124,"column":null}},"line":105},"11":{"name":"(anonymous_11)","decl":{"start":{"line":115,"column":22},"end":{"line":115,"column":28}},"loc":{"start":{"line":115,"column":28},"end":{"line":115,"column":47}},"line":115},"12":{"name":"(anonymous_12)","decl":{"start":{"line":126,"column":30},"end":{"line":126,"column":37}},"loc":{"start":{"line":126,"column":60},"end":{"line":151,"column":null}},"line":126},"13":{"name":"(anonymous_13)","decl":{"start":{"line":153,"column":45},"end":{"line":153,"column":57}},"loc":{"start":{"line":153,"column":57},"end":{"line":164,"column":null}},"line":153},"14":{"name":"(anonymous_14)","decl":{"start":{"line":166,"column":26},"end":{"line":166,"column":27}},"loc":{"start":{"line":166,"column":51},"end":{"line":188,"column":null}},"line":166},"15":{"name":"(anonymous_15)","decl":{"start":{"line":190,"column":21},"end":{"line":190,"column":22}},"loc":{"start":{"line":190,"column":46},"end":{"line":195,"column":null}},"line":190},"16":{"name":"(anonymous_16)","decl":{"start":{"line":203,"column":19},"end":{"line":203,"column":25}},"loc":{"start":{"line":203,"column":25},"end":{"line":203,"column":null}},"line":203},"17":{"name":"(anonymous_17)","decl":{"start":{"line":216,"column":35},"end":{"line":216,"column":41}},"loc":{"start":{"line":216,"column":41},"end":{"line":216,"column":null}},"line":216},"18":{"name":"(anonymous_18)","decl":{"start":{"line":216,"column":55},"end":{"line":216,"column":63}},"loc":{"start":{"line":216,"column":63},"end":{"line":216,"column":68}},"line":216},"19":{"name":"(anonymous_19)","decl":{"start":{"line":225,"column":43},"end":{"line":225,"column":49}},"loc":{"start":{"line":225,"column":49},"end":{"line":227,"column":50}},"line":225},"20":{"name":"(anonymous_20)","decl":{"start":{"line":238,"column":37},"end":{"line":238,"column":43}},"loc":{"start":{"line":238,"column":43},"end":{"line":238,"column":null}},"line":238},"21":{"name":"(anonymous_21)","decl":{"start":{"line":250,"column":34},"end":{"line":250,"column":35}},"loc":{"start":{"line":250,"column":41},"end":{"line":250,"column":null}},"line":250},"22":{"name":"(anonymous_22)","decl":{"start":{"line":270,"column":38},"end":{"line":270,"column":39}},"loc":{"start":{"line":270,"column":51},"end":{"line":298,"column":25}},"line":270},"23":{"name":"(anonymous_23)","decl":{"start":{"line":287,"column":61},"end":{"line":287,"column":67}},"loc":{"start":{"line":287,"column":67},"end":{"line":287,"column":null}},"line":287},"24":{"name":"(anonymous_24)","decl":{"start":{"line":307,"column":17},"end":{"line":307,"column":23}},"loc":{"start":{"line":307,"column":23},"end":{"line":307,"column":null}},"line":307},"25":{"name":"(anonymous_25)","decl":{"start":{"line":315,"column":46},"end":{"line":315,"column":52}},"loc":{"start":{"line":315,"column":52},"end":{"line":315,"column":81}},"line":315},"26":{"name":"(anonymous_26)","decl":{"start":{"line":327,"column":17},"end":{"line":327,"column":23}},"loc":{"start":{"line":327,"column":23},"end":{"line":327,"column":null}},"line":327},"27":{"name":"(anonymous_27)","decl":{"start":{"line":335,"column":46},"end":{"line":335,"column":52}},"loc":{"start":{"line":335,"column":52},"end":{"line":335,"column":78}},"line":335}},"branchMap":{"0":{"loc":{"start":{"line":45,"column":61},"end":{"line":45,"column":85}},"type":"default-arg","locations":[{"start":{"line":45,"column":75},"end":{"line":45,"column":85}}],"line":45},"1":{"loc":{"start":{"line":63,"column":21},"end":{"line":63,"column":null}},"type":"binary-expr","locations":[{"start":{"line":63,"column":21},"end":{"line":63,"column":41}},{"start":{"line":63,"column":41},"end":{"line":63,"column":null}}],"line":63},"2":{"loc":{"start":{"line":66,"column":4},"end":{"line":68,"column":null}},"type":"if","locations":[{"start":{"line":66,"column":4},"end":{"line":68,"column":null}},{"start":{},"end":{}}],"line":66},"3":{"loc":{"start":{"line":66,"column":8},"end":{"line":66,"column":39}},"type":"binary-expr","locations":[{"start":{"line":66,"column":8},"end":{"line":66,"column":28}},{"start":{"line":66,"column":28},"end":{"line":66,"column":39}}],"line":66},"4":{"loc":{"start":{"line":83,"column":6},"end":{"line":85,"column":null}},"type":"if","locations":[{"start":{"line":83,"column":6},"end":{"line":85,"column":null}},{"start":{},"end":{}}],"line":83},"5":{"loc":{"start":{"line":83,"column":10},"end":{"line":83,"column":78}},"type":"binary-expr","locations":[{"start":{"line":83,"column":10},"end":{"line":83,"column":29}},{"start":{"line":83,"column":29},"end":{"line":83,"column":78}}],"line":83},"6":{"loc":{"start":{"line":87,"column":4},"end":{"line":89,"column":null}},"type":"if","locations":[{"start":{"line":87,"column":4},"end":{"line":89,"column":null}},{"start":{},"end":{}}],"line":87},"7":{"loc":{"start":{"line":96,"column":23},"end":{"line":96,"column":null}},"type":"binary-expr","locations":[{"start":{"line":96,"column":23},"end":{"line":96,"column":43}},{"start":{"line":96,"column":43},"end":{"line":96,"column":null}}],"line":96},"8":{"loc":{"start":{"line":98,"column":4},"end":{"line":102,"column":null}},"type":"if","locations":[{"start":{"line":98,"column":4},"end":{"line":102,"column":null}},{"start":{"line":100,"column":11},"end":{"line":102,"column":null}}],"line":98},"9":{"loc":{"start":{"line":107,"column":19},"end":{"line":107,"column":null}},"type":"binary-expr","locations":[{"start":{"line":107,"column":19},"end":{"line":107,"column":39}},{"start":{"line":107,"column":39},"end":{"line":107,"column":66}},{"start":{"line":107,"column":66},"end":{"line":107,"column":null}}],"line":107},"10":{"loc":{"start":{"line":109,"column":7},"end":{"line":109,"column":null}},"type":"if","locations":[{"start":{"line":109,"column":7},"end":{"line":109,"column":null}},{"start":{},"end":{}}],"line":109},"11":{"loc":{"start":{"line":111,"column":7},"end":{"line":116,"column":null}},"type":"if","locations":[{"start":{"line":111,"column":7},"end":{"line":116,"column":null}},{"start":{"line":113,"column":14},"end":{"line":116,"column":null}}],"line":111},"12":{"loc":{"start":{"line":129,"column":4},"end":{"line":132,"column":null}},"type":"if","locations":[{"start":{"line":129,"column":4},"end":{"line":132,"column":null}},{"start":{},"end":{}}],"line":129},"13":{"loc":{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},"type":"if","locations":[{"start":{"line":134,"column":4},"end":{"line":134,"column":null}},{"start":{},"end":{}}],"line":134},"14":{"loc":{"start":{"line":145,"column":8},"end":{"line":147,"column":null}},"type":"if","locations":[{"start":{"line":145,"column":8},"end":{"line":147,"column":null}},{"start":{},"end":{}}],"line":145},"15":{"loc":{"start":{"line":154,"column":4},"end":{"line":154,"column":null}},"type":"if","locations":[{"start":{"line":154,"column":4},"end":{"line":154,"column":null}},{"start":{},"end":{}}],"line":154},"16":{"loc":{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},"type":"if","locations":[{"start":{"line":168,"column":4},"end":{"line":168,"column":null}},{"start":{},"end":{}}],"line":168},"17":{"loc":{"start":{"line":174,"column":4},"end":{"line":182,"column":null}},"type":"if","locations":[{"start":{"line":174,"column":4},"end":{"line":182,"column":null}},{"start":{},"end":{}}],"line":174},"18":{"loc":{"start":{"line":175,"column":8},"end":{"line":179,"column":null}},"type":"binary-expr","locations":[{"start":{"line":175,"column":8},"end":{"line":175,"column":null}},{"start":{"line":176,"column":8},"end":{"line":176,"column":null}},{"start":{"line":177,"column":8},"end":{"line":177,"column":null}},{"start":{"line":178,"column":8},"end":{"line":178,"column":null}},{"start":{"line":179,"column":8},"end":{"line":179,"column":null}}],"line":175},"19":{"loc":{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},"type":"if","locations":[{"start":{"line":185,"column":4},"end":{"line":187,"column":null}},{"start":{},"end":{}}],"line":185},"20":{"loc":{"start":{"line":191,"column":6},"end":{"line":191,"column":null}},"type":"if","locations":[{"start":{"line":191,"column":6},"end":{"line":191,"column":null}},{"start":{},"end":{}}],"line":191},"21":{"loc":{"start":{"line":199,"column":7},"end":{"line":204,"column":null}},"type":"binary-expr","locations":[{"start":{"line":199,"column":7},"end":{"line":199,"column":null}},{"start":{"line":200,"column":8},"end":{"line":204,"column":null}}],"line":199},"22":{"loc":{"start":{"line":208,"column":19},"end":{"line":208,"column":75}},"type":"binary-expr","locations":[{"start":{"line":208,"column":19},"end":{"line":208,"column":45}},{"start":{"line":208,"column":45},"end":{"line":208,"column":75}}],"line":208},"23":{"loc":{"start":{"line":210,"column":19},"end":{"line":210,"column":57}},"type":"binary-expr","locations":[{"start":{"line":210,"column":19},"end":{"line":210,"column":49}},{"start":{"line":210,"column":49},"end":{"line":210,"column":57}}],"line":210},"24":{"loc":{"start":{"line":214,"column":9},"end":{"line":232,"column":null}},"type":"binary-expr","locations":[{"start":{"line":214,"column":9},"end":{"line":214,"column":null}},{"start":{"line":215,"column":10},"end":{"line":232,"column":null}}],"line":214},"25":{"loc":{"start":{"line":220,"column":13},"end":{"line":230,"column":null}},"type":"binary-expr","locations":[{"start":{"line":220,"column":13},"end":{"line":220,"column":null}},{"start":{"line":221,"column":14},"end":{"line":230,"column":null}}],"line":220},"26":{"loc":{"start":{"line":222,"column":17},"end":{"line":223,"column":null}},"type":"binary-expr","locations":[{"start":{"line":222,"column":17},"end":{"line":222,"column":null}},{"start":{"line":223,"column":20},"end":{"line":223,"column":null}}],"line":222},"27":{"loc":{"start":{"line":244,"column":9},"end":{"line":301,"column":null}},"type":"binary-expr","locations":[{"start":{"line":244,"column":9},"end":{"line":244,"column":null}},{"start":{"line":245,"column":12},"end":{"line":301,"column":null}}],"line":244},"28":{"loc":{"start":{"line":260,"column":38},"end":{"line":260,"column":null}},"type":"binary-expr","locations":[{"start":{"line":260,"column":38},"end":{"line":260,"column":61}},{"start":{"line":260,"column":61},"end":{"line":260,"column":null}}],"line":260},"29":{"loc":{"start":{"line":262,"column":29},"end":{"line":262,"column":null}},"type":"cond-expr","locations":[{"start":{"line":262,"column":51},"end":{"line":262,"column":67}},{"start":{"line":262,"column":67},"end":{"line":262,"column":null}}],"line":262},"30":{"loc":{"start":{"line":268,"column":17},"end":{"line":299,"column":null}},"type":"binary-expr","locations":[{"start":{"line":268,"column":17},"end":{"line":268,"column":null}},{"start":{"line":269,"column":20},"end":{"line":299,"column":null}}],"line":268},"31":{"loc":{"start":{"line":272,"column":45},"end":{"line":272,"column":null}},"type":"binary-expr","locations":[{"start":{"line":272,"column":45},"end":{"line":272,"column":64}},{"start":{"line":272,"column":64},"end":{"line":272,"column":null}}],"line":272},"32":{"loc":{"start":{"line":280,"column":57},"end":{"line":280,"column":87}},"type":"binary-expr","locations":[{"start":{"line":280,"column":57},"end":{"line":280,"column":77}},{"start":{"line":280,"column":77},"end":{"line":280,"column":87}}],"line":280},"33":{"loc":{"start":{"line":285,"column":45},"end":{"line":291,"column":null}},"type":"binary-expr","locations":[{"start":{"line":285,"column":45},"end":{"line":285,"column":null}},{"start":{"line":286,"column":48},"end":{"line":291,"column":null}}],"line":285},"34":{"loc":{"start":{"line":275,"column":52},"end":{"line":275,"column":null}},"type":"binary-expr","locations":[{"start":{"line":275,"column":52},"end":{"line":275,"column":73}},{"start":{"line":275,"column":73},"end":{"line":275,"column":null}}],"line":275}},"s":{"0":1,"1":0,"2":1,"3":21,"4":1,"5":12,"6":21,"7":21,"8":21,"9":21,"10":21,"11":21,"12":21,"13":21,"14":21,"15":21,"16":21,"17":21,"18":21,"19":21,"20":10,"21":2,"22":2,"23":2,"24":2,"25":0,"26":21,"27":0,"28":0,"29":13,"30":4,"31":13,"32":13,"33":21,"34":1,"35":1,"36":1,"37":0,"38":21,"39":2,"40":2,"41":2,"42":0,"43":2,"44":0,"45":2,"46":1,"47":0,"48":1,"49":1,"50":1,"51":21,"52":1,"53":1,"54":0,"55":0,"56":1,"57":0,"58":1,"59":1,"60":1,"61":1,"62":1,"63":1,"64":0,"65":0,"66":1,"67":21,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":21,"78":12,"79":0,"80":12,"81":12,"82":12,"83":0,"84":0,"85":21,"86":1,"87":1,"88":0,"89":21,"90":0,"91":4,"92":4,"93":2,"94":2,"95":2,"96":1,"97":1,"98":1,"99":0,"100":0,"101":0,"102":0,"103":0},"f":{"0":0,"1":21,"2":12,"3":21,"4":10,"5":2,"6":13,"7":0,"8":13,"9":1,"10":2,"11":0,"12":1,"13":0,"14":12,"15":1,"16":0,"17":4,"18":4,"19":2,"20":2,"21":1,"22":1,"23":0,"24":0,"25":0,"26":0,"27":0},"b":{"0":[21],"1":[21,0],"2":[2,8],"3":[10,2],"4":[0,0],"5":[0,0],"6":[4,9],"7":[1,0],"8":[1,0],"9":[2,0,0],"10":[0,2],"11":[0,2],"12":[0,1],"13":[0,1],"14":[0,0],"15":[0,0],"16":[0,12],"17":[12,0],"18":[12,0,0,0,0],"19":[0,0],"20":[1,0],"21":[21,3],"22":[21,21],"23":[21,0],"24":[21,12],"25":[12,4],"26":[4,4],"27":[21,5],"28":[5,4],"29":[1,4],"30":[5,1],"31":[1,1],"32":[1,0],"33":[1,0],"34":[1,0]},"meta":{"lastBranch":35,"lastFunction":28,"lastStatement":104,"seen":{"s:15:18:19:Infinity":0,"f:15:18:15:Infinity":0,"s:16:2:19:Infinity":1,"s:23:20:26:Infinity":2,"f:23:20:23:Infinity":1,"s:24:2:26:Infinity":3,"s:31:21:34:Infinity":4,"f:31:21:31:Infinity":2,"s:32:2:34:Infinity":5,"f:45:24:45:33":3,"b:45:75:45:85":0,"s:46:22:46:Infinity":6,"s:48:34:48:Infinity":7,"s:49:8:49:Infinity":8,"s:50:8:50:Infinity":9,"s:51:48:51:Infinity":10,"s:52:38:52:Infinity":11,"s:55:46:55:Infinity":12,"s:56:36:56:Infinity":13,"s:57:52:57:Infinity":14,"s:58:28:58:Infinity":15,"s:59:30:59:Infinity":16,"s:61:44:61:Infinity":17,"s:63:21:63:Infinity":18,"b:63:21:63:41:63:41:63:Infinity":1,"s:65:2:69:Infinity":19,"f:65:12:65:18":4,"b:66:4:68:Infinity:undefined:undefined:undefined:undefined":2,"s:66:4:68:Infinity":20,"b:66:8:66:28:66:28:66:39":3,"s:67:8:67:Infinity":21,"f:71:17:71:32":5,"s:72:6:77:Infinity":22,"s:73:23:73:Infinity":23,"s:74:10:74:Infinity":24,"s:76:10:76:Infinity":25,"s:81:2:93:Infinity":26,"f:81:12:81:18":6,"f:82:13:82:32":7,"b:83:6:85:Infinity:undefined:undefined:undefined:undefined":4,"s:83:6:85:Infinity":27,"b:83:10:83:29:83:29:83:78":5,"s:84:8:84:Infinity":28,"b:87:4:89:Infinity:undefined:undefined:undefined:undefined":6,"s:87:4:89:Infinity":29,"s:88:6:88:Infinity":30,"s:90:4:92:Infinity":31,"f:90:11:90:17":8,"s:91:6:91:Infinity":32,"s:95:26:103:Infinity":33,"f:95:26:95:32":9,"s:96:23:96:Infinity":34,"b:96:23:96:43:96:43:96:Infinity":7,"b:98:4:102:Infinity:100:11:102:Infinity":8,"s:98:4:102:Infinity":35,"s:99:8:99:Infinity":36,"s:101:8:101:Infinity":37,"s:105:31:124:Infinity":38,"f:105:31:105:43":10,"s:106:4:123:Infinity":39,"s:107:19:107:Infinity":40,"b:107:19:107:39:107:39:107:66:107:66:107:Infinity":9,"b:109:7:109:Infinity:undefined:undefined:undefined:undefined":10,"s:109:7:109:Infinity":41,"s:109:16:109:Infinity":42,"b:111:7:116:Infinity:113:14:116:Infinity":11,"s:111:7:116:Infinity":43,"s:112:11:112:Infinity":44,"s:114:11:114:Infinity":45,"s:115:11:115:Infinity":46,"f:115:22:115:28":11,"s:115:28:115:47":47,"s:118:7:118:Infinity":48,"s:119:7:119:Infinity":49,"s:122:6:122:Infinity":50,"s:126:30:151:Infinity":51,"f:126:30:126:37":12,"s:127:4:127:Infinity":52,"b:129:4:132:Infinity:undefined:undefined:undefined:undefined":12,"s:129:4:132:Infinity":53,"s:130:8:130:Infinity":54,"s:131:8:131:Infinity":55,"b:134:4:134:Infinity:undefined:undefined:undefined:undefined":13,"s:134:4:134:Infinity":56,"s:134:29:134:Infinity":57,"s:136:4:150:Infinity":58,"s:137:8:137:Infinity":59,"s:138:8:138:Infinity":60,"s:140:8:140:Infinity":61,"s:141:8:141:Infinity":62,"s:142:8:142:Infinity":63,"b:145:8:147:Infinity:undefined:undefined:undefined:undefined":14,"s:145:8:147:Infinity":64,"s:146:12:146:Infinity":65,"s:149:8:149:Infinity":66,"s:153:45:164:Infinity":67,"f:153:45:153:57":13,"b:154:4:154:Infinity:undefined:undefined:undefined:undefined":15,"s:154:4:154:Infinity":68,"s:154:26:154:Infinity":69,"s:155:4:163:Infinity":70,"s:156:8:156:Infinity":71,"s:157:8:157:Infinity":72,"s:158:8:158:Infinity":73,"s:159:8:159:Infinity":74,"s:161:8:161:Infinity":75,"s:162:8:162:Infinity":76,"s:166:26:188:Infinity":77,"f:166:26:166:27":14,"b:168:4:168:Infinity:undefined:undefined:undefined:undefined":16,"s:168:4:168:Infinity":78,"s:168:35:168:Infinity":79,"s:171:19:171:Infinity":80,"b:174:4:182:Infinity:undefined:undefined:undefined:undefined":17,"s:174:4:182:Infinity":81,"b:175:8:175:Infinity:176:8:176:Infinity:177:8:177:Infinity:178:8:178:Infinity:179:8:179:Infinity":18,"s:181:8:181:Infinity":82,"b:185:4:187:Infinity:undefined:undefined:undefined:undefined":19,"s:185:4:187:Infinity":83,"s:186:8:186:Infinity":84,"s:190:21:195:Infinity":85,"f:190:21:190:22":15,"b:191:6:191:Infinity:undefined:undefined:undefined:undefined":20,"s:191:6:191:Infinity":86,"s:191:23:191:Infinity":87,"s:192:6:194:Infinity":88,"s:197:2:348:Infinity":89,"b:199:7:199:Infinity:200:8:204:Infinity":21,"f:203:19:203:25":16,"s:203:25:203:Infinity":90,"b:208:19:208:45:208:45:208:75":22,"b:210:19:210:49:210:49:210:57":23,"b:214:9:214:Infinity:215:10:232:Infinity":24,"f:216:35:216:41":17,"s:216:41:216:Infinity":91,"f:216:55:216:63":18,"s:216:63:216:68":92,"b:220:13:220:Infinity:221:14:230:Infinity":25,"b:222:17:222:Infinity:223:20:223:Infinity":26,"f:225:43:225:49":19,"s:226:20:226:Infinity":93,"s:227:20:227:47":94,"f:238:37:238:43":20,"s:238:43:238:Infinity":95,"b:244:9:244:Infinity:245:12:301:Infinity":27,"f:250:34:250:35":21,"s:250:41:250:Infinity":96,"b:260:38:260:61:260:61:260:Infinity":28,"b:262:51:262:67:262:67:262:Infinity":29,"b:268:17:268:Infinity:269:20:299:Infinity":30,"f:270:38:270:39":22,"s:272:45:272:Infinity":97,"b:272:45:272:64:272:64:272:Infinity":31,"s:274:28:296:Infinity":98,"b:280:57:280:77:280:77:280:87":32,"b:285:45:285:Infinity:286:48:291:Infinity":33,"f:287:61:287:67":23,"s:287:67:287:Infinity":99,"b:275:52:275:73:275:73:275:Infinity":34,"f:307:17:307:23":24,"s:307:23:307:Infinity":100,"f:315:46:315:52":25,"s:315:52:315:81":101,"f:327:17:327:23":26,"s:327:23:327:Infinity":102,"f:335:46:335:52":27,"s:335:52:335:78":103}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/domain/Searchbar/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/domain/Searchbar/index.tsx","statementMap":{"0":{"start":{"line":12,"column":26},"end":{"line":12,"column":null}},"1":{"start":{"line":13,"column":10},"end":{"line":13,"column":null}},"2":{"start":{"line":15,"column":10},"end":{"line":15,"column":null}},"3":{"start":{"line":17,"column":34},"end":{"line":17,"column":null}},"4":{"start":{"line":18,"column":34},"end":{"line":18,"column":null}},"5":{"start":{"line":21,"column":44},"end":{"line":21,"column":null}},"6":{"start":{"line":22,"column":38},"end":{"line":22,"column":null}},"7":{"start":{"line":25,"column":54},"end":{"line":25,"column":null}},"8":{"start":{"line":26,"column":48},"end":{"line":26,"column":null}},"9":{"start":{"line":28,"column":24},"end":{"line":47,"column":null}},"10":{"start":{"line":29,"column":8},"end":{"line":29,"column":null}},"11":{"start":{"line":30,"column":8},"end":{"line":46,"column":null}},"12":{"start":{"line":31,"column":12},"end":{"line":31,"column":null}},"13":{"start":{"line":32,"column":12},"end":{"line":45,"column":null}},"14":{"start":{"line":34,"column":56},"end":{"line":37,"column":null}},"15":{"start":{"line":35,"column":52},"end":{"line":35,"column":54}},"16":{"start":{"line":36,"column":50},"end":{"line":36,"column":52}},"17":{"start":{"line":39,"column":16},"end":{"line":39,"column":null}},"18":{"start":{"line":40,"column":16},"end":{"line":40,"column":null}},"19":{"start":{"line":42,"column":16},"end":{"line":42,"column":null}},"20":{"start":{"line":44,"column":16},"end":{"line":44,"column":null}},"21":{"start":{"line":50,"column":4},"end":{"line":75,"column":null}},"22":{"start":{"line":51,"column":8},"end":{"line":55,"column":null}},"23":{"start":{"line":52,"column":12},"end":{"line":52,"column":null}},"24":{"start":{"line":53,"column":12},"end":{"line":53,"column":null}},"25":{"start":{"line":54,"column":12},"end":{"line":54,"column":null}},"26":{"start":{"line":57,"column":27},"end":{"line":57,"column":null}},"27":{"start":{"line":60,"column":30},"end":{"line":64,"column":null}},"28":{"start":{"line":61,"column":12},"end":{"line":63,"column":null}},"29":{"start":{"line":63,"column":44},"end":{"line":63,"column":83}},"30":{"start":{"line":67,"column":30},"end":{"line":70,"column":null}},"31":{"start":{"line":68,"column":12},"end":{"line":69,"column":null}},"32":{"start":{"line":69,"column":44},"end":{"line":69,"column":83}},"33":{"start":{"line":72,"column":8},"end":{"line":72,"column":null}},"34":{"start":{"line":73,"column":8},"end":{"line":73,"column":null}},"35":{"start":{"line":78,"column":4},"end":{"line":86,"column":null}},"36":{"start":{"line":80,"column":12},"end":{"line":82,"column":null}},"37":{"start":{"line":81,"column":16},"end":{"line":81,"column":null}},"38":{"start":{"line":84,"column":8},"end":{"line":84,"column":null}},"39":{"start":{"line":85,"column":8},"end":{"line":85,"column":null}},"40":{"start":{"line":85,"column":21},"end":{"line":85,"column":null}},"41":{"start":{"line":89,"column":38},"end":{"line":93,"column":null}},"42":{"start":{"line":90,"column":8},"end":{"line":90,"column":null}},"43":{"start":{"line":91,"column":8},"end":{"line":91,"column":null}},"44":{"start":{"line":92,"column":8},"end":{"line":92,"column":null}},"45":{"start":{"line":95,"column":36},"end":{"line":99,"column":null}},"46":{"start":{"line":96,"column":8},"end":{"line":96,"column":null}},"47":{"start":{"line":97,"column":8},"end":{"line":97,"column":null}},"48":{"start":{"line":98,"column":8},"end":{"line":98,"column":null}},"49":{"start":{"line":101,"column":23},"end":{"line":101,"column":null}},"50":{"start":{"line":103,"column":4},"end":{"line":159,"column":null}},"51":{"start":{"line":110,"column":33},"end":{"line":110,"column":null}},"52":{"start":{"line":128,"column":40},"end":{"line":135,"column":null}},"53":{"start":{"line":130,"column":59},"end":{"line":130,"column":null}},"54":{"start":{"line":145,"column":40},"end":{"line":151,"column":null}},"55":{"start":{"line":147,"column":59},"end":{"line":147,"column":null}}},"fnMap":{"0":{"name":"Searchbar","decl":{"start":{"line":11,"column":24},"end":{"line":11,"column":36}},"loc":{"start":{"line":11,"column":36},"end":{"line":161,"column":null}},"line":11},"1":{"name":"(anonymous_1)","decl":{"start":{"line":28,"column":24},"end":{"line":28,"column":36}},"loc":{"start":{"line":28,"column":36},"end":{"line":47,"column":null}},"line":28},"2":{"name":"(anonymous_2)","decl":{"start":{"line":35,"column":46},"end":{"line":35,"column":52}},"loc":{"start":{"line":35,"column":52},"end":{"line":35,"column":54}},"line":35},"3":{"name":"(anonymous_3)","decl":{"start":{"line":36,"column":44},"end":{"line":36,"column":50}},"loc":{"start":{"line":36,"column":50},"end":{"line":36,"column":52}},"line":36},"4":{"name":"(anonymous_4)","decl":{"start":{"line":50,"column":14},"end":{"line":50,"column":20}},"loc":{"start":{"line":50,"column":20},"end":{"line":75,"column":7}},"line":50},"5":{"name":"(anonymous_5)","decl":{"start":{"line":60,"column":52},"end":{"line":60,"column":null}},"loc":{"start":{"line":61,"column":12},"end":{"line":63,"column":null}},"line":61},"6":{"name":"(anonymous_6)","decl":{"start":{"line":63,"column":36},"end":{"line":63,"column":44}},"loc":{"start":{"line":63,"column":44},"end":{"line":63,"column":83}},"line":63},"7":{"name":"(anonymous_7)","decl":{"start":{"line":67,"column":49},"end":{"line":67,"column":null}},"loc":{"start":{"line":68,"column":12},"end":{"line":69,"column":null}},"line":68},"8":{"name":"(anonymous_8)","decl":{"start":{"line":69,"column":36},"end":{"line":69,"column":44}},"loc":{"start":{"line":69,"column":44},"end":{"line":69,"column":83}},"line":69},"9":{"name":"(anonymous_9)","decl":{"start":{"line":78,"column":14},"end":{"line":78,"column":20}},"loc":{"start":{"line":78,"column":20},"end":{"line":86,"column":7}},"line":78},"10":{"name":"handleClickOutside","decl":{"start":{"line":79,"column":17},"end":{"line":79,"column":36}},"loc":{"start":{"line":79,"column":55},"end":{"line":83,"column":null}},"line":79},"11":{"name":"(anonymous_11)","decl":{"start":{"line":85,"column":15},"end":{"line":85,"column":21}},"loc":{"start":{"line":85,"column":21},"end":{"line":85,"column":null}},"line":85},"12":{"name":"(anonymous_12)","decl":{"start":{"line":89,"column":38},"end":{"line":89,"column":39}},"loc":{"start":{"line":89,"column":63},"end":{"line":93,"column":null}},"line":89},"13":{"name":"(anonymous_13)","decl":{"start":{"line":95,"column":36},"end":{"line":95,"column":37}},"loc":{"start":{"line":95,"column":59},"end":{"line":99,"column":null}},"line":95},"14":{"name":"(anonymous_14)","decl":{"start":{"line":110,"column":26},"end":{"line":110,"column":27}},"loc":{"start":{"line":110,"column":33},"end":{"line":110,"column":null}},"line":110},"15":{"name":"(anonymous_15)","decl":{"start":{"line":127,"column":61},"end":{"line":127,"column":null}},"loc":{"start":{"line":128,"column":40},"end":{"line":135,"column":null}},"line":128},"16":{"name":"(anonymous_16)","decl":{"start":{"line":130,"column":53},"end":{"line":130,"column":59}},"loc":{"start":{"line":130,"column":59},"end":{"line":130,"column":null}},"line":130},"17":{"name":"(anonymous_17)","decl":{"start":{"line":144,"column":58},"end":{"line":144,"column":59}},"loc":{"start":{"line":145,"column":40},"end":{"line":151,"column":null}},"line":145},"18":{"name":"(anonymous_18)","decl":{"start":{"line":147,"column":53},"end":{"line":147,"column":59}},"loc":{"start":{"line":147,"column":59},"end":{"line":147,"column":null}},"line":147}},"branchMap":{"0":{"loc":{"start":{"line":30,"column":8},"end":{"line":46,"column":null}},"type":"if","locations":[{"start":{"line":30,"column":8},"end":{"line":46,"column":null}},{"start":{},"end":{}}],"line":30},"1":{"loc":{"start":{"line":30,"column":12},"end":{"line":30,"column":69}},"type":"binary-expr","locations":[{"start":{"line":30,"column":12},"end":{"line":30,"column":43}},{"start":{"line":30,"column":43},"end":{"line":30,"column":69}}],"line":30},"2":{"loc":{"start":{"line":51,"column":8},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":51,"column":8},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":51},"3":{"loc":{"start":{"line":61,"column":12},"end":{"line":63,"column":null}},"type":"binary-expr","locations":[{"start":{"line":61,"column":12},"end":{"line":61,"column":null}},{"start":{"line":62,"column":12},"end":{"line":62,"column":null}},{"start":{"line":63,"column":12},"end":{"line":63,"column":null}}],"line":61},"4":{"loc":{"start":{"line":68,"column":12},"end":{"line":69,"column":null}},"type":"binary-expr","locations":[{"start":{"line":68,"column":12},"end":{"line":68,"column":null}},{"start":{"line":69,"column":12},"end":{"line":69,"column":null}}],"line":68},"5":{"loc":{"start":{"line":80,"column":12},"end":{"line":82,"column":null}},"type":"if","locations":[{"start":{"line":80,"column":12},"end":{"line":82,"column":null}},{"start":{},"end":{}}],"line":80},"6":{"loc":{"start":{"line":80,"column":16},"end":{"line":80,"column":90}},"type":"binary-expr","locations":[{"start":{"line":80,"column":16},"end":{"line":80,"column":38}},{"start":{"line":80,"column":38},"end":{"line":80,"column":90}}],"line":80},"7":{"loc":{"start":{"line":101,"column":23},"end":{"line":101,"column":null}},"type":"binary-expr","locations":[{"start":{"line":101,"column":23},"end":{"line":101,"column":57}},{"start":{"line":101,"column":57},"end":{"line":101,"column":null}}],"line":101},"8":{"loc":{"start":{"line":115,"column":13},"end":{"line":157,"column":null}},"type":"binary-expr","locations":[{"start":{"line":115,"column":13},"end":{"line":115,"column":26}},{"start":{"line":115,"column":26},"end":{"line":115,"column":null}},{"start":{"line":116,"column":16},"end":{"line":157,"column":null}}],"line":115},"9":{"loc":{"start":{"line":117,"column":21},"end":{"line":155,"column":null}},"type":"cond-expr","locations":[{"start":{"line":118,"column":24},"end":{"line":118,"column":null}},{"start":{"line":119,"column":24},"end":{"line":155,"column":null}}],"line":117},"10":{"loc":{"start":{"line":119,"column":24},"end":{"line":155,"column":null}},"type":"cond-expr","locations":[{"start":{"line":120,"column":24},"end":{"line":120,"column":null}},{"start":{"line":122,"column":24},"end":{"line":155,"column":null}}],"line":119},"11":{"loc":{"start":{"line":124,"column":29},"end":{"line":137,"column":null}},"type":"binary-expr","locations":[{"start":{"line":124,"column":29},"end":{"line":124,"column":null}},{"start":{"line":125,"column":32},"end":{"line":137,"column":null}}],"line":124},"12":{"loc":{"start":{"line":134,"column":45},"end":{"line":134,"column":null}},"type":"binary-expr","locations":[{"start":{"line":134,"column":45},"end":{"line":134,"column":71}},{"start":{"line":134,"column":71},"end":{"line":134,"column":null}}],"line":134},"13":{"loc":{"start":{"line":141,"column":29},"end":{"line":153,"column":null}},"type":"binary-expr","locations":[{"start":{"line":141,"column":29},"end":{"line":141,"column":null}},{"start":{"line":142,"column":32},"end":{"line":153,"column":null}}],"line":141},"14":{"loc":{"start":{"line":147,"column":83},"end":{"line":147,"column":108}},"type":"binary-expr","locations":[{"start":{"line":147,"column":83},"end":{"line":147,"column":94}},{"start":{"line":147,"column":94},"end":{"line":147,"column":108}}],"line":147},"15":{"loc":{"start":{"line":150,"column":56},"end":{"line":150,"column":89}},"type":"binary-expr","locations":[{"start":{"line":150,"column":56},"end":{"line":150,"column":79}},{"start":{"line":150,"column":79},"end":{"line":150,"column":89}}],"line":150},"16":{"loc":{"start":{"line":146,"column":49},"end":{"line":146,"column":null}},"type":"binary-expr","locations":[{"start":{"line":146,"column":49},"end":{"line":146,"column":60}},{"start":{"line":146,"column":60},"end":{"line":146,"column":null}}],"line":146}},"s":{"0":47,"1":47,"2":47,"3":47,"4":47,"5":47,"6":47,"7":47,"8":47,"9":47,"10":6,"11":6,"12":6,"13":6,"14":6,"15":0,"16":0,"17":6,"18":6,"19":0,"20":6,"21":47,"22":20,"23":8,"24":8,"25":8,"26":12,"27":12,"28":3,"29":0,"30":12,"31":3,"32":0,"33":12,"34":12,"35":47,"36":1,"37":1,"38":6,"39":6,"40":6,"41":47,"42":1,"43":1,"44":1,"45":47,"46":1,"47":1,"48":1,"49":47,"50":47,"51":7,"52":1,"53":1,"54":3,"55":1},"f":{"0":47,"1":6,"2":0,"3":0,"4":20,"5":3,"6":0,"7":3,"8":0,"9":6,"10":1,"11":6,"12":1,"13":1,"14":7,"15":1,"16":1,"17":3,"18":1},"b":{"0":[6,0],"1":[6,6],"2":[8,12],"3":[3,2,2],"4":[3,0],"5":[1,0],"6":[1,1],"7":[47,45],"8":[47,31,23],"9":[12,11],"10":[7,4],"11":[4,1],"12":[1,0],"13":[4,3],"14":[1,0],"15":[3,2],"16":[3,0]},"meta":{"lastBranch":17,"lastFunction":19,"lastStatement":56,"seen":{"f:11:24:11:36":0,"s:12:26:12:Infinity":0,"s:13:10:13:Infinity":1,"s:15:10:15:Infinity":2,"s:17:34:17:Infinity":3,"s:18:34:18:Infinity":4,"s:21:44:21:Infinity":5,"s:22:38:22:Infinity":6,"s:25:54:25:Infinity":7,"s:26:48:26:Infinity":8,"s:28:24:47:Infinity":9,"f:28:24:28:36":1,"s:29:8:29:Infinity":10,"b:30:8:46:Infinity:undefined:undefined:undefined:undefined":0,"s:30:8:46:Infinity":11,"b:30:12:30:43:30:43:30:69":1,"s:31:12:31:Infinity":12,"s:32:12:45:Infinity":13,"s:34:56:37:Infinity":14,"f:35:46:35:52":2,"s:35:52:35:54":15,"f:36:44:36:50":3,"s:36:50:36:52":16,"s:39:16:39:Infinity":17,"s:40:16:40:Infinity":18,"s:42:16:42:Infinity":19,"s:44:16:44:Infinity":20,"s:50:4:75:Infinity":21,"f:50:14:50:20":4,"b:51:8:55:Infinity:undefined:undefined:undefined:undefined":2,"s:51:8:55:Infinity":22,"s:52:12:52:Infinity":23,"s:53:12:53:Infinity":24,"s:54:12:54:Infinity":25,"s:57:27:57:Infinity":26,"s:60:30:64:Infinity":27,"f:60:52:60:Infinity":5,"s:61:12:63:Infinity":28,"b:61:12:61:Infinity:62:12:62:Infinity:63:12:63:Infinity":3,"f:63:36:63:44":6,"s:63:44:63:83":29,"s:67:30:70:Infinity":30,"f:67:49:67:Infinity":7,"s:68:12:69:Infinity":31,"b:68:12:68:Infinity:69:12:69:Infinity":4,"f:69:36:69:44":8,"s:69:44:69:83":32,"s:72:8:72:Infinity":33,"s:73:8:73:Infinity":34,"s:78:4:86:Infinity":35,"f:78:14:78:20":9,"f:79:17:79:36":10,"b:80:12:82:Infinity:undefined:undefined:undefined:undefined":5,"s:80:12:82:Infinity":36,"b:80:16:80:38:80:38:80:90":6,"s:81:16:81:Infinity":37,"s:84:8:84:Infinity":38,"s:85:8:85:Infinity":39,"f:85:15:85:21":11,"s:85:21:85:Infinity":40,"s:89:38:93:Infinity":41,"f:89:38:89:39":12,"s:90:8:90:Infinity":42,"s:91:8:91:Infinity":43,"s:92:8:92:Infinity":44,"s:95:36:99:Infinity":45,"f:95:36:95:37":13,"s:96:8:96:Infinity":46,"s:97:8:97:Infinity":47,"s:98:8:98:Infinity":48,"s:101:23:101:Infinity":49,"b:101:23:101:57:101:57:101:Infinity":7,"s:103:4:159:Infinity":50,"f:110:26:110:27":14,"s:110:33:110:Infinity":51,"b:115:13:115:26:115:26:115:Infinity:116:16:157:Infinity":8,"b:118:24:118:Infinity:119:24:155:Infinity":9,"b:120:24:120:Infinity:122:24:155:Infinity":10,"b:124:29:124:Infinity:125:32:137:Infinity":11,"f:127:61:127:Infinity":15,"s:128:40:135:Infinity":52,"f:130:53:130:59":16,"s:130:59:130:Infinity":53,"b:134:45:134:71:134:71:134:Infinity":12,"b:141:29:141:Infinity:142:32:153:Infinity":13,"f:144:58:144:59":17,"s:145:40:151:Infinity":54,"f:147:53:147:59":18,"s:147:59:147:Infinity":55,"b:147:83:147:94:147:94:147:108":14,"b:150:56:150:79:150:79:150:89":15,"b:146:49:146:60:146:60:146:Infinity":16}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/domain/TagInput/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/domain/TagInput/index.tsx","statementMap":{"0":{"start":{"line":23,"column":36},"end":{"line":23,"column":null}},"1":{"start":{"line":24,"column":40},"end":{"line":24,"column":null}},"2":{"start":{"line":25,"column":24},"end":{"line":25,"column":null}},"3":{"start":{"line":26,"column":8},"end":{"line":26,"column":null}},"4":{"start":{"line":28,"column":2},"end":{"line":38,"column":null}},"5":{"start":{"line":29,"column":4},"end":{"line":37,"column":null}},"6":{"start":{"line":30,"column":23},"end":{"line":33,"column":null}},"7":{"start":{"line":31,"column":8},"end":{"line":32,"column":null}},"8":{"start":{"line":34,"column":6},"end":{"line":34,"column":null}},"9":{"start":{"line":36,"column":6},"end":{"line":36,"column":null}},"10":{"start":{"line":41,"column":2},"end":{"line":51,"column":null}},"11":{"start":{"line":43,"column":6},"end":{"line":45,"column":null}},"12":{"start":{"line":44,"column":8},"end":{"line":44,"column":null}},"13":{"start":{"line":47,"column":4},"end":{"line":47,"column":null}},"14":{"start":{"line":48,"column":4},"end":{"line":50,"column":null}},"15":{"start":{"line":49,"column":6},"end":{"line":49,"column":null}},"16":{"start":{"line":54,"column":23},"end":{"line":66,"column":null}},"17":{"start":{"line":56,"column":4},"end":{"line":59,"column":null}},"18":{"start":{"line":57,"column":6},"end":{"line":57,"column":null}},"19":{"start":{"line":58,"column":6},"end":{"line":58,"column":null}},"20":{"start":{"line":60,"column":4},"end":{"line":65,"column":null}},"21":{"start":{"line":61,"column":6},"end":{"line":61,"column":null}},"22":{"start":{"line":62,"column":6},"end":{"line":62,"column":null}},"23":{"start":{"line":63,"column":6},"end":{"line":63,"column":null}},"24":{"start":{"line":64,"column":6},"end":{"line":64,"column":null}},"25":{"start":{"line":69,"column":26},"end":{"line":72,"column":null}},"26":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"27":{"start":{"line":70,"column":40},"end":{"line":70,"column":59}},"28":{"start":{"line":71,"column":4},"end":{"line":71,"column":null}},"29":{"start":{"line":74,"column":2},"end":{"line":110,"column":null}},"30":{"start":{"line":79,"column":12},"end":{"line":84,"column":null}},"31":{"start":{"line":81,"column":30},"end":{"line":81,"column":null}},"32":{"start":{"line":95,"column":25},"end":{"line":95,"column":null}},"33":{"start":{"line":102,"column":12},"end":{"line":104,"column":null}},"34":{"start":{"line":102,"column":57},"end":{"line":102,"column":null}}},"fnMap":{"0":{"name":"TagInput","decl":{"start":{"line":15,"column":24},"end":{"line":15,"column":33}},"loc":{"start":{"line":21,"column":18},"end":{"line":112,"column":null}},"line":21},"1":{"name":"(anonymous_1)","decl":{"start":{"line":28,"column":12},"end":{"line":28,"column":18}},"loc":{"start":{"line":28,"column":18},"end":{"line":38,"column":5}},"line":28},"2":{"name":"(anonymous_2)","decl":{"start":{"line":30,"column":41},"end":{"line":30,"column":null}},"loc":{"start":{"line":31,"column":8},"end":{"line":32,"column":null}},"line":31},"3":{"name":"(anonymous_3)","decl":{"start":{"line":41,"column":12},"end":{"line":41,"column":18}},"loc":{"start":{"line":41,"column":18},"end":{"line":51,"column":5}},"line":41},"4":{"name":"handleClickOutside","decl":{"start":{"line":42,"column":13},"end":{"line":42,"column":32}},"loc":{"start":{"line":42,"column":51},"end":{"line":46,"column":null}},"line":42},"5":{"name":"(anonymous_5)","decl":{"start":{"line":48,"column":11},"end":{"line":48,"column":17}},"loc":{"start":{"line":48,"column":17},"end":{"line":50,"column":null}},"line":48},"6":{"name":"(anonymous_6)","decl":{"start":{"line":54,"column":23},"end":{"line":54,"column":24}},"loc":{"start":{"line":54,"column":40},"end":{"line":66,"column":null}},"line":54},"7":{"name":"(anonymous_7)","decl":{"start":{"line":69,"column":26},"end":{"line":69,"column":27}},"loc":{"start":{"line":69,"column":51},"end":{"line":72,"column":null}},"line":69},"8":{"name":"(anonymous_8)","decl":{"start":{"line":70,"column":33},"end":{"line":70,"column":40}},"loc":{"start":{"line":70,"column":40},"end":{"line":70,"column":59}},"line":70},"9":{"name":"(anonymous_9)","decl":{"start":{"line":78,"column":28},"end":{"line":78,"column":null}},"loc":{"start":{"line":79,"column":12},"end":{"line":84,"column":null}},"line":79},"10":{"name":"(anonymous_10)","decl":{"start":{"line":81,"column":24},"end":{"line":81,"column":30}},"loc":{"start":{"line":81,"column":30},"end":{"line":81,"column":null}},"line":81},"11":{"name":"(anonymous_11)","decl":{"start":{"line":95,"column":18},"end":{"line":95,"column":19}},"loc":{"start":{"line":95,"column":25},"end":{"line":95,"column":null}},"line":95},"12":{"name":"(anonymous_12)","decl":{"start":{"line":101,"column":29},"end":{"line":101,"column":null}},"loc":{"start":{"line":102,"column":12},"end":{"line":104,"column":null}},"line":102},"13":{"name":"(anonymous_13)","decl":{"start":{"line":102,"column":51},"end":{"line":102,"column":57}},"loc":{"start":{"line":102,"column":57},"end":{"line":102,"column":null}},"line":102}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":9},"end":{"line":16,"column":null}},"type":"default-arg","locations":[{"start":{"line":16,"column":24},"end":{"line":16,"column":null}}],"line":16},"1":{"loc":{"start":{"line":29,"column":4},"end":{"line":37,"column":null}},"type":"if","locations":[{"start":{"line":29,"column":4},"end":{"line":37,"column":null}},{"start":{"line":35,"column":11},"end":{"line":37,"column":null}}],"line":29},"2":{"loc":{"start":{"line":31,"column":8},"end":{"line":32,"column":null}},"type":"binary-expr","locations":[{"start":{"line":31,"column":8},"end":{"line":31,"column":null}},{"start":{"line":32,"column":8},"end":{"line":32,"column":null}}],"line":31},"3":{"loc":{"start":{"line":43,"column":6},"end":{"line":45,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":6},"end":{"line":45,"column":null}},{"start":{},"end":{}}],"line":43},"4":{"loc":{"start":{"line":43,"column":10},"end":{"line":43,"column":84}},"type":"binary-expr","locations":[{"start":{"line":43,"column":10},"end":{"line":43,"column":32}},{"start":{"line":43,"column":32},"end":{"line":43,"column":84}}],"line":43},"5":{"loc":{"start":{"line":56,"column":4},"end":{"line":59,"column":null}},"type":"if","locations":[{"start":{"line":56,"column":4},"end":{"line":59,"column":null}},{"start":{},"end":{}}],"line":56},"6":{"loc":{"start":{"line":60,"column":4},"end":{"line":65,"column":null}},"type":"if","locations":[{"start":{"line":60,"column":4},"end":{"line":65,"column":null}},{"start":{},"end":{}}],"line":60},"7":{"loc":{"start":{"line":76,"column":7},"end":{"line":86,"column":null}},"type":"binary-expr","locations":[{"start":{"line":76,"column":7},"end":{"line":76,"column":null}},{"start":{"line":77,"column":8},"end":{"line":86,"column":null}}],"line":76},"8":{"loc":{"start":{"line":89,"column":28},"end":{"line":89,"column":67}},"type":"cond-expr","locations":[{"start":{"line":89,"column":54},"end":{"line":89,"column":63}},{"start":{"line":89,"column":63},"end":{"line":89,"column":67}}],"line":89},"9":{"loc":{"start":{"line":99,"column":7},"end":{"line":106,"column":null}},"type":"binary-expr","locations":[{"start":{"line":99,"column":7},"end":{"line":99,"column":null}},{"start":{"line":100,"column":8},"end":{"line":106,"column":null}}],"line":99},"10":{"loc":{"start":{"line":109,"column":7},"end":{"line":109,"column":null}},"type":"binary-expr","locations":[{"start":{"line":109,"column":7},"end":{"line":109,"column":16}},{"start":{"line":109,"column":16},"end":{"line":109,"column":null}}],"line":109}},"s":{"0":20,"1":20,"2":20,"3":20,"4":20,"5":9,"6":3,"7":11,"8":3,"9":6,"10":20,"11":0,"12":0,"13":5,"14":5,"15":5,"16":20,"17":2,"18":1,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":20,"26":1,"27":2,"28":1,"29":20,"30":18,"31":1,"32":3,"33":4,"34":2},"f":{"0":20,"1":9,"2":11,"3":5,"4":0,"5":5,"6":2,"7":1,"8":2,"9":18,"10":1,"11":3,"12":4,"13":2},"b":{"0":[20],"1":[3,6],"2":[11,3],"3":[0,0],"4":[0,0],"5":[1,1],"6":[1,0],"7":[20,10],"8":[10,10],"9":[20,4],"10":[20,1]},"meta":{"lastBranch":11,"lastFunction":14,"lastStatement":35,"seen":{"f:15:24:15:33":0,"b:16:24:16:Infinity":0,"s:23:36:23:Infinity":0,"s:24:40:24:Infinity":1,"s:25:24:25:Infinity":2,"s:26:8:26:Infinity":3,"s:28:2:38:Infinity":4,"f:28:12:28:18":1,"b:29:4:37:Infinity:35:11:37:Infinity":1,"s:29:4:37:Infinity":5,"s:30:23:33:Infinity":6,"f:30:41:30:Infinity":2,"s:31:8:32:Infinity":7,"b:31:8:31:Infinity:32:8:32:Infinity":2,"s:34:6:34:Infinity":8,"s:36:6:36:Infinity":9,"s:41:2:51:Infinity":10,"f:41:12:41:18":3,"f:42:13:42:32":4,"b:43:6:45:Infinity:undefined:undefined:undefined:undefined":3,"s:43:6:45:Infinity":11,"b:43:10:43:32:43:32:43:84":4,"s:44:8:44:Infinity":12,"s:47:4:47:Infinity":13,"s:48:4:50:Infinity":14,"f:48:11:48:17":5,"s:49:6:49:Infinity":15,"s:54:23:66:Infinity":16,"f:54:23:54:24":6,"b:56:4:59:Infinity:undefined:undefined:undefined:undefined":5,"s:56:4:59:Infinity":17,"s:57:6:57:Infinity":18,"s:58:6:58:Infinity":19,"b:60:4:65:Infinity:undefined:undefined:undefined:undefined":6,"s:60:4:65:Infinity":20,"s:61:6:61:Infinity":21,"s:62:6:62:Infinity":22,"s:63:6:63:Infinity":23,"s:64:6:64:Infinity":24,"s:69:26:72:Infinity":25,"f:69:26:69:27":7,"s:70:4:70:Infinity":26,"f:70:33:70:40":8,"s:70:40:70:59":27,"s:71:4:71:Infinity":28,"s:74:2:110:Infinity":29,"b:76:7:76:Infinity:77:8:86:Infinity":7,"f:78:28:78:Infinity":9,"s:79:12:84:Infinity":30,"f:81:24:81:30":10,"s:81:30:81:Infinity":31,"b:89:54:89:63:89:63:89:67":8,"f:95:18:95:19":11,"s:95:25:95:Infinity":32,"b:99:7:99:Infinity:100:8:106:Infinity":9,"f:101:29:101:Infinity":12,"s:102:12:104:Infinity":33,"f:102:51:102:57":13,"s:102:57:102:Infinity":34,"b:109:7:109:16:109:16:109:Infinity":10}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/layout/Header/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/layout/Header/index.tsx","statementMap":{"0":{"start":{"line":11,"column":4},"end":{"line":26,"column":null}}},"fnMap":{"0":{"name":"Header","decl":{"start":{"line":10,"column":24},"end":{"line":10,"column":31}},"loc":{"start":{"line":10,"column":63},"end":{"line":28,"column":null}},"line":10}},"branchMap":{},"s":{"0":2},"f":{"0":2},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:10:24:10:31":0,"s:11:4:26:Infinity":0}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/layout/HeaderHome/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/layout/HeaderHome/index.tsx","statementMap":{"0":{"start":{"line":4,"column":4},"end":{"line":16,"column":null}}},"fnMap":{"0":{"name":"HeaderHome","decl":{"start":{"line":3,"column":24},"end":{"line":3,"column":37}},"loc":{"start":{"line":3,"column":37},"end":{"line":18,"column":null}},"line":3}},"branchMap":{},"s":{"0":1},"f":{"0":1},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:3:24:3:37":0,"s:4:4:16:Infinity":0}}} +,"/home/cecilia/Documents/CTable/frontend/src/components/layout/Sidebar/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/components/layout/Sidebar/index.tsx","statementMap":{"0":{"start":{"line":11,"column":50},"end":{"line":11,"column":null}},"1":{"start":{"line":12,"column":24},"end":{"line":12,"column":null}},"2":{"start":{"line":13,"column":46},"end":{"line":13,"column":null}},"3":{"start":{"line":15,"column":30},"end":{"line":17,"column":null}},"4":{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},"5":{"start":{"line":19,"column":6},"end":{"line":35,"column":null}},"6":{"start":{"line":21,"column":33},"end":{"line":32,"column":null}},"7":{"start":{"line":22,"column":10},"end":{"line":30,"column":null}},"8":{"start":{"line":24,"column":39},"end":{"line":24,"column":null}},"9":{"start":{"line":25,"column":12},"end":{"line":25,"column":null}},"10":{"start":{"line":26,"column":12},"end":{"line":26,"column":null}},"11":{"start":{"line":29,"column":12},"end":{"line":29,"column":null}},"12":{"start":{"line":33,"column":8},"end":{"line":34,"column":null}},"13":{"start":{"line":34,"column":10},"end":{"line":34,"column":null}},"14":{"start":{"line":37,"column":4},"end":{"line":68,"column":null}},"15":{"start":{"line":54,"column":28},"end":{"line":62,"column":null}}},"fnMap":{"0":{"name":"Sidebar","decl":{"start":{"line":9,"column":24},"end":{"line":9,"column":34}},"loc":{"start":{"line":9,"column":34},"end":{"line":70,"column":null}},"line":9},"1":{"name":"(anonymous_1)","decl":{"start":{"line":15,"column":30},"end":{"line":15,"column":36}},"loc":{"start":{"line":15,"column":36},"end":{"line":17,"column":null}},"line":15},"2":{"name":"(anonymous_2)","decl":{"start":{"line":19,"column":16},"end":{"line":19,"column":22}},"loc":{"start":{"line":19,"column":22},"end":{"line":35,"column":9}},"line":19},"3":{"name":"(anonymous_3)","decl":{"start":{"line":21,"column":33},"end":{"line":21,"column":45}},"loc":{"start":{"line":21,"column":45},"end":{"line":32,"column":null}},"line":21},"4":{"name":"(anonymous_4)","decl":{"start":{"line":53,"column":45},"end":{"line":53,"column":46}},"loc":{"start":{"line":54,"column":28},"end":{"line":62,"column":null}},"line":54}},"branchMap":{"0":{"loc":{"start":{"line":33,"column":8},"end":{"line":34,"column":null}},"type":"if","locations":[{"start":{"line":33,"column":8},"end":{"line":34,"column":null}},{"start":{},"end":{}}],"line":33},"1":{"loc":{"start":{"line":51,"column":17},"end":{"line":64,"column":null}},"type":"binary-expr","locations":[{"start":{"line":51,"column":17},"end":{"line":51,"column":null}},{"start":{"line":52,"column":20},"end":{"line":64,"column":null}}],"line":51}},"s":{"0":9,"1":9,"2":9,"3":9,"4":2,"5":9,"6":8,"7":8,"8":8,"9":8,"10":8,"11":0,"12":8,"13":8,"14":9,"15":4},"f":{"0":9,"1":2,"2":8,"3":8,"4":4},"b":{"0":[8,0],"1":[9,8]},"meta":{"lastBranch":2,"lastFunction":5,"lastStatement":16,"seen":{"f:9:24:9:34":0,"s:11:50:11:Infinity":0,"s:12:24:12:Infinity":1,"s:13:46:13:Infinity":2,"s:15:30:17:Infinity":3,"f:15:30:15:36":1,"s:16:8:16:Infinity":4,"s:19:6:35:Infinity":5,"f:19:16:19:22":2,"s:21:33:32:Infinity":6,"f:21:33:21:45":3,"s:22:10:30:Infinity":7,"s:24:39:24:Infinity":8,"s:25:12:25:Infinity":9,"s:26:12:26:Infinity":10,"s:29:12:29:Infinity":11,"b:33:8:34:Infinity:undefined:undefined:undefined:undefined":0,"s:33:8:34:Infinity":12,"s:34:10:34:Infinity":13,"s:37:4:68:Infinity":14,"b:51:17:51:Infinity:52:20:64:Infinity":1,"f:53:45:53:46":4,"s:54:28:62:Infinity":15}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/CommunityPage/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/CommunityPage/index.tsx","statementMap":{"0":{"start":{"line":16,"column":22},"end":{"line":16,"column":null}},"1":{"start":{"line":17,"column":8},"end":{"line":17,"column":null}},"2":{"start":{"line":19,"column":38},"end":{"line":19,"column":null}},"3":{"start":{"line":20,"column":32},"end":{"line":20,"column":null}},"4":{"start":{"line":21,"column":24},"end":{"line":21,"column":null}},"5":{"start":{"line":23,"column":34},"end":{"line":23,"column":null}},"6":{"start":{"line":24,"column":48},"end":{"line":24,"column":null}},"7":{"start":{"line":25,"column":8},"end":{"line":25,"column":null}},"8":{"start":{"line":27,"column":46},"end":{"line":27,"column":null}},"9":{"start":{"line":29,"column":2},"end":{"line":42,"column":null}},"10":{"start":{"line":31,"column":8},"end":{"line":31,"column":null}},"11":{"start":{"line":32,"column":8},"end":{"line":32,"column":null}},"12":{"start":{"line":32,"column":26},"end":{"line":32,"column":null}},"13":{"start":{"line":33,"column":8},"end":{"line":39,"column":null}},"14":{"start":{"line":34,"column":25},"end":{"line":34,"column":null}},"15":{"start":{"line":35,"column":12},"end":{"line":35,"column":null}},"16":{"start":{"line":36,"column":12},"end":{"line":36,"column":null}},"17":{"start":{"line":38,"column":12},"end":{"line":38,"column":null}},"18":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"19":{"start":{"line":44,"column":2},"end":{"line":52,"column":null}},"20":{"start":{"line":46,"column":6},"end":{"line":48,"column":null}},"21":{"start":{"line":47,"column":8},"end":{"line":47,"column":null}},"22":{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},"23":{"start":{"line":50,"column":20},"end":{"line":50,"column":null}},"24":{"start":{"line":51,"column":4},"end":{"line":51,"column":null}},"25":{"start":{"line":51,"column":17},"end":{"line":51,"column":null}},"26":{"start":{"line":54,"column":21},"end":{"line":74,"column":null}},"27":{"start":{"line":55,"column":4},"end":{"line":55,"column":null}},"28":{"start":{"line":55,"column":20},"end":{"line":55,"column":null}},"29":{"start":{"line":57,"column":4},"end":{"line":73,"column":null}},"30":{"start":{"line":58,"column":8},"end":{"line":58,"column":null}},"31":{"start":{"line":61,"column":8},"end":{"line":65,"column":null}},"32":{"start":{"line":61,"column":54},"end":{"line":65,"column":17}},"33":{"start":{"line":67,"column":8},"end":{"line":67,"column":null}},"34":{"start":{"line":70,"column":8},"end":{"line":72,"column":null}},"35":{"start":{"line":71,"column":12},"end":{"line":71,"column":null}},"36":{"start":{"line":76,"column":21},"end":{"line":78,"column":null}},"37":{"start":{"line":77,"column":4},"end":{"line":77,"column":null}},"38":{"start":{"line":80,"column":23},"end":{"line":98,"column":null}},"39":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"40":{"start":{"line":81,"column":20},"end":{"line":81,"column":null}},"41":{"start":{"line":82,"column":4},"end":{"line":97,"column":null}},"42":{"start":{"line":83,"column":8},"end":{"line":83,"column":null}},"43":{"start":{"line":84,"column":8},"end":{"line":84,"column":null}},"44":{"start":{"line":85,"column":8},"end":{"line":85,"column":null}},"45":{"start":{"line":88,"column":8},"end":{"line":90,"column":null}},"46":{"start":{"line":89,"column":12},"end":{"line":89,"column":null}},"47":{"start":{"line":93,"column":8},"end":{"line":95,"column":null}},"48":{"start":{"line":94,"column":12},"end":{"line":94,"column":null}},"49":{"start":{"line":96,"column":8},"end":{"line":96,"column":null}},"50":{"start":{"line":100,"column":22},"end":{"line":122,"column":null}},"51":{"start":{"line":101,"column":4},"end":{"line":101,"column":null}},"52":{"start":{"line":101,"column":20},"end":{"line":101,"column":null}},"53":{"start":{"line":103,"column":4},"end":{"line":121,"column":null}},"54":{"start":{"line":104,"column":8},"end":{"line":104,"column":null}},"55":{"start":{"line":107,"column":8},"end":{"line":111,"column":null}},"56":{"start":{"line":107,"column":54},"end":{"line":111,"column":17}},"57":{"start":{"line":113,"column":8},"end":{"line":113,"column":null}},"58":{"start":{"line":114,"column":8},"end":{"line":114,"column":null}},"59":{"start":{"line":117,"column":8},"end":{"line":119,"column":null}},"60":{"start":{"line":118,"column":12},"end":{"line":118,"column":null}},"61":{"start":{"line":120,"column":8},"end":{"line":120,"column":null}},"62":{"start":{"line":124,"column":2},"end":{"line":124,"column":null}},"63":{"start":{"line":124,"column":18},"end":{"line":124,"column":null}},"64":{"start":{"line":126,"column":2},"end":{"line":250,"column":null}},"65":{"start":{"line":134,"column":25},"end":{"line":134,"column":null}},"66":{"start":{"line":155,"column":46},"end":{"line":155,"column":73}},"67":{"start":{"line":161,"column":52},"end":{"line":161,"column":null}},"68":{"start":{"line":172,"column":32},"end":{"line":172,"column":null}},"69":{"start":{"line":173,"column":32},"end":{"line":173,"column":null}},"70":{"start":{"line":187,"column":14},"end":{"line":189,"column":null}},"71":{"start":{"line":200,"column":16},"end":{"line":200,"column":null}},"72":{"start":{"line":209,"column":23},"end":{"line":209,"column":null}},"73":{"start":{"line":218,"column":52},"end":{"line":218,"column":81}},"74":{"start":{"line":230,"column":23},"end":{"line":230,"column":null}},"75":{"start":{"line":238,"column":52},"end":{"line":238,"column":80}}},"fnMap":{"0":{"name":"CommunityPage","decl":{"start":{"line":15,"column":24},"end":{"line":15,"column":40}},"loc":{"start":{"line":15,"column":40},"end":{"line":252,"column":null}},"line":15},"1":{"name":"(anonymous_1)","decl":{"start":{"line":29,"column":12},"end":{"line":29,"column":18}},"loc":{"start":{"line":29,"column":18},"end":{"line":42,"column":5}},"line":29},"2":{"name":"loadData","decl":{"start":{"line":30,"column":19},"end":{"line":30,"column":30}},"loc":{"start":{"line":30,"column":30},"end":{"line":40,"column":null}},"line":30},"3":{"name":"(anonymous_3)","decl":{"start":{"line":44,"column":12},"end":{"line":44,"column":18}},"loc":{"start":{"line":44,"column":18},"end":{"line":52,"column":5}},"line":44},"4":{"name":"handleClickOutside","decl":{"start":{"line":45,"column":13},"end":{"line":45,"column":32}},"loc":{"start":{"line":45,"column":51},"end":{"line":49,"column":null}},"line":45},"5":{"name":"(anonymous_5)","decl":{"start":{"line":51,"column":11},"end":{"line":51,"column":17}},"loc":{"start":{"line":51,"column":17},"end":{"line":51,"column":null}},"line":51},"6":{"name":"(anonymous_6)","decl":{"start":{"line":54,"column":21},"end":{"line":54,"column":33}},"loc":{"start":{"line":54,"column":33},"end":{"line":74,"column":null}},"line":54},"7":{"name":"(anonymous_7)","decl":{"start":{"line":61,"column":21},"end":{"line":61,"column":22}},"loc":{"start":{"line":61,"column":54},"end":{"line":65,"column":17}},"line":61},"8":{"name":"(anonymous_8)","decl":{"start":{"line":76,"column":21},"end":{"line":76,"column":27}},"loc":{"start":{"line":76,"column":27},"end":{"line":78,"column":null}},"line":76},"9":{"name":"(anonymous_9)","decl":{"start":{"line":80,"column":23},"end":{"line":80,"column":35}},"loc":{"start":{"line":80,"column":35},"end":{"line":98,"column":null}},"line":80},"10":{"name":"(anonymous_10)","decl":{"start":{"line":88,"column":19},"end":{"line":88,"column":25}},"loc":{"start":{"line":88,"column":25},"end":{"line":90,"column":11}},"line":88},"11":{"name":"(anonymous_11)","decl":{"start":{"line":100,"column":22},"end":{"line":100,"column":34}},"loc":{"start":{"line":100,"column":34},"end":{"line":122,"column":null}},"line":100},"12":{"name":"(anonymous_12)","decl":{"start":{"line":107,"column":21},"end":{"line":107,"column":22}},"loc":{"start":{"line":107,"column":54},"end":{"line":111,"column":17}},"line":107},"13":{"name":"(anonymous_13)","decl":{"start":{"line":134,"column":19},"end":{"line":134,"column":25}},"loc":{"start":{"line":134,"column":25},"end":{"line":134,"column":null}},"line":134},"14":{"name":"(anonymous_14)","decl":{"start":{"line":155,"column":40},"end":{"line":155,"column":46}},"loc":{"start":{"line":155,"column":46},"end":{"line":155,"column":73}},"line":155},"15":{"name":"(anonymous_15)","decl":{"start":{"line":161,"column":46},"end":{"line":161,"column":52}},"loc":{"start":{"line":161,"column":52},"end":{"line":161,"column":null}},"line":161},"16":{"name":"(anonymous_16)","decl":{"start":{"line":171,"column":55},"end":{"line":171,"column":61}},"loc":{"start":{"line":171,"column":61},"end":{"line":174,"column":31}},"line":171},"17":{"name":"(anonymous_17)","decl":{"start":{"line":186,"column":23},"end":{"line":186,"column":null}},"loc":{"start":{"line":187,"column":14},"end":{"line":189,"column":null}},"line":187},"18":{"name":"(anonymous_18)","decl":{"start":{"line":199,"column":43},"end":{"line":199,"column":44}},"loc":{"start":{"line":200,"column":16},"end":{"line":200,"column":null}},"line":200},"19":{"name":"(anonymous_19)","decl":{"start":{"line":209,"column":17},"end":{"line":209,"column":23}},"loc":{"start":{"line":209,"column":23},"end":{"line":209,"column":null}},"line":209},"20":{"name":"(anonymous_20)","decl":{"start":{"line":218,"column":46},"end":{"line":218,"column":52}},"loc":{"start":{"line":218,"column":52},"end":{"line":218,"column":81}},"line":218},"21":{"name":"(anonymous_21)","decl":{"start":{"line":230,"column":17},"end":{"line":230,"column":23}},"loc":{"start":{"line":230,"column":23},"end":{"line":230,"column":null}},"line":230},"22":{"name":"(anonymous_22)","decl":{"start":{"line":238,"column":46},"end":{"line":238,"column":52}},"loc":{"start":{"line":238,"column":52},"end":{"line":238,"column":80}},"line":238}},"branchMap":{"0":{"loc":{"start":{"line":32,"column":8},"end":{"line":32,"column":null}},"type":"if","locations":[{"start":{"line":32,"column":8},"end":{"line":32,"column":null}},{"start":{},"end":{}}],"line":32},"1":{"loc":{"start":{"line":46,"column":6},"end":{"line":48,"column":null}},"type":"if","locations":[{"start":{"line":46,"column":6},"end":{"line":48,"column":null}},{"start":{},"end":{}}],"line":46},"2":{"loc":{"start":{"line":46,"column":10},"end":{"line":46,"column":78}},"type":"binary-expr","locations":[{"start":{"line":46,"column":10},"end":{"line":46,"column":29}},{"start":{"line":46,"column":29},"end":{"line":46,"column":78}}],"line":46},"3":{"loc":{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},"type":"if","locations":[{"start":{"line":50,"column":4},"end":{"line":50,"column":null}},{"start":{},"end":{}}],"line":50},"4":{"loc":{"start":{"line":55,"column":4},"end":{"line":55,"column":null}},"type":"if","locations":[{"start":{"line":55,"column":4},"end":{"line":55,"column":null}},{"start":{},"end":{}}],"line":55},"5":{"loc":{"start":{"line":61,"column":54},"end":{"line":65,"column":17}},"type":"cond-expr","locations":[{"start":{"line":61,"column":62},"end":{"line":65,"column":13}},{"start":{"line":65,"column":13},"end":{"line":65,"column":17}}],"line":61},"6":{"loc":{"start":{"line":64,"column":26},"end":{"line":64,"column":51}},"type":"binary-expr","locations":[{"start":{"line":64,"column":26},"end":{"line":64,"column":46}},{"start":{"line":64,"column":46},"end":{"line":64,"column":51}}],"line":64},"7":{"loc":{"start":{"line":70,"column":8},"end":{"line":72,"column":null}},"type":"if","locations":[{"start":{"line":70,"column":8},"end":{"line":72,"column":null}},{"start":{},"end":{}}],"line":70},"8":{"loc":{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},"type":"if","locations":[{"start":{"line":81,"column":4},"end":{"line":81,"column":null}},{"start":{},"end":{}}],"line":81},"9":{"loc":{"start":{"line":93,"column":8},"end":{"line":95,"column":null}},"type":"if","locations":[{"start":{"line":93,"column":8},"end":{"line":95,"column":null}},{"start":{},"end":{}}],"line":93},"10":{"loc":{"start":{"line":101,"column":4},"end":{"line":101,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":4},"end":{"line":101,"column":null}},{"start":{},"end":{}}],"line":101},"11":{"loc":{"start":{"line":107,"column":54},"end":{"line":111,"column":17}},"type":"cond-expr","locations":[{"start":{"line":107,"column":62},"end":{"line":111,"column":13}},{"start":{"line":111,"column":13},"end":{"line":111,"column":17}}],"line":107},"12":{"loc":{"start":{"line":110,"column":35},"end":{"line":110,"column":60}},"type":"binary-expr","locations":[{"start":{"line":110,"column":35},"end":{"line":110,"column":55}},{"start":{"line":110,"column":55},"end":{"line":110,"column":60}}],"line":110},"13":{"loc":{"start":{"line":117,"column":8},"end":{"line":119,"column":null}},"type":"if","locations":[{"start":{"line":117,"column":8},"end":{"line":119,"column":null}},{"start":{},"end":{}}],"line":117},"14":{"loc":{"start":{"line":124,"column":2},"end":{"line":124,"column":null}},"type":"if","locations":[{"start":{"line":124,"column":2},"end":{"line":124,"column":null}},{"start":{},"end":{}}],"line":124},"15":{"loc":{"start":{"line":130,"column":7},"end":{"line":135,"column":null}},"type":"binary-expr","locations":[{"start":{"line":130,"column":7},"end":{"line":130,"column":null}},{"start":{"line":131,"column":8},"end":{"line":135,"column":null}}],"line":130},"16":{"loc":{"start":{"line":149,"column":13},"end":{"line":152,"column":null}},"type":"binary-expr","locations":[{"start":{"line":149,"column":13},"end":{"line":149,"column":null}},{"start":{"line":150,"column":12},"end":{"line":152,"column":null}}],"line":149},"17":{"loc":{"start":{"line":154,"column":13},"end":{"line":157,"column":null}},"type":"binary-expr","locations":[{"start":{"line":154,"column":13},"end":{"line":154,"column":35}},{"start":{"line":154,"column":35},"end":{"line":154,"column":null}},{"start":{"line":155,"column":16},"end":{"line":157,"column":null}}],"line":154},"18":{"loc":{"start":{"line":159,"column":12},"end":{"line":179,"column":null}},"type":"binary-expr","locations":[{"start":{"line":159,"column":12},"end":{"line":159,"column":null}},{"start":{"line":160,"column":16},"end":{"line":179,"column":null}}],"line":159},"19":{"loc":{"start":{"line":165,"column":21},"end":{"line":177,"column":null}},"type":"binary-expr","locations":[{"start":{"line":165,"column":21},"end":{"line":165,"column":null}},{"start":{"line":166,"column":24},"end":{"line":177,"column":null}}],"line":165},"20":{"loc":{"start":{"line":187,"column":38},"end":{"line":187,"column":null}},"type":"binary-expr","locations":[{"start":{"line":187,"column":38},"end":{"line":187,"column":56}},{"start":{"line":187,"column":56},"end":{"line":187,"column":null}}],"line":187}},"s":{"0":14,"1":14,"2":14,"3":14,"4":14,"5":14,"6":14,"7":14,"8":14,"9":14,"10":4,"11":4,"12":0,"13":4,"14":4,"15":4,"16":4,"17":0,"18":4,"19":14,"20":0,"21":0,"22":6,"23":1,"24":6,"25":6,"26":14,"27":1,"28":0,"29":1,"30":1,"31":1,"32":1,"33":1,"34":0,"35":0,"36":14,"37":0,"38":14,"39":1,"40":0,"41":1,"42":1,"43":1,"44":1,"45":1,"46":0,"47":0,"48":0,"49":0,"50":14,"51":1,"52":0,"53":1,"54":1,"55":1,"56":1,"57":1,"58":1,"59":0,"60":0,"61":0,"62":14,"63":4,"64":10,"65":0,"66":1,"67":1,"68":1,"69":1,"70":10,"71":10,"72":0,"73":0,"74":0,"75":0},"f":{"0":14,"1":4,"2":4,"3":6,"4":0,"5":6,"6":1,"7":1,"8":0,"9":1,"10":0,"11":1,"12":1,"13":0,"14":1,"15":1,"16":1,"17":10,"18":10,"19":0,"20":0,"21":0,"22":0},"b":{"0":[0,4],"1":[0,0],"2":[0,0],"3":[1,5],"4":[0,1],"5":[1,0],"6":[1,0],"7":[0,0],"8":[0,1],"9":[0,0],"10":[0,1],"11":[1,0],"12":[1,0],"13":[0,0],"14":[4,10],"15":[10,3],"16":[14,3],"17":[14,7,3],"18":[14,4],"19":[4,1],"20":[10,10]},"meta":{"lastBranch":21,"lastFunction":23,"lastStatement":76,"seen":{"f:15:24:15:40":0,"s:16:22:16:Infinity":0,"s:17:8:17:Infinity":1,"s:19:38:19:Infinity":2,"s:20:32:20:Infinity":3,"s:21:24:21:Infinity":4,"s:23:34:23:Infinity":5,"s:24:48:24:Infinity":6,"s:25:8:25:Infinity":7,"s:27:46:27:Infinity":8,"s:29:2:42:Infinity":9,"f:29:12:29:18":1,"f:30:19:30:30":2,"s:31:8:31:Infinity":10,"b:32:8:32:Infinity:undefined:undefined:undefined:undefined":0,"s:32:8:32:Infinity":11,"s:32:26:32:Infinity":12,"s:33:8:39:Infinity":13,"s:34:25:34:Infinity":14,"s:35:12:35:Infinity":15,"s:36:12:36:Infinity":16,"s:38:12:38:Infinity":17,"s:41:4:41:Infinity":18,"s:44:2:52:Infinity":19,"f:44:12:44:18":3,"f:45:13:45:32":4,"b:46:6:48:Infinity:undefined:undefined:undefined:undefined":1,"s:46:6:48:Infinity":20,"b:46:10:46:29:46:29:46:78":2,"s:47:8:47:Infinity":21,"b:50:4:50:Infinity:undefined:undefined:undefined:undefined":3,"s:50:4:50:Infinity":22,"s:50:20:50:Infinity":23,"s:51:4:51:Infinity":24,"f:51:11:51:17":5,"s:51:17:51:Infinity":25,"s:54:21:74:Infinity":26,"f:54:21:54:33":6,"b:55:4:55:Infinity:undefined:undefined:undefined:undefined":4,"s:55:4:55:Infinity":27,"s:55:20:55:Infinity":28,"s:57:4:73:Infinity":29,"s:58:8:58:Infinity":30,"s:61:8:65:Infinity":31,"f:61:21:61:22":7,"s:61:54:65:17":32,"b:61:62:65:13:65:13:65:17":5,"b:64:26:64:46:64:46:64:51":6,"s:67:8:67:Infinity":33,"b:70:8:72:Infinity:undefined:undefined:undefined:undefined":7,"s:70:8:72:Infinity":34,"s:71:12:71:Infinity":35,"s:76:21:78:Infinity":36,"f:76:21:76:27":8,"s:77:4:77:Infinity":37,"s:80:23:98:Infinity":38,"f:80:23:80:35":9,"b:81:4:81:Infinity:undefined:undefined:undefined:undefined":8,"s:81:4:81:Infinity":39,"s:81:20:81:Infinity":40,"s:82:4:97:Infinity":41,"s:83:8:83:Infinity":42,"s:84:8:84:Infinity":43,"s:85:8:85:Infinity":44,"s:88:8:90:Infinity":45,"f:88:19:88:25":10,"s:89:12:89:Infinity":46,"b:93:8:95:Infinity:undefined:undefined:undefined:undefined":9,"s:93:8:95:Infinity":47,"s:94:12:94:Infinity":48,"s:96:8:96:Infinity":49,"s:100:22:122:Infinity":50,"f:100:22:100:34":11,"b:101:4:101:Infinity:undefined:undefined:undefined:undefined":10,"s:101:4:101:Infinity":51,"s:101:20:101:Infinity":52,"s:103:4:121:Infinity":53,"s:104:8:104:Infinity":54,"s:107:8:111:Infinity":55,"f:107:21:107:22":12,"s:107:54:111:17":56,"b:107:62:111:13:111:13:111:17":11,"b:110:35:110:55:110:55:110:60":12,"s:113:8:113:Infinity":57,"s:114:8:114:Infinity":58,"b:117:8:119:Infinity:undefined:undefined:undefined:undefined":13,"s:117:8:119:Infinity":59,"s:118:12:118:Infinity":60,"s:120:8:120:Infinity":61,"b:124:2:124:Infinity:undefined:undefined:undefined:undefined":14,"s:124:2:124:Infinity":62,"s:124:18:124:Infinity":63,"s:126:2:250:Infinity":64,"b:130:7:130:Infinity:131:8:135:Infinity":15,"f:134:19:134:25":13,"s:134:25:134:Infinity":65,"b:149:13:149:Infinity:150:12:152:Infinity":16,"b:154:13:154:35:154:35:154:Infinity:155:16:157:Infinity":17,"f:155:40:155:46":14,"s:155:46:155:73":66,"b:159:12:159:Infinity:160:16:179:Infinity":18,"f:161:46:161:52":15,"s:161:52:161:Infinity":67,"b:165:21:165:Infinity:166:24:177:Infinity":19,"f:171:55:171:61":16,"s:172:32:172:Infinity":68,"s:173:32:173:Infinity":69,"f:186:23:186:Infinity":17,"s:187:14:189:Infinity":70,"b:187:38:187:56:187:56:187:Infinity":20,"f:199:43:199:44":18,"s:200:16:200:Infinity":71,"f:209:17:209:23":19,"s:209:23:209:Infinity":72,"f:218:46:218:52":20,"s:218:52:218:81":73,"f:230:17:230:23":21,"s:230:23:230:Infinity":74,"f:238:46:238:52":22,"s:238:52:238:80":75}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/CommunityPage/styles.ts": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/CommunityPage/styles.ts","statementMap":{"0":{"start":{"line":3,"column":27},"end":{"line":6,"column":null}},"1":{"start":{"line":6,"column":49},"end":{"line":6,"column":66}},"2":{"start":{"line":6,"column":83},"end":{"line":6,"column":133}},"3":{"start":{"line":9,"column":27},"end":{"line":9,"column":null}},"4":{"start":{"line":29,"column":22},"end":{"line":32,"column":null}},"5":{"start":{"line":32,"column":49},"end":{"line":32,"column":67}},"6":{"start":{"line":32,"column":84},"end":{"line":32,"column":138}},"7":{"start":{"line":60,"column":31},"end":{"line":60,"column":null}},"8":{"start":{"line":85,"column":22},"end":{"line":90,"column":null}},"9":{"start":{"line":89,"column":49},"end":{"line":89,"column":68}},"10":{"start":{"line":89,"column":85},"end":{"line":89,"column":103}},"11":{"start":{"line":90,"column":31},"end":{"line":90,"column":48}},"12":{"start":{"line":117,"column":26},"end":{"line":161,"column":null}},"13":{"start":{"line":128,"column":22},"end":{"line":128,"column":39}},"14":{"start":{"line":134,"column":51},"end":{"line":134,"column":68}},"15":{"start":{"line":134,"column":85},"end":{"line":134,"column":103}},"16":{"start":{"line":151,"column":52},"end":{"line":151,"column":70}},"17":{"start":{"line":157,"column":22},"end":{"line":157,"column":72}},"18":{"start":{"line":161,"column":27},"end":{"line":161,"column":50}},"19":{"start":{"line":176,"column":29},"end":{"line":176,"column":null}},"20":{"start":{"line":183,"column":26},"end":{"line":216,"column":null}},"21":{"start":{"line":186,"column":31},"end":{"line":186,"column":49}},"22":{"start":{"line":187,"column":25},"end":{"line":187,"column":43}},"23":{"start":{"line":188,"column":20},"end":{"line":188,"column":37}},"24":{"start":{"line":193,"column":36},"end":{"line":193,"column":54}},"25":{"start":{"line":215,"column":38},"end":{"line":215,"column":56}},"26":{"start":{"line":216,"column":27},"end":{"line":216,"column":76}},"27":{"start":{"line":224,"column":27},"end":{"line":259,"column":null}},"28":{"start":{"line":227,"column":31},"end":{"line":227,"column":53}},"29":{"start":{"line":229,"column":20},"end":{"line":229,"column":42}},"30":{"start":{"line":244,"column":27},"end":{"line":244,"column":49}},"31":{"start":{"line":257,"column":22},"end":{"line":257,"column":39}},"32":{"start":{"line":258,"column":29},"end":{"line":258,"column":51}},"33":{"start":{"line":259,"column":38},"end":{"line":259,"column":60}},"34":{"start":{"line":273,"column":29},"end":{"line":292,"column":null}},"35":{"start":{"line":277,"column":31},"end":{"line":277,"column":49}},"36":{"start":{"line":278,"column":25},"end":{"line":278,"column":42}},"37":{"start":{"line":279,"column":20},"end":{"line":279,"column":38}},"38":{"start":{"line":289,"column":33},"end":{"line":289,"column":51}},"39":{"start":{"line":290,"column":22},"end":{"line":290,"column":39}},"40":{"start":{"line":292,"column":38},"end":{"line":292,"column":56}},"41":{"start":{"line":302,"column":27},"end":{"line":302,"column":null}},"42":{"start":{"line":316,"column":26},"end":{"line":316,"column":null}},"43":{"start":{"line":335,"column":31},"end":{"line":336,"column":null}},"44":{"start":{"line":336,"column":49},"end":{"line":336,"column":71}},"45":{"start":{"line":336,"column":88},"end":{"line":336,"column":137}},"46":{"start":{"line":350,"column":27},"end":{"line":406,"column":null}},"47":{"start":{"line":351,"column":25},"end":{"line":351,"column":42}},"48":{"start":{"line":352,"column":31},"end":{"line":352,"column":49}},"49":{"start":{"line":377,"column":22},"end":{"line":377,"column":39}},"50":{"start":{"line":396,"column":53},"end":{"line":396,"column":71}},"51":{"start":{"line":396,"column":88},"end":{"line":396,"column":137}},"52":{"start":{"line":406,"column":22},"end":{"line":406,"column":66}},"53":{"start":{"line":418,"column":33},"end":{"line":418,"column":null}},"54":{"start":{"line":425,"column":26},"end":{"line":439,"column":null}},"55":{"start":{"line":426,"column":31},"end":{"line":426,"column":50}},"56":{"start":{"line":427,"column":20},"end":{"line":427,"column":39}},"57":{"start":{"line":432,"column":25},"end":{"line":432,"column":44}},"58":{"start":{"line":437,"column":27},"end":{"line":437,"column":46}},"59":{"start":{"line":439,"column":37},"end":{"line":439,"column":56}},"60":{"start":{"line":443,"column":27},"end":{"line":443,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":6,"column":40},"end":{"line":6,"column":49}},"loc":{"start":{"line":6,"column":49},"end":{"line":6,"column":66}},"line":6},"1":{"name":"(anonymous_1)","decl":{"start":{"line":6,"column":74},"end":{"line":6,"column":83}},"loc":{"start":{"line":6,"column":83},"end":{"line":6,"column":133}},"line":6},"2":{"name":"(anonymous_2)","decl":{"start":{"line":32,"column":40},"end":{"line":32,"column":49}},"loc":{"start":{"line":32,"column":49},"end":{"line":32,"column":67}},"line":32},"3":{"name":"(anonymous_3)","decl":{"start":{"line":32,"column":75},"end":{"line":32,"column":84}},"loc":{"start":{"line":32,"column":84},"end":{"line":32,"column":138}},"line":32},"4":{"name":"(anonymous_4)","decl":{"start":{"line":89,"column":40},"end":{"line":89,"column":49}},"loc":{"start":{"line":89,"column":49},"end":{"line":89,"column":68}},"line":89},"5":{"name":"(anonymous_5)","decl":{"start":{"line":89,"column":76},"end":{"line":89,"column":85}},"loc":{"start":{"line":89,"column":85},"end":{"line":89,"column":103}},"line":89},"6":{"name":"(anonymous_6)","decl":{"start":{"line":90,"column":22},"end":{"line":90,"column":31}},"loc":{"start":{"line":90,"column":31},"end":{"line":90,"column":48}},"line":90},"7":{"name":"(anonymous_7)","decl":{"start":{"line":128,"column":13},"end":{"line":128,"column":22}},"loc":{"start":{"line":128,"column":22},"end":{"line":128,"column":39}},"line":128},"8":{"name":"(anonymous_8)","decl":{"start":{"line":134,"column":42},"end":{"line":134,"column":51}},"loc":{"start":{"line":134,"column":51},"end":{"line":134,"column":68}},"line":134},"9":{"name":"(anonymous_9)","decl":{"start":{"line":134,"column":76},"end":{"line":134,"column":85}},"loc":{"start":{"line":134,"column":85},"end":{"line":134,"column":103}},"line":134},"10":{"name":"(anonymous_10)","decl":{"start":{"line":151,"column":43},"end":{"line":151,"column":52}},"loc":{"start":{"line":151,"column":52},"end":{"line":151,"column":70}},"line":151},"11":{"name":"(anonymous_11)","decl":{"start":{"line":157,"column":13},"end":{"line":157,"column":22}},"loc":{"start":{"line":157,"column":22},"end":{"line":157,"column":72}},"line":157},"12":{"name":"(anonymous_12)","decl":{"start":{"line":161,"column":18},"end":{"line":161,"column":27}},"loc":{"start":{"line":161,"column":27},"end":{"line":161,"column":50}},"line":161},"13":{"name":"(anonymous_13)","decl":{"start":{"line":186,"column":22},"end":{"line":186,"column":31}},"loc":{"start":{"line":186,"column":31},"end":{"line":186,"column":49}},"line":186},"14":{"name":"(anonymous_14)","decl":{"start":{"line":187,"column":16},"end":{"line":187,"column":25}},"loc":{"start":{"line":187,"column":25},"end":{"line":187,"column":43}},"line":187},"15":{"name":"(anonymous_15)","decl":{"start":{"line":188,"column":11},"end":{"line":188,"column":20}},"loc":{"start":{"line":188,"column":20},"end":{"line":188,"column":37}},"line":188},"16":{"name":"(anonymous_16)","decl":{"start":{"line":193,"column":27},"end":{"line":193,"column":36}},"loc":{"start":{"line":193,"column":36},"end":{"line":193,"column":54}},"line":193},"17":{"name":"(anonymous_17)","decl":{"start":{"line":215,"column":29},"end":{"line":215,"column":38}},"loc":{"start":{"line":215,"column":38},"end":{"line":215,"column":56}},"line":215},"18":{"name":"(anonymous_18)","decl":{"start":{"line":216,"column":18},"end":{"line":216,"column":27}},"loc":{"start":{"line":216,"column":27},"end":{"line":216,"column":76}},"line":216},"19":{"name":"(anonymous_19)","decl":{"start":{"line":227,"column":22},"end":{"line":227,"column":31}},"loc":{"start":{"line":227,"column":31},"end":{"line":227,"column":53}},"line":227},"20":{"name":"(anonymous_20)","decl":{"start":{"line":229,"column":11},"end":{"line":229,"column":20}},"loc":{"start":{"line":229,"column":20},"end":{"line":229,"column":42}},"line":229},"21":{"name":"(anonymous_21)","decl":{"start":{"line":244,"column":18},"end":{"line":244,"column":27}},"loc":{"start":{"line":244,"column":27},"end":{"line":244,"column":49}},"line":244},"22":{"name":"(anonymous_22)","decl":{"start":{"line":257,"column":13},"end":{"line":257,"column":22}},"loc":{"start":{"line":257,"column":22},"end":{"line":257,"column":39}},"line":257},"23":{"name":"(anonymous_23)","decl":{"start":{"line":258,"column":20},"end":{"line":258,"column":29}},"loc":{"start":{"line":258,"column":29},"end":{"line":258,"column":51}},"line":258},"24":{"name":"(anonymous_24)","decl":{"start":{"line":259,"column":29},"end":{"line":259,"column":38}},"loc":{"start":{"line":259,"column":38},"end":{"line":259,"column":60}},"line":259},"25":{"name":"(anonymous_25)","decl":{"start":{"line":277,"column":22},"end":{"line":277,"column":31}},"loc":{"start":{"line":277,"column":31},"end":{"line":277,"column":49}},"line":277},"26":{"name":"(anonymous_26)","decl":{"start":{"line":278,"column":16},"end":{"line":278,"column":25}},"loc":{"start":{"line":278,"column":25},"end":{"line":278,"column":42}},"line":278},"27":{"name":"(anonymous_27)","decl":{"start":{"line":279,"column":11},"end":{"line":279,"column":20}},"loc":{"start":{"line":279,"column":20},"end":{"line":279,"column":38}},"line":279},"28":{"name":"(anonymous_28)","decl":{"start":{"line":289,"column":24},"end":{"line":289,"column":33}},"loc":{"start":{"line":289,"column":33},"end":{"line":289,"column":51}},"line":289},"29":{"name":"(anonymous_29)","decl":{"start":{"line":290,"column":13},"end":{"line":290,"column":22}},"loc":{"start":{"line":290,"column":22},"end":{"line":290,"column":39}},"line":290},"30":{"name":"(anonymous_30)","decl":{"start":{"line":292,"column":29},"end":{"line":292,"column":38}},"loc":{"start":{"line":292,"column":38},"end":{"line":292,"column":56}},"line":292},"31":{"name":"(anonymous_31)","decl":{"start":{"line":336,"column":40},"end":{"line":336,"column":49}},"loc":{"start":{"line":336,"column":49},"end":{"line":336,"column":71}},"line":336},"32":{"name":"(anonymous_32)","decl":{"start":{"line":336,"column":79},"end":{"line":336,"column":88}},"loc":{"start":{"line":336,"column":88},"end":{"line":336,"column":137}},"line":336},"33":{"name":"(anonymous_33)","decl":{"start":{"line":351,"column":16},"end":{"line":351,"column":25}},"loc":{"start":{"line":351,"column":25},"end":{"line":351,"column":42}},"line":351},"34":{"name":"(anonymous_34)","decl":{"start":{"line":352,"column":22},"end":{"line":352,"column":31}},"loc":{"start":{"line":352,"column":31},"end":{"line":352,"column":49}},"line":352},"35":{"name":"(anonymous_35)","decl":{"start":{"line":377,"column":13},"end":{"line":377,"column":22}},"loc":{"start":{"line":377,"column":22},"end":{"line":377,"column":39}},"line":377},"36":{"name":"(anonymous_36)","decl":{"start":{"line":396,"column":44},"end":{"line":396,"column":53}},"loc":{"start":{"line":396,"column":53},"end":{"line":396,"column":71}},"line":396},"37":{"name":"(anonymous_37)","decl":{"start":{"line":396,"column":79},"end":{"line":396,"column":88}},"loc":{"start":{"line":396,"column":88},"end":{"line":396,"column":137}},"line":396},"38":{"name":"(anonymous_38)","decl":{"start":{"line":406,"column":13},"end":{"line":406,"column":22}},"loc":{"start":{"line":406,"column":22},"end":{"line":406,"column":66}},"line":406},"39":{"name":"(anonymous_39)","decl":{"start":{"line":426,"column":22},"end":{"line":426,"column":31}},"loc":{"start":{"line":426,"column":31},"end":{"line":426,"column":50}},"line":426},"40":{"name":"(anonymous_40)","decl":{"start":{"line":427,"column":11},"end":{"line":427,"column":20}},"loc":{"start":{"line":427,"column":20},"end":{"line":427,"column":39}},"line":427},"41":{"name":"(anonymous_41)","decl":{"start":{"line":432,"column":16},"end":{"line":432,"column":25}},"loc":{"start":{"line":432,"column":25},"end":{"line":432,"column":44}},"line":432},"42":{"name":"(anonymous_42)","decl":{"start":{"line":437,"column":18},"end":{"line":437,"column":27}},"loc":{"start":{"line":437,"column":27},"end":{"line":437,"column":46}},"line":437},"43":{"name":"(anonymous_43)","decl":{"start":{"line":439,"column":28},"end":{"line":439,"column":37}},"loc":{"start":{"line":439,"column":37},"end":{"line":439,"column":56}},"line":439}},"branchMap":{"0":{"loc":{"start":{"line":6,"column":83},"end":{"line":6,"column":133}},"type":"binary-expr","locations":[{"start":{"line":6,"column":83},"end":{"line":6,"column":110}},{"start":{"line":6,"column":110},"end":{"line":6,"column":133}}],"line":6},"1":{"loc":{"start":{"line":32,"column":84},"end":{"line":32,"column":138}},"type":"binary-expr","locations":[{"start":{"line":32,"column":84},"end":{"line":32,"column":115}},{"start":{"line":32,"column":115},"end":{"line":32,"column":138}}],"line":32},"2":{"loc":{"start":{"line":157,"column":22},"end":{"line":157,"column":72}},"type":"binary-expr","locations":[{"start":{"line":157,"column":22},"end":{"line":157,"column":49}},{"start":{"line":157,"column":49},"end":{"line":157,"column":72}}],"line":157},"3":{"loc":{"start":{"line":216,"column":27},"end":{"line":216,"column":76}},"type":"binary-expr","locations":[{"start":{"line":216,"column":27},"end":{"line":216,"column":58}},{"start":{"line":216,"column":58},"end":{"line":216,"column":76}}],"line":216},"4":{"loc":{"start":{"line":336,"column":88},"end":{"line":336,"column":137}},"type":"binary-expr","locations":[{"start":{"line":336,"column":88},"end":{"line":336,"column":115}},{"start":{"line":336,"column":115},"end":{"line":336,"column":137}}],"line":336},"5":{"loc":{"start":{"line":396,"column":88},"end":{"line":396,"column":137}},"type":"binary-expr","locations":[{"start":{"line":396,"column":88},"end":{"line":396,"column":119}},{"start":{"line":396,"column":119},"end":{"line":396,"column":137}}],"line":396},"6":{"loc":{"start":{"line":406,"column":22},"end":{"line":406,"column":66}},"type":"binary-expr","locations":[{"start":{"line":406,"column":22},"end":{"line":406,"column":49}},{"start":{"line":406,"column":49},"end":{"line":406,"column":66}}],"line":406}},"s":{"0":1,"1":10,"2":10,"3":1,"4":1,"5":10,"6":10,"7":1,"8":1,"9":10,"10":10,"11":10,"12":1,"13":10,"14":10,"15":10,"16":10,"17":10,"18":10,"19":1,"20":1,"21":3,"22":3,"23":3,"24":3,"25":3,"26":3,"27":1,"28":3,"29":3,"30":3,"31":3,"32":3,"33":3,"34":1,"35":4,"36":4,"37":4,"38":4,"39":4,"40":4,"41":1,"42":1,"43":1,"44":10,"45":10,"46":1,"47":10,"48":10,"49":10,"50":10,"51":10,"52":10,"53":1,"54":1,"55":10,"56":10,"57":10,"58":10,"59":10,"60":1},"f":{"0":10,"1":10,"2":10,"3":10,"4":10,"5":10,"6":10,"7":10,"8":10,"9":10,"10":10,"11":10,"12":10,"13":3,"14":3,"15":3,"16":3,"17":3,"18":3,"19":3,"20":3,"21":3,"22":3,"23":3,"24":3,"25":4,"26":4,"27":4,"28":4,"29":4,"30":4,"31":10,"32":10,"33":10,"34":10,"35":10,"36":10,"37":10,"38":10,"39":10,"40":10,"41":10,"42":10,"43":10},"b":{"0":[10,10],"1":[10,10],"2":[10,10],"3":[3,3],"4":[10,10],"5":[10,10],"6":[10,10]},"meta":{"lastBranch":7,"lastFunction":44,"lastStatement":61,"seen":{"s:3:27:6:Infinity":0,"f:6:40:6:49":0,"s:6:49:6:66":1,"f:6:74:6:83":1,"s:6:83:6:133":2,"b:6:83:6:110:6:110:6:133":0,"s:9:27:9:Infinity":3,"s:29:22:32:Infinity":4,"f:32:40:32:49":2,"s:32:49:32:67":5,"f:32:75:32:84":3,"s:32:84:32:138":6,"b:32:84:32:115:32:115:32:138":1,"s:60:31:60:Infinity":7,"s:85:22:90:Infinity":8,"f:89:40:89:49":4,"s:89:49:89:68":9,"f:89:76:89:85":5,"s:89:85:89:103":10,"f:90:22:90:31":6,"s:90:31:90:48":11,"s:117:26:161:Infinity":12,"f:128:13:128:22":7,"s:128:22:128:39":13,"f:134:42:134:51":8,"s:134:51:134:68":14,"f:134:76:134:85":9,"s:134:85:134:103":15,"f:151:43:151:52":10,"s:151:52:151:70":16,"f:157:13:157:22":11,"s:157:22:157:72":17,"b:157:22:157:49:157:49:157:72":2,"f:161:18:161:27":12,"s:161:27:161:50":18,"s:176:29:176:Infinity":19,"s:183:26:216:Infinity":20,"f:186:22:186:31":13,"s:186:31:186:49":21,"f:187:16:187:25":14,"s:187:25:187:43":22,"f:188:11:188:20":15,"s:188:20:188:37":23,"f:193:27:193:36":16,"s:193:36:193:54":24,"f:215:29:215:38":17,"s:215:38:215:56":25,"f:216:18:216:27":18,"s:216:27:216:76":26,"b:216:27:216:58:216:58:216:76":3,"s:224:27:259:Infinity":27,"f:227:22:227:31":19,"s:227:31:227:53":28,"f:229:11:229:20":20,"s:229:20:229:42":29,"f:244:18:244:27":21,"s:244:27:244:49":30,"f:257:13:257:22":22,"s:257:22:257:39":31,"f:258:20:258:29":23,"s:258:29:258:51":32,"f:259:29:259:38":24,"s:259:38:259:60":33,"s:273:29:292:Infinity":34,"f:277:22:277:31":25,"s:277:31:277:49":35,"f:278:16:278:25":26,"s:278:25:278:42":36,"f:279:11:279:20":27,"s:279:20:279:38":37,"f:289:24:289:33":28,"s:289:33:289:51":38,"f:290:13:290:22":29,"s:290:22:290:39":39,"f:292:29:292:38":30,"s:292:38:292:56":40,"s:302:27:302:Infinity":41,"s:316:26:316:Infinity":42,"s:335:31:336:Infinity":43,"f:336:40:336:49":31,"s:336:49:336:71":44,"f:336:79:336:88":32,"s:336:88:336:137":45,"b:336:88:336:115:336:115:336:137":4,"s:350:27:406:Infinity":46,"f:351:16:351:25":33,"s:351:25:351:42":47,"f:352:22:352:31":34,"s:352:31:352:49":48,"f:377:13:377:22":35,"s:377:22:377:39":49,"f:396:44:396:53":36,"s:396:53:396:71":50,"f:396:79:396:88":37,"s:396:88:396:137":51,"b:396:88:396:119:396:119:396:137":5,"f:406:13:406:22":38,"s:406:22:406:66":52,"b:406:22:406:49:406:49:406:66":6,"s:418:33:418:Infinity":53,"s:425:26:439:Infinity":54,"f:426:22:426:31":39,"s:426:31:426:50":55,"f:427:11:427:20":40,"s:427:20:427:39":56,"f:432:16:432:25":41,"s:432:25:432:44":57,"f:437:18:437:27":42,"s:437:27:437:46":58,"f:439:28:439:37":43,"s:439:37:439:56":59,"s:443:27:443:Infinity":60}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/CreateCommunity/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/CreateCommunity/index.tsx","statementMap":{"0":{"start":{"line":15,"column":8},"end":{"line":15,"column":null}},"1":{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},"2":{"start":{"line":18,"column":26},"end":{"line":18,"column":null}},"3":{"start":{"line":19,"column":21},"end":{"line":19,"column":null}},"4":{"start":{"line":21,"column":49},"end":{"line":29,"column":null}},"5":{"start":{"line":31,"column":27},"end":{"line":31,"column":null}},"6":{"start":{"line":32,"column":28},"end":{"line":32,"column":null}},"7":{"start":{"line":33,"column":20},"end":{"line":33,"column":null}},"8":{"start":{"line":34,"column":38},"end":{"line":34,"column":null}},"9":{"start":{"line":35,"column":30},"end":{"line":35,"column":null}},"10":{"start":{"line":37,"column":2},"end":{"line":47,"column":null}},"11":{"start":{"line":39,"column":8},"end":{"line":44,"column":null}},"12":{"start":{"line":40,"column":30},"end":{"line":40,"column":null}},"13":{"start":{"line":41,"column":10},"end":{"line":41,"column":null}},"14":{"start":{"line":43,"column":10},"end":{"line":43,"column":null}},"15":{"start":{"line":46,"column":6},"end":{"line":46,"column":null}},"16":{"start":{"line":49,"column":19},"end":{"line":74,"column":null}},"17":{"start":{"line":50,"column":4},"end":{"line":72,"column":null}},"18":{"start":{"line":51,"column":6},"end":{"line":61,"column":null}},"19":{"start":{"line":53,"column":8},"end":{"line":53,"column":null}},"20":{"start":{"line":54,"column":8},"end":{"line":54,"column":null}},"21":{"start":{"line":55,"column":8},"end":{"line":55,"column":null}},"22":{"start":{"line":58,"column":8},"end":{"line":58,"column":null}},"23":{"start":{"line":59,"column":8},"end":{"line":59,"column":null}},"24":{"start":{"line":60,"column":8},"end":{"line":60,"column":null}},"25":{"start":{"line":63,"column":6},"end":{"line":65,"column":null}},"26":{"start":{"line":64,"column":10},"end":{"line":64,"column":null}},"27":{"start":{"line":68,"column":6},"end":{"line":68,"column":null}},"28":{"start":{"line":69,"column":6},"end":{"line":71,"column":null}},"29":{"start":{"line":70,"column":8},"end":{"line":70,"column":null}},"30":{"start":{"line":76,"column":2},"end":{"line":138,"column":null}},"31":{"start":{"line":84,"column":25},"end":{"line":84,"column":null}},"32":{"start":{"line":123,"column":16},"end":{"line":129,"column":null}}},"fnMap":{"0":{"name":"CreateCommunity","decl":{"start":{"line":14,"column":24},"end":{"line":14,"column":42}},"loc":{"start":{"line":14,"column":42},"end":{"line":140,"column":null}},"line":14},"1":{"name":"(anonymous_1)","decl":{"start":{"line":37,"column":12},"end":{"line":37,"column":18}},"loc":{"start":{"line":37,"column":18},"end":{"line":47,"column":7}},"line":37},"2":{"name":"loadTechs","decl":{"start":{"line":38,"column":21},"end":{"line":38,"column":33}},"loc":{"start":{"line":38,"column":33},"end":{"line":45,"column":null}},"line":38},"3":{"name":"(anonymous_3)","decl":{"start":{"line":49,"column":19},"end":{"line":49,"column":20}},"loc":{"start":{"line":49,"column":45},"end":{"line":74,"column":null}},"line":49},"4":{"name":"(anonymous_4)","decl":{"start":{"line":63,"column":17},"end":{"line":63,"column":23}},"loc":{"start":{"line":63,"column":23},"end":{"line":65,"column":9}},"line":63},"5":{"name":"(anonymous_5)","decl":{"start":{"line":84,"column":19},"end":{"line":84,"column":25}},"loc":{"start":{"line":84,"column":25},"end":{"line":84,"column":null}},"line":84},"6":{"name":"(anonymous_6)","decl":{"start":{"line":122,"column":22},"end":{"line":122,"column":23}},"loc":{"start":{"line":123,"column":16},"end":{"line":129,"column":null}},"line":123}},"branchMap":{"0":{"loc":{"start":{"line":24,"column":19},"end":{"line":24,"column":null}},"type":"binary-expr","locations":[{"start":{"line":24,"column":19},"end":{"line":24,"column":51}},{"start":{"line":24,"column":51},"end":{"line":24,"column":null}}],"line":24},"1":{"loc":{"start":{"line":25,"column":12},"end":{"line":25,"column":null}},"type":"binary-expr","locations":[{"start":{"line":25,"column":12},"end":{"line":25,"column":37}},{"start":{"line":25,"column":37},"end":{"line":25,"column":null}}],"line":25},"2":{"loc":{"start":{"line":26,"column":19},"end":{"line":26,"column":null}},"type":"binary-expr","locations":[{"start":{"line":26,"column":19},"end":{"line":26,"column":51}},{"start":{"line":26,"column":51},"end":{"line":26,"column":null}}],"line":26},"3":{"loc":{"start":{"line":27,"column":20},"end":{"line":27,"column":null}},"type":"binary-expr","locations":[{"start":{"line":27,"column":20},"end":{"line":27,"column":53}},{"start":{"line":27,"column":53},"end":{"line":27,"column":null}}],"line":27},"4":{"loc":{"start":{"line":32,"column":28},"end":{"line":32,"column":null}},"type":"cond-expr","locations":[{"start":{"line":32,"column":47},"end":{"line":32,"column":73}},{"start":{"line":32,"column":73},"end":{"line":32,"column":null}}],"line":32},"5":{"loc":{"start":{"line":51,"column":6},"end":{"line":61,"column":null}},"type":"if","locations":[{"start":{"line":51,"column":6},"end":{"line":61,"column":null}},{"start":{"line":56,"column":13},"end":{"line":61,"column":null}}],"line":51},"6":{"loc":{"start":{"line":51,"column":10},"end":{"line":51,"column":41}},"type":"binary-expr","locations":[{"start":{"line":51,"column":10},"end":{"line":51,"column":24}},{"start":{"line":51,"column":24},"end":{"line":51,"column":41}}],"line":51},"7":{"loc":{"start":{"line":69,"column":6},"end":{"line":71,"column":null}},"type":"if","locations":[{"start":{"line":69,"column":6},"end":{"line":71,"column":null}},{"start":{},"end":{}}],"line":69},"8":{"loc":{"start":{"line":80,"column":7},"end":{"line":85,"column":null}},"type":"binary-expr","locations":[{"start":{"line":80,"column":7},"end":{"line":80,"column":null}},{"start":{"line":81,"column":8},"end":{"line":85,"column":null}}],"line":80},"9":{"loc":{"start":{"line":91,"column":15},"end":{"line":91,"column":69}},"type":"cond-expr","locations":[{"start":{"line":91,"column":28},"end":{"line":91,"column":50}},{"start":{"line":91,"column":50},"end":{"line":91,"column":69}}],"line":91},"10":{"loc":{"start":{"line":134,"column":41},"end":{"line":134,"column":95}},"type":"cond-expr","locations":[{"start":{"line":134,"column":54},"end":{"line":134,"column":76}},{"start":{"line":134,"column":76},"end":{"line":134,"column":95}}],"line":134}},"s":{"0":7,"1":7,"2":7,"3":7,"4":7,"5":7,"6":7,"7":7,"8":7,"9":7,"10":7,"11":2,"12":2,"13":2,"14":0,"15":2,"16":7,"17":2,"18":2,"19":1,"20":1,"21":1,"22":1,"23":1,"24":1,"25":2,"26":0,"27":0,"28":0,"29":0,"30":7,"31":0,"32":10},"f":{"0":7,"1":2,"2":2,"3":2,"4":0,"5":0,"6":10},"b":{"0":[7,4],"1":[7,4],"2":[7,4],"3":[7,4],"4":[5,2],"5":[1,1],"6":[2,1],"7":[0,0],"8":[7,2],"9":[3,4],"10":[3,4]},"meta":{"lastBranch":11,"lastFunction":7,"lastStatement":33,"seen":{"f:14:24:14:42":0,"s:15:8:15:Infinity":0,"s:16:8:16:Infinity":1,"s:18:26:18:Infinity":2,"s:19:21:19:Infinity":3,"s:21:49:29:Infinity":4,"b:24:19:24:51:24:51:24:Infinity":0,"b:25:12:25:37:25:37:25:Infinity":1,"b:26:19:26:51:26:51:26:Infinity":2,"b:27:20:27:53:27:53:27:Infinity":3,"s:31:27:31:Infinity":5,"s:32:28:32:Infinity":6,"b:32:47:32:73:32:73:32:Infinity":4,"s:33:20:33:Infinity":7,"s:34:38:34:Infinity":8,"s:35:30:35:Infinity":9,"s:37:2:47:Infinity":10,"f:37:12:37:18":1,"f:38:21:38:33":2,"s:39:8:44:Infinity":11,"s:40:30:40:Infinity":12,"s:41:10:41:Infinity":13,"s:43:10:43:Infinity":14,"s:46:6:46:Infinity":15,"s:49:19:74:Infinity":16,"f:49:19:49:20":3,"s:50:4:72:Infinity":17,"b:51:6:61:Infinity:56:13:61:Infinity":5,"s:51:6:61:Infinity":18,"b:51:10:51:24:51:24:51:41":6,"s:53:8:53:Infinity":19,"s:54:8:54:Infinity":20,"s:55:8:55:Infinity":21,"s:58:8:58:Infinity":22,"s:59:8:59:Infinity":23,"s:60:8:60:Infinity":24,"s:63:6:65:Infinity":25,"f:63:17:63:23":4,"s:64:10:64:Infinity":26,"s:68:6:68:Infinity":27,"b:69:6:71:Infinity:undefined:undefined:undefined:undefined":7,"s:69:6:71:Infinity":28,"s:70:8:70:Infinity":29,"s:76:2:138:Infinity":30,"b:80:7:80:Infinity:81:8:85:Infinity":8,"f:84:19:84:25":5,"s:84:25:84:Infinity":31,"b:91:28:91:50:91:50:91:69":9,"f:122:22:122:23":6,"s:123:16:129:Infinity":32,"b:134:54:134:76:134:76:134:95":10}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/CreateProject/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/CreateProject/index.tsx","statementMap":{"0":{"start":{"line":21,"column":8},"end":{"line":21,"column":null}},"1":{"start":{"line":22,"column":8},"end":{"line":22,"column":null}},"2":{"start":{"line":23,"column":30},"end":{"line":23,"column":null}},"3":{"start":{"line":25,"column":29},"end":{"line":25,"column":null}},"4":{"start":{"line":28,"column":24},"end":{"line":28,"column":null}},"5":{"start":{"line":30,"column":21},"end":{"line":30,"column":null}},"6":{"start":{"line":32,"column":25},"end":{"line":34,"column":null}},"7":{"start":{"line":36,"column":29},"end":{"line":42,"column":null}},"8":{"start":{"line":37,"column":4},"end":{"line":37,"column":null}},"9":{"start":{"line":37,"column":15},"end":{"line":37,"column":null}},"10":{"start":{"line":38,"column":14},"end":{"line":38,"column":null}},"11":{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},"12":{"start":{"line":40,"column":28},"end":{"line":40,"column":null}},"13":{"start":{"line":41,"column":4},"end":{"line":41,"column":null}},"14":{"start":{"line":44,"column":49},"end":{"line":53,"column":null}},"15":{"start":{"line":55,"column":27},"end":{"line":55,"column":null}},"16":{"start":{"line":56,"column":28},"end":{"line":56,"column":null}},"17":{"start":{"line":57,"column":20},"end":{"line":57,"column":null}},"18":{"start":{"line":58,"column":38},"end":{"line":58,"column":null}},"19":{"start":{"line":61,"column":2},"end":{"line":71,"column":null}},"20":{"start":{"line":63,"column":6},"end":{"line":68,"column":null}},"21":{"start":{"line":64,"column":28},"end":{"line":64,"column":null}},"22":{"start":{"line":65,"column":8},"end":{"line":65,"column":null}},"23":{"start":{"line":67,"column":8},"end":{"line":67,"column":null}},"24":{"start":{"line":70,"column":4},"end":{"line":70,"column":null}},"25":{"start":{"line":74,"column":19},"end":{"line":105,"column":null}},"26":{"start":{"line":76,"column":36},"end":{"line":79,"column":null}},"27":{"start":{"line":81,"column":4},"end":{"line":104,"column":null}},"28":{"start":{"line":82,"column":6},"end":{"line":92,"column":null}},"29":{"start":{"line":84,"column":8},"end":{"line":84,"column":null}},"30":{"start":{"line":85,"column":8},"end":{"line":85,"column":null}},"31":{"start":{"line":86,"column":8},"end":{"line":86,"column":null}},"32":{"start":{"line":89,"column":8},"end":{"line":89,"column":null}},"33":{"start":{"line":90,"column":8},"end":{"line":90,"column":null}},"34":{"start":{"line":91,"column":8},"end":{"line":91,"column":null}},"35":{"start":{"line":95,"column":6},"end":{"line":97,"column":null}},"36":{"start":{"line":96,"column":10},"end":{"line":96,"column":null}},"37":{"start":{"line":100,"column":6},"end":{"line":100,"column":null}},"38":{"start":{"line":101,"column":6},"end":{"line":103,"column":null}},"39":{"start":{"line":102,"column":8},"end":{"line":102,"column":null}},"40":{"start":{"line":107,"column":2},"end":{"line":205,"column":null}},"41":{"start":{"line":114,"column":25},"end":{"line":114,"column":null}},"42":{"start":{"line":152,"column":16},"end":{"line":160,"column":null}},"43":{"start":{"line":158,"column":47},"end":{"line":158,"column":null}},"44":{"start":{"line":171,"column":16},"end":{"line":177,"column":null}}},"fnMap":{"0":{"name":"CreateProject","decl":{"start":{"line":20,"column":24},"end":{"line":20,"column":40}},"loc":{"start":{"line":20,"column":40},"end":{"line":207,"column":null}},"line":20},"1":{"name":"(anonymous_1)","decl":{"start":{"line":36,"column":29},"end":{"line":36,"column":30}},"loc":{"start":{"line":36,"column":55},"end":{"line":42,"column":null}},"line":36},"2":{"name":"(anonymous_2)","decl":{"start":{"line":61,"column":12},"end":{"line":61,"column":18}},"loc":{"start":{"line":61,"column":18},"end":{"line":71,"column":5}},"line":61},"3":{"name":"loadTechs","decl":{"start":{"line":62,"column":19},"end":{"line":62,"column":31}},"loc":{"start":{"line":62,"column":31},"end":{"line":69,"column":null}},"line":62},"4":{"name":"(anonymous_4)","decl":{"start":{"line":74,"column":19},"end":{"line":74,"column":20}},"loc":{"start":{"line":74,"column":47},"end":{"line":105,"column":null}},"line":74},"5":{"name":"(anonymous_5)","decl":{"start":{"line":95,"column":17},"end":{"line":95,"column":23}},"loc":{"start":{"line":95,"column":23},"end":{"line":97,"column":9}},"line":95},"6":{"name":"(anonymous_6)","decl":{"start":{"line":114,"column":19},"end":{"line":114,"column":25}},"loc":{"start":{"line":114,"column":25},"end":{"line":114,"column":null}},"line":114},"7":{"name":"(anonymous_7)","decl":{"start":{"line":151,"column":22},"end":{"line":151,"column":23}},"loc":{"start":{"line":152,"column":16},"end":{"line":160,"column":null}},"line":152},"8":{"name":"(anonymous_8)","decl":{"start":{"line":158,"column":28},"end":{"line":158,"column":29}},"loc":{"start":{"line":158,"column":47},"end":{"line":158,"column":null}},"line":158},"9":{"name":"(anonymous_9)","decl":{"start":{"line":170,"column":22},"end":{"line":170,"column":23}},"loc":{"start":{"line":171,"column":16},"end":{"line":177,"column":null}},"line":171}},"branchMap":{"0":{"loc":{"start":{"line":32,"column":25},"end":{"line":34,"column":null}},"type":"binary-expr","locations":[{"start":{"line":32,"column":25},"end":{"line":32,"column":null}},{"start":{"line":33,"column":25},"end":{"line":33,"column":null}},{"start":{"line":34,"column":26},"end":{"line":34,"column":null}}],"line":32},"1":{"loc":{"start":{"line":34,"column":26},"end":{"line":34,"column":null}},"type":"cond-expr","locations":[{"start":{"line":34,"column":52},"end":{"line":34,"column":62}},{"start":{"line":34,"column":62},"end":{"line":34,"column":null}}],"line":34},"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":40,"column":4},"end":{"line":40,"column":null}},"type":"if","locations":[{"start":{"line":40,"column":4},"end":{"line":40,"column":null}},{"start":{},"end":{}}],"line":40},"4":{"loc":{"start":{"line":47,"column":13},"end":{"line":47,"column":null}},"type":"binary-expr","locations":[{"start":{"line":47,"column":13},"end":{"line":47,"column":37}},{"start":{"line":47,"column":37},"end":{"line":47,"column":null}}],"line":47},"5":{"loc":{"start":{"line":48,"column":19},"end":{"line":48,"column":null}},"type":"binary-expr","locations":[{"start":{"line":48,"column":19},"end":{"line":48,"column":49}},{"start":{"line":48,"column":49},"end":{"line":48,"column":null}}],"line":48},"6":{"loc":{"start":{"line":49,"column":20},"end":{"line":49,"column":null}},"type":"binary-expr","locations":[{"start":{"line":49,"column":20},"end":{"line":49,"column":51}},{"start":{"line":49,"column":51},"end":{"line":49,"column":null}}],"line":49},"7":{"loc":{"start":{"line":50,"column":14},"end":{"line":50,"column":null}},"type":"binary-expr","locations":[{"start":{"line":50,"column":14},"end":{"line":50,"column":39}},{"start":{"line":50,"column":39},"end":{"line":50,"column":null}}],"line":50},"8":{"loc":{"start":{"line":56,"column":28},"end":{"line":56,"column":null}},"type":"cond-expr","locations":[{"start":{"line":56,"column":47},"end":{"line":56,"column":73}},{"start":{"line":56,"column":73},"end":{"line":56,"column":null}}],"line":56},"9":{"loc":{"start":{"line":82,"column":6},"end":{"line":92,"column":null}},"type":"if","locations":[{"start":{"line":82,"column":6},"end":{"line":92,"column":null}},{"start":{"line":87,"column":13},"end":{"line":92,"column":null}}],"line":82},"10":{"loc":{"start":{"line":82,"column":10},"end":{"line":82,"column":40}},"type":"binary-expr","locations":[{"start":{"line":82,"column":10},"end":{"line":82,"column":24}},{"start":{"line":82,"column":24},"end":{"line":82,"column":40}}],"line":82},"11":{"loc":{"start":{"line":101,"column":6},"end":{"line":103,"column":null}},"type":"if","locations":[{"start":{"line":101,"column":6},"end":{"line":103,"column":null}},{"start":{},"end":{}}],"line":101},"12":{"loc":{"start":{"line":110,"column":7},"end":{"line":115,"column":null}},"type":"binary-expr","locations":[{"start":{"line":110,"column":7},"end":{"line":110,"column":null}},{"start":{"line":111,"column":8},"end":{"line":115,"column":null}}],"line":110},"13":{"loc":{"start":{"line":121,"column":15},"end":{"line":121,"column":63}},"type":"cond-expr","locations":[{"start":{"line":121,"column":28},"end":{"line":121,"column":47}},{"start":{"line":121,"column":47},"end":{"line":121,"column":63}}],"line":121},"14":{"loc":{"start":{"line":200,"column":13},"end":{"line":200,"column":null}},"type":"cond-expr","locations":[{"start":{"line":200,"column":26},"end":{"line":200,"column":48}},{"start":{"line":200,"column":48},"end":{"line":200,"column":null}}],"line":200}},"s":{"0":13,"1":13,"2":13,"3":13,"4":13,"5":13,"6":13,"7":13,"8":13,"9":7,"10":6,"11":6,"12":0,"13":6,"14":13,"15":13,"16":13,"17":13,"18":13,"19":13,"20":4,"21":4,"22":4,"23":0,"24":4,"25":13,"26":2,"27":2,"28":2,"29":1,"30":1,"31":1,"32":1,"33":1,"34":1,"35":2,"36":0,"37":0,"38":0,"39":0,"40":13,"41":0,"42":15,"43":2,"44":15},"f":{"0":13,"1":13,"2":4,"3":4,"4":2,"5":0,"6":0,"7":15,"8":2,"9":15},"b":{"0":[13,7,7],"1":[7,0],"2":[7,6],"3":[0,6],"4":[13,7],"5":[13,10],"6":[13,10],"7":[13,7],"8":[5,8],"9":[1,1],"10":[2,1],"11":[0,0],"12":[13,2],"13":[6,7],"14":[6,7]},"meta":{"lastBranch":15,"lastFunction":10,"lastStatement":45,"seen":{"f:20:24:20:40":0,"s:21:8:21:Infinity":0,"s:22:8:22:Infinity":1,"s:23:30:23:Infinity":2,"s:25:29:25:Infinity":3,"s:28:24:28:Infinity":4,"s:30:21:30:Infinity":5,"s:32:25:34:Infinity":6,"b:32:25:32:Infinity:33:25:33:Infinity:34:26:34:Infinity":0,"b:34:52:34:62:34:62:34:Infinity":1,"s:36:29:42:Infinity":7,"f:36:29:36:30":1,"b:37:4:37:Infinity:undefined:undefined:undefined:undefined":2,"s:37:4:37:Infinity":8,"s:37:15:37:Infinity":9,"s:38:14:38:Infinity":10,"b:40:4:40:Infinity:undefined:undefined:undefined:undefined":3,"s:40:4:40:Infinity":11,"s:40:28:40:Infinity":12,"s:41:4:41:Infinity":13,"s:44:49:53:Infinity":14,"b:47:13:47:37:47:37:47:Infinity":4,"b:48:19:48:49:48:49:48:Infinity":5,"b:49:20:49:51:49:51:49:Infinity":6,"b:50:14:50:39:50:39:50:Infinity":7,"s:55:27:55:Infinity":15,"s:56:28:56:Infinity":16,"b:56:47:56:73:56:73:56:Infinity":8,"s:57:20:57:Infinity":17,"s:58:38:58:Infinity":18,"s:61:2:71:Infinity":19,"f:61:12:61:18":2,"f:62:19:62:31":3,"s:63:6:68:Infinity":20,"s:64:28:64:Infinity":21,"s:65:8:65:Infinity":22,"s:67:8:67:Infinity":23,"s:70:4:70:Infinity":24,"s:74:19:105:Infinity":25,"f:74:19:74:20":4,"s:76:36:79:Infinity":26,"s:81:4:104:Infinity":27,"b:82:6:92:Infinity:87:13:92:Infinity":9,"s:82:6:92:Infinity":28,"b:82:10:82:24:82:24:82:40":10,"s:84:8:84:Infinity":29,"s:85:8:85:Infinity":30,"s:86:8:86:Infinity":31,"s:89:8:89:Infinity":32,"s:90:8:90:Infinity":33,"s:91:8:91:Infinity":34,"s:95:6:97:Infinity":35,"f:95:17:95:23":5,"s:96:10:96:Infinity":36,"s:100:6:100:Infinity":37,"b:101:6:103:Infinity:undefined:undefined:undefined:undefined":11,"s:101:6:103:Infinity":38,"s:102:8:102:Infinity":39,"s:107:2:205:Infinity":40,"b:110:7:110:Infinity:111:8:115:Infinity":12,"f:114:19:114:25":6,"s:114:25:114:Infinity":41,"b:121:28:121:47:121:47:121:63":13,"f:151:22:151:23":7,"s:152:16:160:Infinity":42,"f:158:28:158:29":8,"s:158:47:158:Infinity":43,"f:170:22:170:23":9,"s:171:16:177:Infinity":44,"b:200:26:200:48:200:48:200:Infinity":14}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/EditProfile/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/EditProfile/index.tsx","statementMap":{"0":{"start":{"line":14,"column":34},"end":{"line":14,"column":null}},"1":{"start":{"line":15,"column":8},"end":{"line":15,"column":null}},"2":{"start":{"line":16,"column":38},"end":{"line":16,"column":null}},"3":{"start":{"line":19,"column":27},"end":{"line":24,"column":null}},"4":{"start":{"line":20,"column":2},"end":{"line":20,"column":null}},"5":{"start":{"line":20,"column":19},"end":{"line":20,"column":null}},"6":{"start":{"line":21,"column":15},"end":{"line":21,"column":null}},"7":{"start":{"line":22,"column":2},"end":{"line":22,"column":null}},"8":{"start":{"line":22,"column":29},"end":{"line":22,"column":null}},"9":{"start":{"line":23,"column":2},"end":{"line":23,"column":null}},"10":{"start":{"line":26,"column":43},"end":{"line":26,"column":null}},"11":{"start":{"line":29,"column":2},"end":{"line":37,"column":null}},"12":{"start":{"line":30,"column":4},"end":{"line":36,"column":null}},"13":{"start":{"line":31,"column":6},"end":{"line":31,"column":null}},"14":{"start":{"line":32,"column":6},"end":{"line":32,"column":null}},"15":{"start":{"line":33,"column":6},"end":{"line":33,"column":null}},"16":{"start":{"line":34,"column":6},"end":{"line":34,"column":null}},"17":{"start":{"line":35,"column":6},"end":{"line":35,"column":null}},"18":{"start":{"line":39,"column":19},"end":{"line":59,"column":null}},"19":{"start":{"line":40,"column":4},"end":{"line":58,"column":null}},"20":{"start":{"line":41,"column":6},"end":{"line":41,"column":null}},"21":{"start":{"line":42,"column":6},"end":{"line":42,"column":null}},"22":{"start":{"line":44,"column":6},"end":{"line":44,"column":null}},"23":{"start":{"line":46,"column":6},"end":{"line":46,"column":null}},"24":{"start":{"line":49,"column":6},"end":{"line":51,"column":null}},"25":{"start":{"line":50,"column":10},"end":{"line":50,"column":null}},"26":{"start":{"line":54,"column":6},"end":{"line":54,"column":null}},"27":{"start":{"line":55,"column":6},"end":{"line":57,"column":null}},"28":{"start":{"line":56,"column":8},"end":{"line":56,"column":null}},"29":{"start":{"line":61,"column":2},"end":{"line":124,"column":null}},"30":{"start":{"line":68,"column":27},"end":{"line":68,"column":null}}},"fnMap":{"0":{"name":"EditProfile","decl":{"start":{"line":13,"column":24},"end":{"line":13,"column":38}},"loc":{"start":{"line":13,"column":38},"end":{"line":126,"column":null}},"line":13},"1":{"name":"(anonymous_1)","decl":{"start":{"line":19,"column":27},"end":{"line":19,"column":28}},"loc":{"start":{"line":19,"column":52},"end":{"line":24,"column":null}},"line":19},"2":{"name":"(anonymous_2)","decl":{"start":{"line":29,"column":12},"end":{"line":29,"column":18}},"loc":{"start":{"line":29,"column":18},"end":{"line":37,"column":5}},"line":29},"3":{"name":"(anonymous_3)","decl":{"start":{"line":39,"column":19},"end":{"line":39,"column":26}},"loc":{"start":{"line":39,"column":52},"end":{"line":59,"column":null}},"line":39},"4":{"name":"(anonymous_4)","decl":{"start":{"line":49,"column":17},"end":{"line":49,"column":23}},"loc":{"start":{"line":49,"column":23},"end":{"line":51,"column":9}},"line":49},"5":{"name":"(anonymous_5)","decl":{"start":{"line":68,"column":21},"end":{"line":68,"column":27}},"loc":{"start":{"line":68,"column":27},"end":{"line":68,"column":null}},"line":68}},"branchMap":{"0":{"loc":{"start":{"line":20,"column":2},"end":{"line":20,"column":null}},"type":"if","locations":[{"start":{"line":20,"column":2},"end":{"line":20,"column":null}},{"start":{},"end":{}}],"line":20},"1":{"loc":{"start":{"line":22,"column":2},"end":{"line":22,"column":null}},"type":"if","locations":[{"start":{"line":22,"column":2},"end":{"line":22,"column":null}},{"start":{},"end":{}}],"line":22},"2":{"loc":{"start":{"line":30,"column":4},"end":{"line":36,"column":null}},"type":"if","locations":[{"start":{"line":30,"column":4},"end":{"line":36,"column":null}},{"start":{},"end":{}}],"line":30},"3":{"loc":{"start":{"line":31,"column":31},"end":{"line":31,"column":61}},"type":"binary-expr","locations":[{"start":{"line":31,"column":31},"end":{"line":31,"column":59}},{"start":{"line":31,"column":59},"end":{"line":31,"column":61}}],"line":31},"4":{"loc":{"start":{"line":32,"column":27},"end":{"line":32,"column":53}},"type":"binary-expr","locations":[{"start":{"line":32,"column":27},"end":{"line":32,"column":51}},{"start":{"line":32,"column":51},"end":{"line":32,"column":53}}],"line":32},"5":{"loc":{"start":{"line":33,"column":24},"end":{"line":33,"column":47}},"type":"binary-expr","locations":[{"start":{"line":33,"column":24},"end":{"line":33,"column":45}},{"start":{"line":33,"column":45},"end":{"line":33,"column":47}}],"line":33},"6":{"loc":{"start":{"line":34,"column":28},"end":{"line":34,"column":59}},"type":"binary-expr","locations":[{"start":{"line":34,"column":28},"end":{"line":34,"column":57}},{"start":{"line":34,"column":57},"end":{"line":34,"column":59}}],"line":34},"7":{"loc":{"start":{"line":55,"column":6},"end":{"line":57,"column":null}},"type":"if","locations":[{"start":{"line":55,"column":6},"end":{"line":57,"column":null}},{"start":{},"end":{}}],"line":55},"8":{"loc":{"start":{"line":64,"column":7},"end":{"line":69,"column":null}},"type":"binary-expr","locations":[{"start":{"line":64,"column":7},"end":{"line":64,"column":null}},{"start":{"line":65,"column":8},"end":{"line":69,"column":null}}],"line":64}},"s":{"0":8,"1":8,"2":8,"3":8,"4":3,"5":0,"6":3,"7":3,"8":0,"9":3,"10":8,"11":8,"12":3,"13":3,"14":3,"15":3,"16":3,"17":3,"18":8,"19":2,"20":2,"21":2,"22":1,"23":1,"24":1,"25":0,"26":1,"27":1,"28":1,"29":8,"30":0},"f":{"0":8,"1":3,"2":3,"3":2,"4":0,"5":0},"b":{"0":[0,3],"1":[0,3],"2":[3,0],"3":[3,0],"4":[3,0],"5":[3,0],"6":[3,0],"7":[1,0],"8":[8,2]},"meta":{"lastBranch":9,"lastFunction":6,"lastStatement":31,"seen":{"f:13:24:13:38":0,"s:14:34:14:Infinity":0,"s:15:8:15:Infinity":1,"s:16:38:16:Infinity":2,"s:19:27:24:Infinity":3,"f:19:27:19:28":1,"b:20:2:20:Infinity:undefined:undefined:undefined:undefined":0,"s:20:2:20:Infinity":4,"s:20:19:20:Infinity":5,"s:21:15:21:Infinity":6,"b:22:2:22:Infinity:undefined:undefined:undefined:undefined":1,"s:22:2:22:Infinity":7,"s:22:29:22:Infinity":8,"s:23:2:23:Infinity":9,"s:26:43:26:Infinity":10,"s:29:2:37:Infinity":11,"f:29:12:29:18":2,"b:30:4:36:Infinity:undefined:undefined:undefined:undefined":2,"s:30:4:36:Infinity":12,"s:31:6:31:Infinity":13,"b:31:31:31:59:31:59:31:61":3,"s:32:6:32:Infinity":14,"b:32:27:32:51:32:51:32:53":4,"s:33:6:33:Infinity":15,"b:33:24:33:45:33:45:33:47":5,"s:34:6:34:Infinity":16,"b:34:28:34:57:34:57:34:59":6,"s:35:6:35:Infinity":17,"s:39:19:59:Infinity":18,"f:39:19:39:26":3,"s:40:4:58:Infinity":19,"s:41:6:41:Infinity":20,"s:42:6:42:Infinity":21,"s:44:6:44:Infinity":22,"s:46:6:46:Infinity":23,"s:49:6:51:Infinity":24,"f:49:17:49:23":4,"s:50:10:50:Infinity":25,"s:54:6:54:Infinity":26,"b:55:6:57:Infinity:undefined:undefined:undefined:undefined":7,"s:55:6:57:Infinity":27,"s:56:8:56:Infinity":28,"s:61:2:124:Infinity":29,"b:64:7:64:Infinity:65:8:69:Infinity":8,"f:68:21:68:27":5,"s:68:27:68:Infinity":30}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/Feed/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/Feed/index.tsx","statementMap":{"0":{"start":{"line":15,"column":50},"end":{"line":15,"column":null}},"1":{"start":{"line":16,"column":34},"end":{"line":16,"column":null}},"2":{"start":{"line":17,"column":10},"end":{"line":17,"column":null}},"3":{"start":{"line":18,"column":26},"end":{"line":18,"column":null}},"4":{"start":{"line":19,"column":40},"end":{"line":19,"column":null}},"5":{"start":{"line":21,"column":4},"end":{"line":37,"column":null}},"6":{"start":{"line":23,"column":12},"end":{"line":23,"column":null}},"7":{"start":{"line":24,"column":12},"end":{"line":34,"column":null}},"8":{"start":{"line":25,"column":33},"end":{"line":25,"column":null}},"9":{"start":{"line":26,"column":16},"end":{"line":26,"column":null}},"10":{"start":{"line":28,"column":16},"end":{"line":28,"column":null}},"11":{"start":{"line":29,"column":16},"end":{"line":31,"column":null}},"12":{"start":{"line":30,"column":20},"end":{"line":30,"column":null}},"13":{"start":{"line":33,"column":16},"end":{"line":33,"column":null}},"14":{"start":{"line":36,"column":8},"end":{"line":36,"column":null}},"15":{"start":{"line":39,"column":32},"end":{"line":42,"column":null}},"16":{"start":{"line":40,"column":8},"end":{"line":40,"column":null}},"17":{"start":{"line":41,"column":8},"end":{"line":41,"column":null}},"18":{"start":{"line":44,"column":34},"end":{"line":47,"column":null}},"19":{"start":{"line":45,"column":8},"end":{"line":45,"column":null}},"20":{"start":{"line":46,"column":8},"end":{"line":46,"column":null}},"21":{"start":{"line":49,"column":4},"end":{"line":116,"column":null}},"22":{"start":{"line":55,"column":35},"end":{"line":55,"column":null}},"23":{"start":{"line":59,"column":41},"end":{"line":59,"column":68}},"24":{"start":{"line":72,"column":32},"end":{"line":76,"column":null}},"25":{"start":{"line":104,"column":31},"end":{"line":104,"column":null}}},"fnMap":{"0":{"name":"Feed","decl":{"start":{"line":14,"column":24},"end":{"line":14,"column":31}},"loc":{"start":{"line":14,"column":31},"end":{"line":118,"column":null}},"line":14},"1":{"name":"(anonymous_1)","decl":{"start":{"line":21,"column":14},"end":{"line":21,"column":20}},"loc":{"start":{"line":21,"column":20},"end":{"line":37,"column":7}},"line":21},"2":{"name":"loadFeed","decl":{"start":{"line":22,"column":23},"end":{"line":22,"column":34}},"loc":{"start":{"line":22,"column":34},"end":{"line":35,"column":null}},"line":22},"3":{"name":"(anonymous_3)","decl":{"start":{"line":39,"column":32},"end":{"line":39,"column":38}},"loc":{"start":{"line":39,"column":38},"end":{"line":42,"column":null}},"line":39},"4":{"name":"(anonymous_4)","decl":{"start":{"line":44,"column":34},"end":{"line":44,"column":40}},"loc":{"start":{"line":44,"column":40},"end":{"line":47,"column":null}},"line":44},"5":{"name":"(anonymous_5)","decl":{"start":{"line":55,"column":29},"end":{"line":55,"column":35}},"loc":{"start":{"line":55,"column":35},"end":{"line":55,"column":null}},"line":55},"6":{"name":"(anonymous_6)","decl":{"start":{"line":59,"column":35},"end":{"line":59,"column":41}},"loc":{"start":{"line":59,"column":41},"end":{"line":59,"column":68}},"line":59},"7":{"name":"(anonymous_7)","decl":{"start":{"line":71,"column":38},"end":{"line":71,"column":39}},"loc":{"start":{"line":72,"column":32},"end":{"line":76,"column":null}},"line":72},"8":{"name":"(anonymous_8)","decl":{"start":{"line":104,"column":25},"end":{"line":104,"column":31}},"loc":{"start":{"line":104,"column":31},"end":{"line":104,"column":null}},"line":104}},"branchMap":{"0":{"loc":{"start":{"line":26,"column":25},"end":{"line":26,"column":39}},"type":"binary-expr","locations":[{"start":{"line":26,"column":25},"end":{"line":26,"column":37}},{"start":{"line":26,"column":37},"end":{"line":26,"column":39}}],"line":26},"1":{"loc":{"start":{"line":29,"column":16},"end":{"line":31,"column":null}},"type":"if","locations":[{"start":{"line":29,"column":16},"end":{"line":31,"column":null}},{"start":{},"end":{}}],"line":29},"2":{"loc":{"start":{"line":51,"column":13},"end":{"line":56,"column":null}},"type":"binary-expr","locations":[{"start":{"line":51,"column":13},"end":{"line":51,"column":null}},{"start":{"line":52,"column":16},"end":{"line":56,"column":null}}],"line":51},"3":{"loc":{"start":{"line":65,"column":25},"end":{"line":96,"column":null}},"type":"cond-expr","locations":[{"start":{"line":66,"column":28},"end":{"line":69,"column":null}},{"start":{"line":70,"column":28},"end":{"line":96,"column":null}}],"line":65},"4":{"loc":{"start":{"line":70,"column":28},"end":{"line":96,"column":null}},"type":"cond-expr","locations":[{"start":{"line":71,"column":28},"end":{"line":77,"column":null}},{"start":{"line":79,"column":28},"end":{"line":96,"column":null}}],"line":70},"5":{"loc":{"start":{"line":73,"column":42},"end":{"line":73,"column":null}},"type":"binary-expr","locations":[{"start":{"line":73,"column":42},"end":{"line":73,"column":82}},{"start":{"line":73,"column":82},"end":{"line":73,"column":108}},{"start":{"line":73,"column":108},"end":{"line":73,"column":null}}],"line":73}},"s":{"0":18,"1":18,"2":18,"3":18,"4":18,"5":18,"6":6,"7":6,"8":6,"9":5,"10":1,"11":1,"12":1,"13":6,"14":6,"15":18,"16":1,"17":1,"18":18,"19":1,"20":1,"21":18,"22":0,"23":2,"24":2,"25":0},"f":{"0":18,"1":6,"2":6,"3":1,"4":1,"5":0,"6":2,"7":2,"8":0},"b":{"0":[5,0],"1":[1,0],"2":[18,1],"3":[12,6],"4":[1,5],"5":[2,0,0]},"meta":{"lastBranch":6,"lastFunction":9,"lastStatement":26,"seen":{"f:14:24:14:31":0,"s:15:50:15:Infinity":0,"s:16:34:16:Infinity":1,"s:17:10:17:Infinity":2,"s:18:26:18:Infinity":3,"s:19:40:19:Infinity":4,"s:21:4:37:Infinity":5,"f:21:14:21:20":1,"f:22:23:22:34":2,"s:23:12:23:Infinity":6,"s:24:12:34:Infinity":7,"s:25:33:25:Infinity":8,"s:26:16:26:Infinity":9,"b:26:25:26:37:26:37:26:39":0,"s:28:16:28:Infinity":10,"b:29:16:31:Infinity:undefined:undefined:undefined:undefined":1,"s:29:16:31:Infinity":11,"s:30:20:30:Infinity":12,"s:33:16:33:Infinity":13,"s:36:8:36:Infinity":14,"s:39:32:42:Infinity":15,"f:39:32:39:38":3,"s:40:8:40:Infinity":16,"s:41:8:41:Infinity":17,"s:44:34:47:Infinity":18,"f:44:34:44:40":4,"s:45:8:45:Infinity":19,"s:46:8:46:Infinity":20,"s:49:4:116:Infinity":21,"b:51:13:51:Infinity:52:16:56:Infinity":2,"f:55:29:55:35":5,"s:55:35:55:Infinity":22,"f:59:35:59:41":6,"s:59:41:59:68":23,"b:66:28:69:Infinity:70:28:96:Infinity":3,"b:71:28:77:Infinity:79:28:96:Infinity":4,"f:71:38:71:39":7,"s:72:32:76:Infinity":24,"b:73:42:73:82:73:82:73:108:73:108:73:Infinity":5,"f:104:25:104:31":8,"s:104:31:104:Infinity":25}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/Feed/styles.ts": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/Feed/styles.ts","statementMap":{"0":{"start":{"line":4,"column":27},"end":{"line":17,"column":null}},"1":{"start":{"line":5,"column":51},"end":{"line":5,"column":74}},"2":{"start":{"line":5,"column":91},"end":{"line":5,"column":114}},"3":{"start":{"line":16,"column":66},"end":{"line":16,"column":85}},"4":{"start":{"line":17,"column":66},"end":{"line":17,"column":84}},"5":{"start":{"line":24,"column":30},"end":{"line":24,"column":null}},"6":{"start":{"line":51,"column":29},"end":{"line":87,"column":null}},"7":{"start":{"line":55,"column":27},"end":{"line":55,"column":49}},"8":{"start":{"line":62,"column":37},"end":{"line":62,"column":60}},"9":{"start":{"line":87,"column":41},"end":{"line":87,"column":64}},"10":{"start":{"line":97,"column":24},"end":{"line":97,"column":null}},"11":{"start":{"line":127,"column":32},"end":{"line":151,"column":null}},"12":{"start":{"line":130,"column":22},"end":{"line":130,"column":45}},"13":{"start":{"line":144,"column":26},"end":{"line":144,"column":46}},"14":{"start":{"line":151,"column":26},"end":{"line":151,"column":49}},"15":{"start":{"line":160,"column":26},"end":{"line":177,"column":null}},"16":{"start":{"line":163,"column":40},"end":{"line":163,"column":63}},"17":{"start":{"line":166,"column":26},"end":{"line":166,"column":43}},"18":{"start":{"line":170,"column":55},"end":{"line":170,"column":72}},"19":{"start":{"line":170,"column":86},"end":{"line":170,"column":106}},"20":{"start":{"line":177,"column":26},"end":{"line":177,"column":49}},"21":{"start":{"line":184,"column":32},"end":{"line":206,"column":null}},"22":{"start":{"line":195,"column":37},"end":{"line":195,"column":60}},"23":{"start":{"line":196,"column":37},"end":{"line":196,"column":56}},"24":{"start":{"line":206,"column":26},"end":{"line":206,"column":49}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":5,"column":42},"end":{"line":5,"column":51}},"loc":{"start":{"line":5,"column":51},"end":{"line":5,"column":74}},"line":5},"1":{"name":"(anonymous_1)","decl":{"start":{"line":5,"column":82},"end":{"line":5,"column":91}},"loc":{"start":{"line":5,"column":91},"end":{"line":5,"column":114}},"line":5},"2":{"name":"(anonymous_2)","decl":{"start":{"line":16,"column":57},"end":{"line":16,"column":66}},"loc":{"start":{"line":16,"column":66},"end":{"line":16,"column":85}},"line":16},"3":{"name":"(anonymous_3)","decl":{"start":{"line":17,"column":57},"end":{"line":17,"column":66}},"loc":{"start":{"line":17,"column":66},"end":{"line":17,"column":84}},"line":17},"4":{"name":"(anonymous_4)","decl":{"start":{"line":55,"column":18},"end":{"line":55,"column":27}},"loc":{"start":{"line":55,"column":27},"end":{"line":55,"column":49}},"line":55},"5":{"name":"(anonymous_5)","decl":{"start":{"line":62,"column":28},"end":{"line":62,"column":37}},"loc":{"start":{"line":62,"column":37},"end":{"line":62,"column":60}},"line":62},"6":{"name":"(anonymous_6)","decl":{"start":{"line":87,"column":32},"end":{"line":87,"column":41}},"loc":{"start":{"line":87,"column":41},"end":{"line":87,"column":64}},"line":87},"7":{"name":"(anonymous_7)","decl":{"start":{"line":130,"column":13},"end":{"line":130,"column":22}},"loc":{"start":{"line":130,"column":22},"end":{"line":130,"column":45}},"line":130},"8":{"name":"(anonymous_8)","decl":{"start":{"line":144,"column":17},"end":{"line":144,"column":26}},"loc":{"start":{"line":144,"column":26},"end":{"line":144,"column":46}},"line":144},"9":{"name":"(anonymous_9)","decl":{"start":{"line":151,"column":17},"end":{"line":151,"column":26}},"loc":{"start":{"line":151,"column":26},"end":{"line":151,"column":49}},"line":151},"10":{"name":"(anonymous_10)","decl":{"start":{"line":163,"column":31},"end":{"line":163,"column":40}},"loc":{"start":{"line":163,"column":40},"end":{"line":163,"column":63}},"line":163},"11":{"name":"(anonymous_11)","decl":{"start":{"line":166,"column":17},"end":{"line":166,"column":26}},"loc":{"start":{"line":166,"column":26},"end":{"line":166,"column":43}},"line":166},"12":{"name":"(anonymous_12)","decl":{"start":{"line":170,"column":46},"end":{"line":170,"column":55}},"loc":{"start":{"line":170,"column":55},"end":{"line":170,"column":72}},"line":170},"13":{"name":"(anonymous_13)","decl":{"start":{"line":170,"column":77},"end":{"line":170,"column":86}},"loc":{"start":{"line":170,"column":86},"end":{"line":170,"column":106}},"line":170},"14":{"name":"(anonymous_14)","decl":{"start":{"line":177,"column":17},"end":{"line":177,"column":26}},"loc":{"start":{"line":177,"column":26},"end":{"line":177,"column":49}},"line":177},"15":{"name":"(anonymous_15)","decl":{"start":{"line":195,"column":28},"end":{"line":195,"column":37}},"loc":{"start":{"line":195,"column":37},"end":{"line":195,"column":60}},"line":195},"16":{"name":"(anonymous_16)","decl":{"start":{"line":196,"column":28},"end":{"line":196,"column":37}},"loc":{"start":{"line":196,"column":37},"end":{"line":196,"column":56}},"line":196},"17":{"name":"(anonymous_17)","decl":{"start":{"line":206,"column":17},"end":{"line":206,"column":26}},"loc":{"start":{"line":206,"column":26},"end":{"line":206,"column":49}},"line":206}},"branchMap":{},"s":{"0":4,"1":44,"2":44,"3":44,"4":44,"5":4,"6":4,"7":16,"8":16,"9":16,"10":4,"11":4,"12":5,"13":5,"14":5,"15":4,"16":0,"17":0,"18":0,"19":0,"20":0,"21":4,"22":10,"23":10,"24":10},"f":{"0":44,"1":44,"2":44,"3":44,"4":16,"5":16,"6":16,"7":5,"8":5,"9":5,"10":0,"11":0,"12":0,"13":0,"14":0,"15":10,"16":10,"17":10},"b":{},"meta":{"lastBranch":0,"lastFunction":18,"lastStatement":25,"seen":{"s:4:27:17:Infinity":0,"f:5:42:5:51":0,"s:5:51:5:74":1,"f:5:82:5:91":1,"s:5:91:5:114":2,"f:16:57:16:66":2,"s:16:66:16:85":3,"f:17:57:17:66":3,"s:17:66:17:84":4,"s:24:30:24:Infinity":5,"s:51:29:87:Infinity":6,"f:55:18:55:27":4,"s:55:27:55:49":7,"f:62:28:62:37":5,"s:62:37:62:60":8,"f:87:32:87:41":6,"s:87:41:87:64":9,"s:97:24:97:Infinity":10,"s:127:32:151:Infinity":11,"f:130:13:130:22":7,"s:130:22:130:45":12,"f:144:17:144:26":8,"s:144:26:144:46":13,"f:151:17:151:26":9,"s:151:26:151:49":14,"s:160:26:177:Infinity":15,"f:163:31:163:40":10,"s:163:40:163:63":16,"f:166:17:166:26":11,"s:166:26:166:43":17,"f:170:46:170:55":12,"s:170:55:170:72":18,"f:170:77:170:86":13,"s:170:86:170:106":19,"f:177:17:177:26":14,"s:177:26:177:49":20,"s:184:32:206:Infinity":21,"f:195:28:195:37":15,"s:195:37:195:60":22,"f:196:28:196:37":16,"s:196:37:196:56":23,"f:206:17:206:26":17,"s:206:26:206:49":24}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/Home/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/Home/index.tsx","statementMap":{"0":{"start":{"line":5,"column":4},"end":{"line":12,"column":null}}},"fnMap":{"0":{"name":"Home","decl":{"start":{"line":4,"column":24},"end":{"line":4,"column":31}},"loc":{"start":{"line":4,"column":31},"end":{"line":14,"column":null}},"line":4}},"branchMap":{},"s":{"0":1},"f":{"0":1},"b":{},"meta":{"lastBranch":0,"lastFunction":1,"lastStatement":1,"seen":{"f:4:24:4:31":0,"s:5:4:12:Infinity":0}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/Login/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/Login/index.tsx","statementMap":{"0":{"start":{"line":19,"column":38},"end":{"line":19,"column":null}},"1":{"start":{"line":20,"column":16},"end":{"line":20,"column":null}},"2":{"start":{"line":22,"column":60},"end":{"line":22,"column":null}},"3":{"start":{"line":23,"column":8},"end":{"line":23,"column":null}},"4":{"start":{"line":26,"column":6},"end":{"line":26,"column":null}},"5":{"start":{"line":27,"column":6},"end":{"line":46,"column":null}},"6":{"start":{"line":28,"column":8},"end":{"line":28,"column":null}},"7":{"start":{"line":30,"column":8},"end":{"line":30,"column":null}},"8":{"start":{"line":33,"column":8},"end":{"line":33,"column":null}},"9":{"start":{"line":35,"column":8},"end":{"line":37,"column":null}},"10":{"start":{"line":36,"column":8},"end":{"line":36,"column":null}},"11":{"start":{"line":40,"column":8},"end":{"line":40,"column":null}},"12":{"start":{"line":43,"column":8},"end":{"line":45,"column":null}},"13":{"start":{"line":44,"column":8},"end":{"line":44,"column":null}},"14":{"start":{"line":49,"column":2},"end":{"line":82,"column":null}},"15":{"start":{"line":55,"column":25},"end":{"line":55,"column":null}}},"fnMap":{"0":{"name":"LoginPage","decl":{"start":{"line":18,"column":24},"end":{"line":18,"column":36}},"loc":{"start":{"line":18,"column":36},"end":{"line":84,"column":null}},"line":18},"1":{"name":"onSubmit","decl":{"start":{"line":25,"column":19},"end":{"line":25,"column":28}},"loc":{"start":{"line":25,"column":46},"end":{"line":47,"column":null}},"line":25},"2":{"name":"(anonymous_2)","decl":{"start":{"line":35,"column":19},"end":{"line":35,"column":25}},"loc":{"start":{"line":35,"column":25},"end":{"line":37,"column":11}},"line":35},"3":{"name":"(anonymous_3)","decl":{"start":{"line":55,"column":19},"end":{"line":55,"column":25}},"loc":{"start":{"line":55,"column":25},"end":{"line":55,"column":null}},"line":55}},"branchMap":{"0":{"loc":{"start":{"line":43,"column":8},"end":{"line":45,"column":null}},"type":"if","locations":[{"start":{"line":43,"column":8},"end":{"line":45,"column":null}},{"start":{},"end":{}}],"line":43},"1":{"loc":{"start":{"line":51,"column":7},"end":{"line":56,"column":null}},"type":"binary-expr","locations":[{"start":{"line":51,"column":7},"end":{"line":51,"column":null}},{"start":{"line":52,"column":8},"end":{"line":56,"column":null}}],"line":51}},"s":{"0":10,"1":10,"2":10,"3":10,"4":2,"5":2,"6":2,"7":1,"8":1,"9":1,"10":0,"11":1,"12":1,"13":1,"14":10,"15":0},"f":{"0":10,"1":2,"2":0,"3":0},"b":{"0":[1,0],"1":[10,2]},"meta":{"lastBranch":2,"lastFunction":4,"lastStatement":16,"seen":{"f:18:24:18:36":0,"s:19:38:19:Infinity":0,"s:20:16:20:Infinity":1,"s:22:60:22:Infinity":2,"s:23:8:23:Infinity":3,"f:25:19:25:28":1,"s:26:6:26:Infinity":4,"s:27:6:46:Infinity":5,"s:28:8:28:Infinity":6,"s:30:8:30:Infinity":7,"s:33:8:33:Infinity":8,"s:35:8:37:Infinity":9,"f:35:19:35:25":2,"s:36:8:36:Infinity":10,"s:40:8:40:Infinity":11,"b:43:8:45:Infinity:undefined:undefined:undefined:undefined":0,"s:43:8:45:Infinity":12,"s:44:8:44:Infinity":13,"s:49:2:82:Infinity":14,"b:51:7:51:Infinity:52:8:56:Infinity":1,"f:55:19:55:25":3,"s:55:25:55:Infinity":15}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/Profile/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/Profile/index.tsx","statementMap":{"0":{"start":{"line":18,"column":18},"end":{"line":22,"column":null}},"1":{"start":{"line":19,"column":2},"end":{"line":22,"column":null}},"2":{"start":{"line":24,"column":21},"end":{"line":27,"column":null}},"3":{"start":{"line":25,"column":2},"end":{"line":27,"column":null}},"4":{"start":{"line":29,"column":21},"end":{"line":32,"column":null}},"5":{"start":{"line":30,"column":2},"end":{"line":32,"column":null}},"6":{"start":{"line":39,"column":30},"end":{"line":39,"column":null}},"7":{"start":{"line":40,"column":22},"end":{"line":40,"column":null}},"8":{"start":{"line":41,"column":34},"end":{"line":41,"column":null}},"9":{"start":{"line":42,"column":8},"end":{"line":42,"column":null}},"10":{"start":{"line":44,"column":8},"end":{"line":44,"column":null}},"11":{"start":{"line":47,"column":32},"end":{"line":47,"column":null}},"12":{"start":{"line":48,"column":38},"end":{"line":48,"column":null}},"13":{"start":{"line":50,"column":34},"end":{"line":50,"column":null}},"14":{"start":{"line":51,"column":62},"end":{"line":51,"column":null}},"15":{"start":{"line":52,"column":38},"end":{"line":52,"column":null}},"16":{"start":{"line":54,"column":2},"end":{"line":75,"column":null}},"17":{"start":{"line":56,"column":4},"end":{"line":56,"column":null}},"18":{"start":{"line":57,"column":29},"end":{"line":72,"column":null}},"19":{"start":{"line":58,"column":6},"end":{"line":70,"column":null}},"20":{"start":{"line":60,"column":8},"end":{"line":60,"column":null}},"21":{"start":{"line":61,"column":29},"end":{"line":61,"column":null}},"22":{"start":{"line":63,"column":48},"end":{"line":63,"column":null}},"23":{"start":{"line":65,"column":8},"end":{"line":65,"column":null}},"24":{"start":{"line":66,"column":8},"end":{"line":66,"column":null}},"25":{"start":{"line":69,"column":8},"end":{"line":69,"column":null}},"26":{"start":{"line":73,"column":4},"end":{"line":74,"column":null}},"27":{"start":{"line":74,"column":6},"end":{"line":74,"column":null}},"28":{"start":{"line":78,"column":2},"end":{"line":90,"column":null}},"29":{"start":{"line":80,"column":6},"end":{"line":82,"column":null}},"30":{"start":{"line":81,"column":8},"end":{"line":81,"column":null}},"31":{"start":{"line":84,"column":4},"end":{"line":86,"column":null}},"32":{"start":{"line":85,"column":6},"end":{"line":85,"column":null}},"33":{"start":{"line":87,"column":4},"end":{"line":89,"column":null}},"34":{"start":{"line":88,"column":6},"end":{"line":88,"column":null}},"35":{"start":{"line":92,"column":23},"end":{"line":95,"column":null}},"36":{"start":{"line":93,"column":4},"end":{"line":93,"column":null}},"37":{"start":{"line":94,"column":4},"end":{"line":94,"column":null}},"38":{"start":{"line":97,"column":30},"end":{"line":104,"column":null}},"39":{"start":{"line":98,"column":6},"end":{"line":98,"column":null}},"40":{"start":{"line":101,"column":6},"end":{"line":103,"column":null}},"41":{"start":{"line":102,"column":10},"end":{"line":102,"column":null}},"42":{"start":{"line":102,"column":41},"end":{"line":102,"column":72}},"43":{"start":{"line":106,"column":28},"end":{"line":109,"column":null}},"44":{"start":{"line":107,"column":6},"end":{"line":107,"column":null}},"45":{"start":{"line":108,"column":6},"end":{"line":108,"column":null}},"46":{"start":{"line":111,"column":30},"end":{"line":141,"column":null}},"47":{"start":{"line":113,"column":4},"end":{"line":113,"column":null}},"48":{"start":{"line":113,"column":20},"end":{"line":113,"column":null}},"49":{"start":{"line":114,"column":4},"end":{"line":114,"column":null}},"50":{"start":{"line":116,"column":6},"end":{"line":140,"column":null}},"51":{"start":{"line":117,"column":10},"end":{"line":117,"column":null}},"52":{"start":{"line":118,"column":10},"end":{"line":118,"column":null}},"53":{"start":{"line":120,"column":10},"end":{"line":120,"column":null}},"54":{"start":{"line":122,"column":10},"end":{"line":125,"column":null}},"55":{"start":{"line":123,"column":14},"end":{"line":123,"column":null}},"56":{"start":{"line":124,"column":14},"end":{"line":124,"column":null}},"57":{"start":{"line":128,"column":10},"end":{"line":135,"column":null}},"58":{"start":{"line":129,"column":14},"end":{"line":133,"column":null}},"59":{"start":{"line":130,"column":18},"end":{"line":130,"column":null}},"60":{"start":{"line":131,"column":18},"end":{"line":131,"column":null}},"61":{"start":{"line":131,"column":37},"end":{"line":131,"column":47}},"62":{"start":{"line":131,"column":47},"end":{"line":131,"column":67}},"63":{"start":{"line":132,"column":18},"end":{"line":132,"column":null}},"64":{"start":{"line":134,"column":14},"end":{"line":134,"column":null}},"65":{"start":{"line":136,"column":10},"end":{"line":136,"column":null}},"66":{"start":{"line":138,"column":10},"end":{"line":138,"column":null}},"67":{"start":{"line":139,"column":10},"end":{"line":139,"column":null}},"68":{"start":{"line":144,"column":21},"end":{"line":181,"column":null}},"69":{"start":{"line":145,"column":4},"end":{"line":155,"column":null}},"70":{"start":{"line":146,"column":6},"end":{"line":148,"column":null}},"71":{"start":{"line":147,"column":8},"end":{"line":147,"column":null}},"72":{"start":{"line":150,"column":5},"end":{"line":154,"column":null}},"73":{"start":{"line":151,"column":8},"end":{"line":153,"column":null}},"74":{"start":{"line":157,"column":4},"end":{"line":178,"column":null}},"75":{"start":{"line":159,"column":6},"end":{"line":177,"column":null}},"76":{"start":{"line":160,"column":8},"end":{"line":176,"column":null}},"77":{"start":{"line":174,"column":28},"end":{"line":174,"column":null}},"78":{"start":{"line":180,"column":4},"end":{"line":180,"column":null}},"79":{"start":{"line":183,"column":2},"end":{"line":281,"column":null}},"80":{"start":{"line":191,"column":27},"end":{"line":191,"column":null}},"81":{"start":{"line":203,"column":39},"end":{"line":203,"column":null}},"82":{"start":{"line":210,"column":39},"end":{"line":210,"column":null}},"83":{"start":{"line":216,"column":39},"end":{"line":216,"column":null}},"84":{"start":{"line":216,"column":61},"end":{"line":216,"column":66}},"85":{"start":{"line":228,"column":24},"end":{"line":228,"column":null}},"86":{"start":{"line":229,"column":24},"end":{"line":229,"column":null}},"87":{"start":{"line":256,"column":23},"end":{"line":256,"column":null}},"88":{"start":{"line":266,"column":33},"end":{"line":266,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":18,"column":18},"end":{"line":18,"column":null}},"loc":{"start":{"line":19,"column":2},"end":{"line":22,"column":null}},"line":19},"1":{"name":"(anonymous_1)","decl":{"start":{"line":24,"column":21},"end":{"line":24,"column":null}},"loc":{"start":{"line":25,"column":2},"end":{"line":27,"column":null}},"line":25},"2":{"name":"(anonymous_2)","decl":{"start":{"line":29,"column":21},"end":{"line":29,"column":null}},"loc":{"start":{"line":30,"column":2},"end":{"line":32,"column":null}},"line":30},"3":{"name":"Profile","decl":{"start":{"line":38,"column":24},"end":{"line":38,"column":34}},"loc":{"start":{"line":38,"column":34},"end":{"line":283,"column":null}},"line":38},"4":{"name":"(anonymous_4)","decl":{"start":{"line":54,"column":12},"end":{"line":54,"column":18}},"loc":{"start":{"line":54,"column":18},"end":{"line":75,"column":5}},"line":54},"5":{"name":"(anonymous_5)","decl":{"start":{"line":57,"column":29},"end":{"line":57,"column":41}},"loc":{"start":{"line":57,"column":41},"end":{"line":72,"column":null}},"line":57},"6":{"name":"(anonymous_6)","decl":{"start":{"line":78,"column":12},"end":{"line":78,"column":18}},"loc":{"start":{"line":78,"column":18},"end":{"line":90,"column":5}},"line":78},"7":{"name":"handleClickOutside","decl":{"start":{"line":79,"column":13},"end":{"line":79,"column":32}},"loc":{"start":{"line":79,"column":51},"end":{"line":83,"column":null}},"line":79},"8":{"name":"(anonymous_8)","decl":{"start":{"line":87,"column":11},"end":{"line":87,"column":17}},"loc":{"start":{"line":87,"column":17},"end":{"line":89,"column":null}},"line":87},"9":{"name":"(anonymous_9)","decl":{"start":{"line":92,"column":23},"end":{"line":92,"column":29}},"loc":{"start":{"line":92,"column":29},"end":{"line":95,"column":null}},"line":92},"10":{"name":"(anonymous_10)","decl":{"start":{"line":97,"column":30},"end":{"line":97,"column":37}},"loc":{"start":{"line":97,"column":59},"end":{"line":104,"column":null}},"line":97},"11":{"name":"(anonymous_11)","decl":{"start":{"line":101,"column":22},"end":{"line":101,"column":23}},"loc":{"start":{"line":102,"column":10},"end":{"line":102,"column":null}},"line":102},"12":{"name":"(anonymous_12)","decl":{"start":{"line":102,"column":30},"end":{"line":102,"column":41}},"loc":{"start":{"line":102,"column":41},"end":{"line":102,"column":72}},"line":102},"13":{"name":"(anonymous_13)","decl":{"start":{"line":106,"column":28},"end":{"line":106,"column":34}},"loc":{"start":{"line":106,"column":34},"end":{"line":109,"column":null}},"line":106},"14":{"name":"(anonymous_14)","decl":{"start":{"line":111,"column":30},"end":{"line":111,"column":42}},"loc":{"start":{"line":111,"column":42},"end":{"line":141,"column":null}},"line":111},"15":{"name":"(anonymous_15)","decl":{"start":{"line":122,"column":21},"end":{"line":122,"column":27}},"loc":{"start":{"line":122,"column":27},"end":{"line":125,"column":13}},"line":122},"16":{"name":"(anonymous_16)","decl":{"start":{"line":131,"column":29},"end":{"line":131,"column":35}},"loc":{"start":{"line":131,"column":35},"end":{"line":131,"column":70}},"line":131},"17":{"name":"(anonymous_17)","decl":{"start":{"line":144,"column":21},"end":{"line":144,"column":27}},"loc":{"start":{"line":144,"column":27},"end":{"line":181,"column":null}},"line":144},"18":{"name":"(anonymous_18)","decl":{"start":{"line":150,"column":26},"end":{"line":150,"column":27}},"loc":{"start":{"line":151,"column":8},"end":{"line":153,"column":null}},"line":151},"19":{"name":"(anonymous_19)","decl":{"start":{"line":159,"column":30},"end":{"line":159,"column":null}},"loc":{"start":{"line":160,"column":8},"end":{"line":176,"column":null}},"line":160},"20":{"name":"(anonymous_20)","decl":{"start":{"line":174,"column":22},"end":{"line":174,"column":28}},"loc":{"start":{"line":174,"column":28},"end":{"line":174,"column":null}},"line":174},"21":{"name":"(anonymous_21)","decl":{"start":{"line":191,"column":21},"end":{"line":191,"column":27}},"loc":{"start":{"line":191,"column":27},"end":{"line":191,"column":null}},"line":191},"22":{"name":"(anonymous_22)","decl":{"start":{"line":203,"column":33},"end":{"line":203,"column":39}},"loc":{"start":{"line":203,"column":39},"end":{"line":203,"column":null}},"line":203},"23":{"name":"(anonymous_23)","decl":{"start":{"line":210,"column":33},"end":{"line":210,"column":39}},"loc":{"start":{"line":210,"column":39},"end":{"line":210,"column":null}},"line":210},"24":{"name":"(anonymous_24)","decl":{"start":{"line":216,"column":33},"end":{"line":216,"column":39}},"loc":{"start":{"line":216,"column":39},"end":{"line":216,"column":null}},"line":216},"25":{"name":"(anonymous_25)","decl":{"start":{"line":216,"column":53},"end":{"line":216,"column":61}},"loc":{"start":{"line":216,"column":61},"end":{"line":216,"column":66}},"line":216},"26":{"name":"(anonymous_26)","decl":{"start":{"line":227,"column":47},"end":{"line":227,"column":53}},"loc":{"start":{"line":227,"column":53},"end":{"line":230,"column":23}},"line":227},"27":{"name":"(anonymous_27)","decl":{"start":{"line":256,"column":17},"end":{"line":256,"column":23}},"loc":{"start":{"line":256,"column":23},"end":{"line":256,"column":null}},"line":256},"28":{"name":"(anonymous_28)","decl":{"start":{"line":266,"column":27},"end":{"line":266,"column":33}},"loc":{"start":{"line":266,"column":33},"end":{"line":266,"column":null}},"line":266}},"branchMap":{"0":{"loc":{"start":{"line":73,"column":4},"end":{"line":74,"column":null}},"type":"if","locations":[{"start":{"line":73,"column":4},"end":{"line":74,"column":null}},{"start":{},"end":{}}],"line":73},"1":{"loc":{"start":{"line":80,"column":6},"end":{"line":82,"column":null}},"type":"if","locations":[{"start":{"line":80,"column":6},"end":{"line":82,"column":null}},{"start":{},"end":{}}],"line":80},"2":{"loc":{"start":{"line":80,"column":10},"end":{"line":80,"column":78}},"type":"binary-expr","locations":[{"start":{"line":80,"column":10},"end":{"line":80,"column":29}},{"start":{"line":80,"column":29},"end":{"line":80,"column":78}}],"line":80},"3":{"loc":{"start":{"line":84,"column":4},"end":{"line":86,"column":null}},"type":"if","locations":[{"start":{"line":84,"column":4},"end":{"line":86,"column":null}},{"start":{},"end":{}}],"line":84},"4":{"loc":{"start":{"line":113,"column":4},"end":{"line":113,"column":null}},"type":"if","locations":[{"start":{"line":113,"column":4},"end":{"line":113,"column":null}},{"start":{},"end":{}}],"line":113},"5":{"loc":{"start":{"line":128,"column":10},"end":{"line":135,"column":null}},"type":"if","locations":[{"start":{"line":128,"column":10},"end":{"line":135,"column":null}},{"start":{},"end":{}}],"line":128},"6":{"loc":{"start":{"line":129,"column":14},"end":{"line":133,"column":null}},"type":"if","locations":[{"start":{"line":129,"column":14},"end":{"line":133,"column":null}},{"start":{},"end":{}}],"line":129},"7":{"loc":{"start":{"line":129,"column":18},"end":{"line":129,"column":99}},"type":"binary-expr","locations":[{"start":{"line":129,"column":18},"end":{"line":129,"column":62}},{"start":{"line":129,"column":62},"end":{"line":129,"column":99}}],"line":129},"8":{"loc":{"start":{"line":145,"column":4},"end":{"line":155,"column":null}},"type":"if","locations":[{"start":{"line":145,"column":4},"end":{"line":155,"column":null}},{"start":{},"end":{}}],"line":145},"9":{"loc":{"start":{"line":146,"column":6},"end":{"line":148,"column":null}},"type":"if","locations":[{"start":{"line":146,"column":6},"end":{"line":148,"column":null}},{"start":{},"end":{}}],"line":146},"10":{"loc":{"start":{"line":157,"column":4},"end":{"line":178,"column":null}},"type":"if","locations":[{"start":{"line":157,"column":4},"end":{"line":178,"column":null}},{"start":{},"end":{}}],"line":157},"11":{"loc":{"start":{"line":164,"column":37},"end":{"line":164,"column":70}},"type":"binary-expr","locations":[{"start":{"line":164,"column":37},"end":{"line":164,"column":61}},{"start":{"line":164,"column":61},"end":{"line":164,"column":70}}],"line":164},"12":{"loc":{"start":{"line":170,"column":31},"end":{"line":170,"column":63}},"type":"binary-expr","locations":[{"start":{"line":170,"column":31},"end":{"line":170,"column":56}},{"start":{"line":170,"column":56},"end":{"line":170,"column":63}}],"line":170},"13":{"loc":{"start":{"line":160,"column":30},"end":{"line":160,"column":null}},"type":"binary-expr","locations":[{"start":{"line":160,"column":30},"end":{"line":160,"column":51}},{"start":{"line":160,"column":51},"end":{"line":160,"column":null}}],"line":160},"14":{"loc":{"start":{"line":187,"column":7},"end":{"line":192,"column":null}},"type":"binary-expr","locations":[{"start":{"line":187,"column":7},"end":{"line":187,"column":null}},{"start":{"line":188,"column":8},"end":{"line":192,"column":null}}],"line":187},"15":{"loc":{"start":{"line":222,"column":17},"end":{"line":233,"column":null}},"type":"binary-expr","locations":[{"start":{"line":222,"column":17},"end":{"line":222,"column":null}},{"start":{"line":223,"column":16},"end":{"line":233,"column":null}}],"line":222},"16":{"loc":{"start":{"line":245,"column":25},"end":{"line":245,"column":66}},"type":"binary-expr","locations":[{"start":{"line":245,"column":25},"end":{"line":245,"column":50}},{"start":{"line":245,"column":50},"end":{"line":245,"column":66}}],"line":245},"17":{"loc":{"start":{"line":256,"column":23},"end":{"line":256,"column":null}},"type":"binary-expr","locations":[{"start":{"line":256,"column":23},"end":{"line":256,"column":38}},{"start":{"line":256,"column":38},"end":{"line":256,"column":null}}],"line":256},"18":{"loc":{"start":{"line":275,"column":21},"end":{"line":275,"column":null}},"type":"cond-expr","locations":[{"start":{"line":275,"column":34},"end":{"line":275,"column":51}},{"start":{"line":275,"column":51},"end":{"line":275,"column":null}}],"line":275}},"s":{"0":1,"1":40,"2":1,"3":40,"4":1,"5":40,"6":42,"7":42,"8":42,"9":42,"10":42,"11":42,"12":42,"13":42,"14":42,"15":42,"16":42,"17":40,"18":40,"19":40,"20":40,"21":40,"22":39,"23":39,"24":39,"25":1,"26":40,"27":40,"28":42,"29":1,"30":1,"31":25,"32":7,"33":25,"34":25,"35":42,"36":1,"37":1,"38":42,"39":1,"40":1,"41":1,"42":1,"43":42,"44":1,"45":1,"46":42,"47":3,"48":0,"49":3,"50":3,"51":3,"52":1,"53":1,"54":1,"55":0,"56":0,"57":2,"58":2,"59":1,"60":1,"61":0,"62":0,"63":1,"64":1,"65":1,"66":3,"67":3,"68":42,"69":42,"70":37,"71":35,"72":2,"73":2,"74":5,"75":5,"76":2,"77":1,"78":0,"79":42,"80":0,"81":0,"82":2,"83":7,"84":7,"85":4,"86":4,"87":0,"88":1},"f":{"0":40,"1":40,"2":40,"3":42,"4":40,"5":40,"6":25,"7":1,"8":25,"9":1,"10":1,"11":1,"12":1,"13":1,"14":3,"15":0,"16":0,"17":42,"18":2,"19":2,"20":1,"21":0,"22":0,"23":2,"24":7,"25":7,"26":4,"27":0,"28":1},"b":{"0":[40,0],"1":[1,0],"2":[1,1],"3":[7,18],"4":[0,3],"5":[2,0],"6":[1,1],"7":[2,1],"8":[37,5],"9":[35,2],"10":[5,0],"11":[2,0],"12":[2,0],"13":[2,0],"14":[42,4],"15":[42,7],"16":[42,0],"17":[0,0],"18":[3,39]},"meta":{"lastBranch":19,"lastFunction":29,"lastStatement":89,"seen":{"s:18:18:22:Infinity":0,"f:18:18:18:Infinity":0,"s:19:2:22:Infinity":1,"s:24:21:27:Infinity":2,"f:24:21:24:Infinity":1,"s:25:2:27:Infinity":3,"s:29:21:32:Infinity":4,"f:29:21:29:Infinity":2,"s:30:2:32:Infinity":5,"f:38:24:38:34":3,"s:39:30:39:Infinity":6,"s:40:22:40:Infinity":7,"s:41:34:41:Infinity":8,"s:42:8:42:Infinity":9,"s:44:8:44:Infinity":10,"s:47:32:47:Infinity":11,"s:48:38:48:Infinity":12,"s:50:34:50:Infinity":13,"s:51:62:51:Infinity":14,"s:52:38:52:Infinity":15,"s:54:2:75:Infinity":16,"f:54:12:54:18":4,"s:56:4:56:Infinity":17,"s:57:29:72:Infinity":18,"f:57:29:57:41":5,"s:58:6:70:Infinity":19,"s:60:8:60:Infinity":20,"s:61:29:61:Infinity":21,"s:63:48:63:Infinity":22,"s:65:8:65:Infinity":23,"s:66:8:66:Infinity":24,"s:69:8:69:Infinity":25,"b:73:4:74:Infinity:undefined:undefined:undefined:undefined":0,"s:73:4:74:Infinity":26,"s:74:6:74:Infinity":27,"s:78:2:90:Infinity":28,"f:78:12:78:18":6,"f:79:13:79:32":7,"b:80:6:82:Infinity:undefined:undefined:undefined:undefined":1,"s:80:6:82:Infinity":29,"b:80:10:80:29:80:29:80:78":2,"s:81:8:81:Infinity":30,"b:84:4:86:Infinity:undefined:undefined:undefined:undefined":3,"s:84:4:86:Infinity":31,"s:85:6:85:Infinity":32,"s:87:4:89:Infinity":33,"f:87:11:87:17":8,"s:88:6:88:Infinity":34,"s:92:23:95:Infinity":35,"f:92:23:92:29":9,"s:93:4:93:Infinity":36,"s:94:4:94:Infinity":37,"s:97:30:104:Infinity":38,"f:97:30:97:37":10,"s:98:6:98:Infinity":39,"s:101:6:103:Infinity":40,"f:101:22:101:23":11,"s:102:10:102:Infinity":41,"f:102:30:102:41":12,"s:102:41:102:72":42,"s:106:28:109:Infinity":43,"f:106:28:106:34":13,"s:107:6:107:Infinity":44,"s:108:6:108:Infinity":45,"s:111:30:141:Infinity":46,"f:111:30:111:42":14,"b:113:4:113:Infinity:undefined:undefined:undefined:undefined":4,"s:113:4:113:Infinity":47,"s:113:20:113:Infinity":48,"s:114:4:114:Infinity":49,"s:116:6:140:Infinity":50,"s:117:10:117:Infinity":51,"s:118:10:118:Infinity":52,"s:120:10:120:Infinity":53,"s:122:10:125:Infinity":54,"f:122:21:122:27":15,"s:123:14:123:Infinity":55,"s:124:14:124:Infinity":56,"b:128:10:135:Infinity:undefined:undefined:undefined:undefined":5,"s:128:10:135:Infinity":57,"b:129:14:133:Infinity:undefined:undefined:undefined:undefined":6,"s:129:14:133:Infinity":58,"b:129:18:129:62:129:62:129:99":7,"s:130:18:130:Infinity":59,"s:131:18:131:Infinity":60,"f:131:29:131:35":16,"s:131:37:131:47":61,"s:131:47:131:67":62,"s:132:18:132:Infinity":63,"s:134:14:134:Infinity":64,"s:136:10:136:Infinity":65,"s:138:10:138:Infinity":66,"s:139:10:139:Infinity":67,"s:144:21:181:Infinity":68,"f:144:21:144:27":17,"b:145:4:155:Infinity:undefined:undefined:undefined:undefined":8,"s:145:4:155:Infinity":69,"b:146:6:148:Infinity:undefined:undefined:undefined:undefined":9,"s:146:6:148:Infinity":70,"s:147:8:147:Infinity":71,"s:150:5:154:Infinity":72,"f:150:26:150:27":18,"s:151:8:153:Infinity":73,"b:157:4:178:Infinity:undefined:undefined:undefined:undefined":10,"s:157:4:178:Infinity":74,"s:159:6:177:Infinity":75,"f:159:30:159:Infinity":19,"s:160:8:176:Infinity":76,"b:164:37:164:61:164:61:164:70":11,"b:170:31:170:56:170:56:170:63":12,"f:174:22:174:28":20,"s:174:28:174:Infinity":77,"b:160:30:160:51:160:51:160:Infinity":13,"s:180:4:180:Infinity":78,"s:183:2:281:Infinity":79,"b:187:7:187:Infinity:188:8:192:Infinity":14,"f:191:21:191:27":21,"s:191:27:191:Infinity":80,"f:203:33:203:39":22,"s:203:39:203:Infinity":81,"f:210:33:210:39":23,"s:210:39:210:Infinity":82,"f:216:33:216:39":24,"s:216:39:216:Infinity":83,"f:216:53:216:61":25,"s:216:61:216:66":84,"b:222:17:222:Infinity:223:16:233:Infinity":15,"f:227:47:227:53":26,"s:228:24:228:Infinity":85,"s:229:24:229:Infinity":86,"b:245:25:245:50:245:50:245:66":16,"f:256:17:256:23":27,"s:256:23:256:Infinity":87,"b:256:23:256:38:256:38:256:Infinity":17,"f:266:27:266:33":28,"s:266:33:266:Infinity":88,"b:275:34:275:51:275:51:275:Infinity":18}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/Profile/styles.ts": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/Profile/styles.ts","statementMap":{"0":{"start":{"line":4,"column":27},"end":{"line":5,"column":null}},"1":{"start":{"line":5,"column":49},"end":{"line":5,"column":72}},"2":{"start":{"line":5,"column":89},"end":{"line":5,"column":139}},"3":{"start":{"line":10,"column":30},"end":{"line":10,"column":null}},"4":{"start":{"line":17,"column":29},"end":{"line":22,"column":null}},"5":{"start":{"line":22,"column":33},"end":{"line":22,"column":55}},"6":{"start":{"line":40,"column":24},"end":{"line":40,"column":null}},"7":{"start":{"line":61,"column":29},"end":{"line":62,"column":null}},"8":{"start":{"line":62,"column":49},"end":{"line":62,"column":67}},"9":{"start":{"line":62,"column":84},"end":{"line":62,"column":133}},"10":{"start":{"line":91,"column":27},"end":{"line":91,"column":null}},"11":{"start":{"line":123,"column":29},"end":{"line":128,"column":null}},"12":{"start":{"line":127,"column":49},"end":{"line":127,"column":68}},"13":{"start":{"line":127,"column":85},"end":{"line":127,"column":103}},"14":{"start":{"line":128,"column":31},"end":{"line":128,"column":53}},"15":{"start":{"line":159,"column":24},"end":{"line":181,"column":null}},"16":{"start":{"line":162,"column":20},"end":{"line":162,"column":37}},"17":{"start":{"line":165,"column":49},"end":{"line":165,"column":66}},"18":{"start":{"line":165,"column":83},"end":{"line":165,"column":103}},"19":{"start":{"line":181,"column":50},"end":{"line":181,"column":68}},"20":{"start":{"line":187,"column":30},"end":{"line":187,"column":null}},"21":{"start":{"line":203,"column":26},"end":{"line":272,"column":null}},"22":{"start":{"line":215,"column":31},"end":{"line":217,"column":28}},"23":{"start":{"line":218,"column":20},"end":{"line":220,"column":24}},"24":{"start":{"line":222,"column":25},"end":{"line":224,"column":37}},"25":{"start":{"line":237,"column":27},"end":{"line":239,"column":28}},"26":{"start":{"line":251,"column":27},"end":{"line":253,"column":40}},"27":{"start":{"line":254,"column":33},"end":{"line":256,"column":57}},"28":{"start":{"line":272,"column":26},"end":{"line":272,"column":71}},"29":{"start":{"line":277,"column":30},"end":{"line":277,"column":null}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":5,"column":40},"end":{"line":5,"column":49}},"loc":{"start":{"line":5,"column":49},"end":{"line":5,"column":72}},"line":5},"1":{"name":"(anonymous_1)","decl":{"start":{"line":5,"column":80},"end":{"line":5,"column":89}},"loc":{"start":{"line":5,"column":89},"end":{"line":5,"column":139}},"line":5},"2":{"name":"(anonymous_2)","decl":{"start":{"line":22,"column":24},"end":{"line":22,"column":33}},"loc":{"start":{"line":22,"column":33},"end":{"line":22,"column":55}},"line":22},"3":{"name":"(anonymous_3)","decl":{"start":{"line":62,"column":40},"end":{"line":62,"column":49}},"loc":{"start":{"line":62,"column":49},"end":{"line":62,"column":67}},"line":62},"4":{"name":"(anonymous_4)","decl":{"start":{"line":62,"column":75},"end":{"line":62,"column":84}},"loc":{"start":{"line":62,"column":84},"end":{"line":62,"column":133}},"line":62},"5":{"name":"(anonymous_5)","decl":{"start":{"line":127,"column":40},"end":{"line":127,"column":49}},"loc":{"start":{"line":127,"column":49},"end":{"line":127,"column":68}},"line":127},"6":{"name":"(anonymous_6)","decl":{"start":{"line":127,"column":76},"end":{"line":127,"column":85}},"loc":{"start":{"line":127,"column":85},"end":{"line":127,"column":103}},"line":127},"7":{"name":"(anonymous_7)","decl":{"start":{"line":128,"column":22},"end":{"line":128,"column":31}},"loc":{"start":{"line":128,"column":31},"end":{"line":128,"column":53}},"line":128},"8":{"name":"(anonymous_8)","decl":{"start":{"line":162,"column":11},"end":{"line":162,"column":20}},"loc":{"start":{"line":162,"column":20},"end":{"line":162,"column":37}},"line":162},"9":{"name":"(anonymous_9)","decl":{"start":{"line":165,"column":40},"end":{"line":165,"column":49}},"loc":{"start":{"line":165,"column":49},"end":{"line":165,"column":66}},"line":165},"10":{"name":"(anonymous_10)","decl":{"start":{"line":165,"column":74},"end":{"line":165,"column":83}},"loc":{"start":{"line":165,"column":83},"end":{"line":165,"column":103}},"line":165},"11":{"name":"(anonymous_11)","decl":{"start":{"line":181,"column":41},"end":{"line":181,"column":50}},"loc":{"start":{"line":181,"column":50},"end":{"line":181,"column":68}},"line":181},"12":{"name":"(anonymous_12)","decl":{"start":{"line":215,"column":22},"end":{"line":215,"column":31}},"loc":{"start":{"line":215,"column":31},"end":{"line":217,"column":28}},"line":215},"13":{"name":"(anonymous_13)","decl":{"start":{"line":218,"column":11},"end":{"line":218,"column":20}},"loc":{"start":{"line":218,"column":20},"end":{"line":220,"column":24}},"line":218},"14":{"name":"(anonymous_14)","decl":{"start":{"line":222,"column":16},"end":{"line":222,"column":25}},"loc":{"start":{"line":222,"column":25},"end":{"line":224,"column":37}},"line":222},"15":{"name":"(anonymous_15)","decl":{"start":{"line":237,"column":18},"end":{"line":237,"column":27}},"loc":{"start":{"line":237,"column":27},"end":{"line":239,"column":28}},"line":237},"16":{"name":"(anonymous_16)","decl":{"start":{"line":251,"column":18},"end":{"line":251,"column":27}},"loc":{"start":{"line":251,"column":27},"end":{"line":253,"column":40}},"line":251},"17":{"name":"(anonymous_17)","decl":{"start":{"line":254,"column":24},"end":{"line":254,"column":33}},"loc":{"start":{"line":254,"column":33},"end":{"line":256,"column":57}},"line":254},"18":{"name":"(anonymous_18)","decl":{"start":{"line":272,"column":17},"end":{"line":272,"column":26}},"loc":{"start":{"line":272,"column":26},"end":{"line":272,"column":71}},"line":272}},"branchMap":{"0":{"loc":{"start":{"line":5,"column":89},"end":{"line":5,"column":139}},"type":"binary-expr","locations":[{"start":{"line":5,"column":89},"end":{"line":5,"column":116}},{"start":{"line":5,"column":116},"end":{"line":5,"column":139}}],"line":5},"1":{"loc":{"start":{"line":62,"column":84},"end":{"line":62,"column":133}},"type":"binary-expr","locations":[{"start":{"line":62,"column":84},"end":{"line":62,"column":115}},{"start":{"line":62,"column":115},"end":{"line":62,"column":133}}],"line":62},"2":{"loc":{"start":{"line":215,"column":31},"end":{"line":217,"column":28}},"type":"cond-expr","locations":[{"start":{"line":216,"column":6},"end":{"line":216,"column":null}},{"start":{"line":217,"column":6},"end":{"line":217,"column":28}}],"line":215},"3":{"loc":{"start":{"line":216,"column":6},"end":{"line":216,"column":null}},"type":"binary-expr","locations":[{"start":{"line":216,"column":6},"end":{"line":216,"column":37}},{"start":{"line":216,"column":37},"end":{"line":216,"column":null}}],"line":216},"4":{"loc":{"start":{"line":218,"column":20},"end":{"line":220,"column":24}},"type":"cond-expr","locations":[{"start":{"line":219,"column":6},"end":{"line":219,"column":null}},{"start":{"line":220,"column":6},"end":{"line":220,"column":24}}],"line":218},"5":{"loc":{"start":{"line":222,"column":25},"end":{"line":224,"column":37}},"type":"cond-expr","locations":[{"start":{"line":223,"column":6},"end":{"line":223,"column":null}},{"start":{"line":224,"column":6},"end":{"line":224,"column":37}}],"line":222},"6":{"loc":{"start":{"line":237,"column":27},"end":{"line":239,"column":28}},"type":"cond-expr","locations":[{"start":{"line":238,"column":8},"end":{"line":238,"column":null}},{"start":{"line":239,"column":8},"end":{"line":239,"column":28}}],"line":237},"7":{"loc":{"start":{"line":251,"column":27},"end":{"line":253,"column":40}},"type":"cond-expr","locations":[{"start":{"line":252,"column":8},"end":{"line":252,"column":null}},{"start":{"line":253,"column":8},"end":{"line":253,"column":40}}],"line":251},"8":{"loc":{"start":{"line":254,"column":33},"end":{"line":256,"column":57}},"type":"cond-expr","locations":[{"start":{"line":255,"column":8},"end":{"line":255,"column":null}},{"start":{"line":256,"column":8},"end":{"line":256,"column":57}}],"line":254},"9":{"loc":{"start":{"line":255,"column":8},"end":{"line":255,"column":null}},"type":"binary-expr","locations":[{"start":{"line":255,"column":8},"end":{"line":255,"column":39}},{"start":{"line":255,"column":39},"end":{"line":255,"column":null}}],"line":255},"10":{"loc":{"start":{"line":256,"column":8},"end":{"line":256,"column":57}},"type":"binary-expr","locations":[{"start":{"line":256,"column":8},"end":{"line":256,"column":35}},{"start":{"line":256,"column":35},"end":{"line":256,"column":57}}],"line":256},"11":{"loc":{"start":{"line":272,"column":26},"end":{"line":272,"column":71}},"type":"cond-expr","locations":[{"start":{"line":272,"column":42},"end":{"line":272,"column":59}},{"start":{"line":272,"column":59},"end":{"line":272,"column":71}}],"line":272}},"s":{"0":1,"1":40,"2":40,"3":1,"4":1,"5":3,"6":1,"7":1,"8":40,"9":40,"10":1,"11":1,"12":40,"13":40,"14":40,"15":1,"16":40,"17":40,"18":40,"19":40,"20":1,"21":1,"22":120,"23":120,"24":120,"25":120,"26":120,"27":120,"28":120,"29":1},"f":{"0":40,"1":40,"2":3,"3":40,"4":40,"5":40,"6":40,"7":40,"8":40,"9":40,"10":40,"11":40,"12":120,"13":120,"14":120,"15":120,"16":120,"17":120,"18":120},"b":{"0":[40,40],"1":[40,40],"2":[40,80],"3":[40,40],"4":[40,80],"5":[40,80],"6":[40,80],"7":[40,80],"8":[40,80],"9":[40,40],"10":[80,80],"11":[40,80]},"meta":{"lastBranch":12,"lastFunction":19,"lastStatement":30,"seen":{"s:4:27:5:Infinity":0,"f:5:40:5:49":0,"s:5:49:5:72":1,"f:5:80:5:89":1,"s:5:89:5:139":2,"b:5:89:5:116:5:116:5:139":0,"s:10:30:10:Infinity":3,"s:17:29:22:Infinity":4,"f:22:24:22:33":2,"s:22:33:22:55":5,"s:40:24:40:Infinity":6,"s:61:29:62:Infinity":7,"f:62:40:62:49":3,"s:62:49:62:67":8,"f:62:75:62:84":4,"s:62:84:62:133":9,"b:62:84:62:115:62:115:62:133":1,"s:91:27:91:Infinity":10,"s:123:29:128:Infinity":11,"f:127:40:127:49":5,"s:127:49:127:68":12,"f:127:76:127:85":6,"s:127:85:127:103":13,"f:128:22:128:31":7,"s:128:31:128:53":14,"s:159:24:181:Infinity":15,"f:162:11:162:20":8,"s:162:20:162:37":16,"f:165:40:165:49":9,"s:165:49:165:66":17,"f:165:74:165:83":10,"s:165:83:165:103":18,"f:181:41:181:50":11,"s:181:50:181:68":19,"s:187:30:187:Infinity":20,"s:203:26:272:Infinity":21,"f:215:22:215:31":12,"s:215:31:217:28":22,"b:216:6:216:Infinity:217:6:217:28":2,"b:216:6:216:37:216:37:216:Infinity":3,"f:218:11:218:20":13,"s:218:20:220:24":23,"b:219:6:219:Infinity:220:6:220:24":4,"f:222:16:222:25":14,"s:222:25:224:37":24,"b:223:6:223:Infinity:224:6:224:37":5,"f:237:18:237:27":15,"s:237:27:239:28":25,"b:238:8:238:Infinity:239:8:239:28":6,"f:251:18:251:27":16,"s:251:27:253:40":26,"b:252:8:252:Infinity:253:8:253:40":7,"f:254:24:254:33":17,"s:254:33:256:57":27,"b:255:8:255:Infinity:256:8:256:57":8,"b:255:8:255:39:255:39:255:Infinity":9,"b:256:8:256:35:256:35:256:57":10,"f:272:17:272:26":18,"s:272:26:272:71":28,"b:272:42:272:59:272:59:272:71":11,"s:277:30:277:Infinity":29}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/ProjectPage/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/ProjectPage/index.tsx","statementMap":{"0":{"start":{"line":10,"column":20},"end":{"line":10,"column":null}},"1":{"start":{"line":11,"column":28},"end":{"line":11,"column":null}},"2":{"start":{"line":12,"column":28},"end":{"line":12,"column":null}},"3":{"start":{"line":14,"column":2},"end":{"line":28,"column":null}},"4":{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},"5":{"start":{"line":16,"column":24},"end":{"line":16,"column":null}},"6":{"start":{"line":17,"column":8},"end":{"line":25,"column":null}},"7":{"start":{"line":18,"column":12},"end":{"line":18,"column":null}},"8":{"start":{"line":19,"column":25},"end":{"line":19,"column":null}},"9":{"start":{"line":20,"column":12},"end":{"line":20,"column":null}},"10":{"start":{"line":22,"column":12},"end":{"line":22,"column":null}},"11":{"start":{"line":24,"column":12},"end":{"line":24,"column":null}},"12":{"start":{"line":27,"column":4},"end":{"line":27,"column":null}},"13":{"start":{"line":30,"column":2},"end":{"line":30,"column":null}},"14":{"start":{"line":30,"column":15},"end":{"line":30,"column":null}},"15":{"start":{"line":31,"column":2},"end":{"line":31,"column":null}},"16":{"start":{"line":31,"column":16},"end":{"line":31,"column":null}},"17":{"start":{"line":34,"column":20},"end":{"line":34,"column":null}},"18":{"start":{"line":36,"column":2},"end":{"line":93,"column":null}},"19":{"start":{"line":84,"column":16},"end":{"line":86,"column":null}}},"fnMap":{"0":{"name":"ProjectPage","decl":{"start":{"line":9,"column":24},"end":{"line":9,"column":38}},"loc":{"start":{"line":9,"column":38},"end":{"line":95,"column":null}},"line":9},"1":{"name":"(anonymous_1)","decl":{"start":{"line":14,"column":12},"end":{"line":14,"column":18}},"loc":{"start":{"line":14,"column":18},"end":{"line":28,"column":5}},"line":14},"2":{"name":"loadData","decl":{"start":{"line":15,"column":19},"end":{"line":15,"column":30}},"loc":{"start":{"line":15,"column":30},"end":{"line":26,"column":null}},"line":15},"3":{"name":"(anonymous_3)","decl":{"start":{"line":83,"column":41},"end":{"line":83,"column":42}},"loc":{"start":{"line":84,"column":16},"end":{"line":86,"column":null}},"line":84}},"branchMap":{"0":{"loc":{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},"type":"if","locations":[{"start":{"line":16,"column":8},"end":{"line":16,"column":null}},{"start":{},"end":{}}],"line":16},"1":{"loc":{"start":{"line":30,"column":2},"end":{"line":30,"column":null}},"type":"if","locations":[{"start":{"line":30,"column":2},"end":{"line":30,"column":null}},{"start":{},"end":{}}],"line":30},"2":{"loc":{"start":{"line":31,"column":2},"end":{"line":31,"column":null}},"type":"if","locations":[{"start":{"line":31,"column":2},"end":{"line":31,"column":null}},{"start":{},"end":{}}],"line":31},"3":{"loc":{"start":{"line":53,"column":36},"end":{"line":53,"column":81}},"type":"binary-expr","locations":[{"start":{"line":53,"column":36},"end":{"line":53,"column":62}},{"start":{"line":53,"column":62},"end":{"line":53,"column":81}}],"line":53}},"s":{"0":4,"1":4,"2":4,"3":4,"4":2,"5":0,"6":2,"7":2,"8":2,"9":2,"10":0,"11":2,"12":2,"13":4,"14":2,"15":2,"16":2,"17":1,"18":1,"19":2},"f":{"0":4,"1":2,"2":2,"3":2},"b":{"0":[0,2],"1":[2,2],"2":[1,1],"3":[1,0]},"meta":{"lastBranch":4,"lastFunction":4,"lastStatement":20,"seen":{"f:9:24:9:38":0,"s:10:20:10:Infinity":0,"s:11:28:11:Infinity":1,"s:12:28:12:Infinity":2,"s:14:2:28:Infinity":3,"f:14:12:14:18":1,"f:15:19:15:30":2,"b:16:8:16:Infinity:undefined:undefined:undefined:undefined":0,"s:16:8:16:Infinity":4,"s:16:24:16:Infinity":5,"s:17:8:25:Infinity":6,"s:18:12:18:Infinity":7,"s:19:25:19:Infinity":8,"s:20:12:20:Infinity":9,"s:22:12:22:Infinity":10,"s:24:12:24:Infinity":11,"s:27:4:27:Infinity":12,"b:30:2:30:Infinity:undefined:undefined:undefined:undefined":1,"s:30:2:30:Infinity":13,"s:30:15:30:Infinity":14,"b:31:2:31:Infinity:undefined:undefined:undefined:undefined":2,"s:31:2:31:Infinity":15,"s:31:16:31:Infinity":16,"s:34:20:34:Infinity":17,"s:36:2:93:Infinity":18,"b:53:36:53:62:53:62:53:81":3,"f:83:41:83:42":3,"s:84:16:86:Infinity":19}}} +,"/home/cecilia/Documents/CTable/frontend/src/pages/Register/index.tsx": {"path":"/home/cecilia/Documents/CTable/frontend/src/pages/Register/index.tsx","statementMap":{"0":{"start":{"line":13,"column":38},"end":{"line":13,"column":null}},"1":{"start":{"line":16,"column":69},"end":{"line":16,"column":null}},"2":{"start":{"line":17,"column":8},"end":{"line":17,"column":null}},"3":{"start":{"line":20,"column":4},"end":{"line":20,"column":null}},"4":{"start":{"line":21,"column":4},"end":{"line":39,"column":null}},"5":{"start":{"line":22,"column":6},"end":{"line":22,"column":null}},"6":{"start":{"line":24,"column":6},"end":{"line":24,"column":null}},"7":{"start":{"line":27,"column":6},"end":{"line":27,"column":null}},"8":{"start":{"line":28,"column":6},"end":{"line":30,"column":null}},"9":{"start":{"line":29,"column":8},"end":{"line":29,"column":null}},"10":{"start":{"line":33,"column":6},"end":{"line":33,"column":null}},"11":{"start":{"line":36,"column":6},"end":{"line":38,"column":null}},"12":{"start":{"line":37,"column":8},"end":{"line":37,"column":null}},"13":{"start":{"line":42,"column":2},"end":{"line":109,"column":null}},"14":{"start":{"line":49,"column":25},"end":{"line":49,"column":null}},"15":{"start":{"line":92,"column":14},"end":{"line":98,"column":null}}},"fnMap":{"0":{"name":"Register","decl":{"start":{"line":11,"column":24},"end":{"line":11,"column":35}},"loc":{"start":{"line":11,"column":35},"end":{"line":111,"column":null}},"line":11},"1":{"name":"onSubmit","decl":{"start":{"line":19,"column":17},"end":{"line":19,"column":26}},"loc":{"start":{"line":19,"column":47},"end":{"line":40,"column":null}},"line":19},"2":{"name":"(anonymous_2)","decl":{"start":{"line":28,"column":17},"end":{"line":28,"column":23}},"loc":{"start":{"line":28,"column":23},"end":{"line":30,"column":9}},"line":28},"3":{"name":"(anonymous_3)","decl":{"start":{"line":49,"column":19},"end":{"line":49,"column":25}},"loc":{"start":{"line":49,"column":25},"end":{"line":49,"column":null}},"line":49},"4":{"name":"(anonymous_4)","decl":{"start":{"line":91,"column":20},"end":{"line":91,"column":21}},"loc":{"start":{"line":92,"column":14},"end":{"line":98,"column":null}},"line":92}},"branchMap":{"0":{"loc":{"start":{"line":36,"column":6},"end":{"line":38,"column":null}},"type":"if","locations":[{"start":{"line":36,"column":6},"end":{"line":38,"column":null}},{"start":{},"end":{}}],"line":36},"1":{"loc":{"start":{"line":45,"column":7},"end":{"line":50,"column":null}},"type":"binary-expr","locations":[{"start":{"line":45,"column":7},"end":{"line":45,"column":null}},{"start":{"line":46,"column":8},"end":{"line":50,"column":null}}],"line":45}},"s":{"0":8,"1":8,"2":8,"3":2,"4":2,"5":2,"6":1,"7":1,"8":1,"9":0,"10":1,"11":1,"12":1,"13":8,"14":0,"15":10},"f":{"0":8,"1":2,"2":0,"3":0,"4":10},"b":{"0":[1,0],"1":[8,2]},"meta":{"lastBranch":2,"lastFunction":5,"lastStatement":16,"seen":{"f:11:24:11:35":0,"s:13:38:13:Infinity":0,"s:16:69:16:Infinity":1,"s:17:8:17:Infinity":2,"f:19:17:19:26":1,"s:20:4:20:Infinity":3,"s:21:4:39:Infinity":4,"s:22:6:22:Infinity":5,"s:24:6:24:Infinity":6,"s:27:6:27:Infinity":7,"s:28:6:30:Infinity":8,"f:28:17:28:23":2,"s:29:8:29:Infinity":9,"s:33:6:33:Infinity":10,"b:36:6:38:Infinity:undefined:undefined:undefined:undefined":0,"s:36:6:38:Infinity":11,"s:37:8:37:Infinity":12,"s:42:2:109:Infinity":13,"b:45:7:45:Infinity:46:8:50:Infinity":1,"f:49:19:49:25":3,"s:49:25:49:Infinity":14,"f:91:20:91:21":4,"s:92:14:98:Infinity":15}}} +} diff --git a/frontend/coverage/index.html b/frontend/coverage/index.html new file mode 100644 index 0000000..66eb4df --- /dev/null +++ b/frontend/coverage/index.html @@ -0,0 +1,431 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 75.59% + Statements + 672/889 +
+ + +
+ 66.03% + Branches + 278/421 +
+ + +
+ 77.74% + Functions + 262/337 +
+ + +
+ 76.3% + Lines + 644/844 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src +
+
100%1/1100%0/0100%1/1100%1/1
src/API +
+
5.3%6/1134%2/504.54%1/225.3%6/113
src/components/common/Keyword +
+
100%3/3100%0/0100%1/1100%3/3
src/components/common/Modal +
+
100%12/12100%4/4100%4/4100%12/12
src/components/common/Toast +
+
100%7/7100%0/0100%4/4100%7/7
src/components/domain/CreationForm +
+
87.32%62/7185.71%12/1484.48%49/5886.95%60/69
src/components/domain/Postcard +
+
69.23%72/10458.9%43/7364.28%18/2872.16%70/97
src/components/domain/Searchbar +
+
91.07%51/5683.33%30/3678.94%15/1990.9%50/55
src/components/domain/TagInput +
+
94.28%33/3576.19%16/2192.85%13/1493.93%31/33
src/components/layout/Header +
+
100%1/1100%0/0100%1/1100%1/1
src/components/layout/HeaderHome +
+
100%1/1100%0/0100%1/1100%1/1
src/components/layout/Sidebar +
+
93.75%15/1675%3/4100%5/593.75%15/16
src/pages/CommunityPage +
+
83.94%115/13768.42%39/5788.05%59/6785.24%104/122
src/pages/CreateCommunity +
+
81.81%27/3390.9%20/2271.42%5/781.81%27/33
src/pages/CreateProject +
+
84.44%38/4587.09%27/3180%8/1086.04%37/43
src/pages/EditProfile +
+
87.09%27/3155.55%10/1866.66%4/693.1%27/29
src/pages/Feed +
+
86.27%44/5169.23%9/1374.07%20/2787.75%43/49
src/pages/Home +
+
100%1/1100%0/0100%1/1100%1/1
src/pages/Login +
+
87.5%14/1675%3/450%2/487.5%14/16
src/pages/Profile +
+
92.43%110/11982.25%51/6289.58%43/4894.54%104/110
src/pages/ProjectPage +
+
90%18/2075%6/8100%4/494.11%16/17
src/pages/Register +
+
87.5%14/1675%3/460%3/587.5%14/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/index.html b/frontend/coverage/lcov-report/index.html new file mode 100644 index 0000000..8d9e753 --- /dev/null +++ b/frontend/coverage/lcov-report/index.html @@ -0,0 +1,431 @@ + + + + + + Code coverage report for All files + + + + + + + + + +
+
+

All files

+
+ +
+ 75.59% + Statements + 672/889 +
+ + +
+ 66.03% + Branches + 278/421 +
+ + +
+ 77.74% + Functions + 262/337 +
+ + +
+ 76.3% + Lines + 644/844 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
src +
+
100%1/1100%0/0100%1/1100%1/1
src/API +
+
5.3%6/1134%2/504.54%1/225.3%6/113
src/components/common/Keyword +
+
100%3/3100%0/0100%1/1100%3/3
src/components/common/Modal +
+
100%12/12100%4/4100%4/4100%12/12
src/components/common/Toast +
+
100%7/7100%0/0100%4/4100%7/7
src/components/domain/CreationForm +
+
87.32%62/7185.71%12/1484.48%49/5886.95%60/69
src/components/domain/Postcard +
+
69.23%72/10458.9%43/7364.28%18/2872.16%70/97
src/components/domain/Searchbar +
+
91.07%51/5683.33%30/3678.94%15/1990.9%50/55
src/components/domain/TagInput +
+
94.28%33/3576.19%16/2192.85%13/1493.93%31/33
src/components/layout/Header +
+
100%1/1100%0/0100%1/1100%1/1
src/components/layout/HeaderHome +
+
100%1/1100%0/0100%1/1100%1/1
src/components/layout/Sidebar +
+
93.75%15/1675%3/4100%5/593.75%15/16
src/pages/CommunityPage +
+
83.94%115/13768.42%39/5788.05%59/6785.24%104/122
src/pages/CreateCommunity +
+
81.81%27/3390.9%20/2271.42%5/781.81%27/33
src/pages/CreateProject +
+
84.44%38/4587.09%27/3180%8/1086.04%37/43
src/pages/EditProfile +
+
87.09%27/3155.55%10/1866.66%4/693.1%27/29
src/pages/Feed +
+
86.27%44/5169.23%9/1374.07%20/2787.75%43/49
src/pages/Home +
+
100%1/1100%0/0100%1/1100%1/1
src/pages/Login +
+
87.5%14/1675%3/450%2/487.5%14/16
src/pages/Profile +
+
92.43%110/11982.25%51/6289.58%43/4894.54%104/110
src/pages/ProjectPage +
+
90%18/2075%6/8100%4/494.11%16/17
src/pages/Register +
+
87.5%14/1675%3/460%3/587.5%14/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/API/Comment.ts.html b/frontend/coverage/lcov-report/src/API/Comment.ts.html new file mode 100644 index 0000000..c203914 --- /dev/null +++ b/frontend/coverage/lcov-report/src/API/Comment.ts.html @@ -0,0 +1,319 @@ + + + + + + Code coverage report for src/API/Comment.ts + + + + + + + + + +
+
+

All files / src/API Comment.ts

+
+ +
+ 4.16% + Statements + 1/24 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 4.16% + Lines + 1/24 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import api from './api';
+import { isAxiosError } from 'axios';
+export interface CommentProps {
+  projectTitle?: string;
+  commentID?: string;
+  content: string;
+  createdAt?: string;
+  authorID?: string;
+  projectID?: string;
+  username?: string;
+  fullName?: string;
+}
+ 
+const getAuthHeader = () => {
+  return {
+    headers: {
+      'Authorization': `Bearer ${localStorage.getItem('token')}`
+    }
+  };
+};
+ 
+export async function CreateComment(projectId: string, content: string) {
+  try{
+ 
+    const response = await api.post(`/api/project/${projectId}/comments`, 
+      {content},
+      getAuthHeader()
+    );
+ 
+    return response.data;
+ 
+  }catch(error){
+ 
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao enviar comentário.");
+ 
+  }
+}
+ 
+export async function GetComments(projectId: string): Promise<CommentProps[]> {
+  try{
+  
+    const response = await api.get(`/api/project/${projectId}/comments`, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    console.error("Erro ao buscar comentários:", error);
+    throw new Error("Erro ao carregar comentários.");
+  }
+ 
+ 
+}
+ 
+export async function GetUserComments(): Promise<CommentProps[]> {
+  try{
+    const response = await api.get('/api/user/comments', getAuthHeader());
+ 
+    return response.data;
+  }catch(error){
+    console.error("Erro ao buscar comentários do usuário:", error);
+    throw new Error("Erro ao carregar comentários do usuário.");
+  }
+}
+ 
+export async function DeleteComment(commentId: string) {
+  try{
+  
+    const response = await api.delete(`/api/project/${commentId}/deletecomment`, getAuthHeader());
+ 
+    return response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao excluir comentário.");
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/API/Community.ts.html b/frontend/coverage/lcov-report/src/API/Community.ts.html new file mode 100644 index 0000000..2c98955 --- /dev/null +++ b/frontend/coverage/lcov-report/src/API/Community.ts.html @@ -0,0 +1,451 @@ + + + + + + Code coverage report for src/API/Community.ts + + + + + + + + + +
+
+

All files / src/API Community.ts

+
+ +
+ 2.04% + Statements + 1/49 +
+ + +
+ 0% + Branches + 0/24 +
+ + +
+ 0% + Functions + 0/9 +
+ + +
+ 2.04% + Lines + 1/49 +
+ + +
+

+ 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 +123  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import api from './api';
+import { isAxiosError } from 'axios';
+ 
+export interface CommunityProps {
+    communityID: string;
+    name: string;
+    description: string;
+    technologies: string[];
+    createdAt: Date;
+    updatedAt: Date;
+    memberCount?: number; 
+    isMember?: boolean;
+    isAdmin?: boolean;
+}
+ 
+const getAuthHeader = () => {
+  return {
+    headers: {
+      'Authorization': `Bearer ${localStorage.getItem('token')}`
+    }
+  };
+};
+ 
+export async function NewCommunity(data: CommunityProps) { 
+ 
+    try{
+      console.log("Enviando dados da comunidade:", data);
+      const response = await api.post('/api/newcommunity', data, getAuthHeader());
+      return response.data
+    }catch(error){
+      if (isAxiosError(error) && error.response) {
+          throw new Error(error.response.data.message);
+      }
+      throw new Error("Erro ao criar comunidade.");
+    }
+}
+ 
+export async function GetUserCommunities(): Promise<CommunityProps[]> {
+  try{
+  const response = await api.get<CommunityProps[]>('/api/user/communities', getAuthHeader());
+  return response.data
+  }catch(error){
+    console.error("Erro ao obter comunidades:", error);
+    throw new Error('Erro ao obter comunidades');
+  }
+} 
+ 
+export async function GetCommunityById(communityId: string) {
+  try{
+    const response = await api.get(`/api/communities/data/${communityId}`, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response?.status === 404) {
+          throw new Error('Comunidade não encontrada');
+      }
+    throw new Error('Erro ao carregar a comunidade');
+  }
+}
+ 
+export async function JoinCommunity(communityId: string) {
+  try{
+    const response = await api.post(`/api/communities/${communityId}/join`, {}, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+          throw new Error(error.response.data.message);
+      }
+    throw new Error('Erro ao entrar na comunidade');
+  }
+}
+ 
+export async function DeleteCommunity(communityId: string) {
+  try{
+    const response = await api.delete(`/api/communities/deletecommunity/${communityId}`, getAuthHeader());
+    return response.data
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+          throw new Error(error.response.data.message);
+      }
+    throw new Error("Erro ao excluir comunidade.");
+  }
+}
+ 
+export async function UpdateCommunity(communityId: string, data: CommunityProps) {
+  try{
+    const response = await api.put(`/api/communities/updatecommunity/${communityId}`,
+      data,
+      getAuthHeader()
+    );
+ 
+    return response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+        throw new Error(error.response.data.message);
+      }
+    throw new Error("Erro ao atualizar comunidade.");
+  }
+}
+ 
+export async function LeaveCommunity(communityId: string) {
+  try{
+    const response = await api.delete(`/api/user/leavecommunity/${communityId}`, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+        throw new Error(error.response.data.message);
+      }
+    throw new Error("Erro ao sair da comunidade.");
+  }
+}
+ 
+export async function GetAllCommunities(): Promise<CommunityProps[]> {
+  try{
+    const response = await api.get<CommunityProps[]>('/api/communities', getAuthHeader());
+    return response.data
+  }catch(error){
+    console.error("Erro ao obter todas as comunidades:", error);
+    throw new Error('Erro ao obter todas as comunidades');
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/API/Project.ts.html b/frontend/coverage/lcov-report/src/API/Project.ts.html new file mode 100644 index 0000000..d0c2729 --- /dev/null +++ b/frontend/coverage/lcov-report/src/API/Project.ts.html @@ -0,0 +1,415 @@ + + + + + + Code coverage report for src/API/Project.ts + + + + + + + + + +
+
+

All files / src/API Project.ts

+
+ +
+ 7.69% + Statements + 3/39 +
+ + +
+ 0% + Branches + 0/16 +
+ + +
+ 12.5% + Functions + 1/8 +
+ + +
+ 7.69% + Lines + 3/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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +2x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import api from './api';
+import { isAxiosError } from 'axios';
+ 
+export interface ProjectProps {
+  id?: string;
+  title: string;
+  description: string;
+  technologies: string[]; 
+  status: string;
+  startDate: Date;
+  authorUsername?: string; 
+  authorName?: string;
+  creatorID?: number;
+}
+ 
+export function parseDate(dataString: string): Date {
+  // Divide a string "20/11/2025" em partes
+  const [dia, mes, ano] = dataString.split('/');
+ 
+  // Cria a data: new Date(ano, mês - 1, dia)
+  return new Date(Number(ano), Number(mes) - 1, Number(dia));
+}
+ 
+const getAuthHeader = () => {
+  return {
+    headers: {
+      'Authorization': `Bearer ${localStorage.getItem('token')}`
+    }
+  };
+};
+ 
+export async function NewProject(data: ProjectProps) {
+  try{
+    const response = await api.post('/api/user/newproject', data, getAuthHeader());
+ 
+    return response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao criar projeto.");
+  }
+}
+ 
+export async function UpdateProject(projectId: string, data: ProjectProps) {
+  try{
+    const response = await api.put(`/api/user/updateproject/${projectId}`, 
+      data, 
+      getAuthHeader()
+    );
+    return response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao atualizar projeto.");
+  }
+ 
+}
+ 
+export async function GetFeedProjects(): Promise<ProjectProps[]> {
+ 
+  try{
+    const response = await api.get('/api/user/home', getAuthHeader());
+ 
+    console.log("Dados do feed de projetos:", response.data);
+ 
+    return response.data.feed;
+  }catch(error){
+    console.error("Erro ao buscar feed:", error);
+    throw new Error("Erro ao carregar o feed de projetos.");
+  }
+}
+ 
+export async function DeleteProject(projectId: string) {
+  try{
+    await api.delete(`/api/user/deleteproject/${projectId}`, getAuthHeader());
+  }
+  catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao excluir projeto.");
+  }
+}
+ 
+export async function GetUserProjects(): Promise<ProjectProps[]> {
+  try{
+    const response = await api.get('/api/user/projects', getAuthHeader());
+    
+    console.log("Dados dos projetos do usuário:", response.data.projects);
+ 
+    return response.data.projects;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao buscar projetos do usuário.");
+  }
+}
+ 
+export async function GetProjectById(projectId: string): Promise<ProjectProps> {
+  try{
+    const response = await api.get(`/api/projects/${projectId}`, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    console.error("Erro ao buscar projeto:", error);
+    throw new Error('Erro ao carregar projeto');
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/API/api.ts.html b/frontend/coverage/lcov-report/src/API/api.ts.html new file mode 100644 index 0000000..24bddd5 --- /dev/null +++ b/frontend/coverage/lcov-report/src/API/api.ts.html @@ -0,0 +1,103 @@ + + + + + + Code coverage report for src/API/api.ts + + + + + + + + + +
+
+

All files / src/API api.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +5x +  +  +  + 
import axios from 'axios';
+ 
+const api = axios.create({
+  baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000',
+});
+ 
+export default api;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/API/index.html b/frontend/coverage/lcov-report/src/API/index.html new file mode 100644 index 0000000..4c3cfe1 --- /dev/null +++ b/frontend/coverage/lcov-report/src/API/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/API + + + + + + + + + +
+
+

All files src/API

+
+ +
+ 5.3% + Statements + 6/113 +
+ + +
+ 4% + Branches + 2/50 +
+ + +
+ 4.54% + Functions + 1/22 +
+ + +
+ 5.3% + Lines + 6/113 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
Comment.ts +
+
4.16%1/240%0/80%0/54.16%1/24
Community.ts +
+
2.04%1/490%0/240%0/92.04%1/49
Project.ts +
+
7.69%3/390%0/1612.5%1/87.69%3/39
api.ts +
+
100%1/1100%2/2100%0/0100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/App.tsx.html b/frontend/coverage/lcov-report/src/App.tsx.html new file mode 100644 index 0000000..d17c8d1 --- /dev/null +++ b/frontend/coverage/lcov-report/src/App.tsx.html @@ -0,0 +1,142 @@ + + + + + + Code coverage report for src/App.tsx + + + + + + + + + +
+
+

All files / src App.tsx

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  + 
import { ThemeProvider } from "styled-components"
+import { defaultTheme } from './styles/themes/default'
+import { GlobalStyle } from './styles/global'
+import { Router } from "./Router"
+import { BrowserRouter } from "react-router-dom"
+ 
+function App() {
+ 
+  return (
+    <ThemeProvider theme={defaultTheme}>
+      <BrowserRouter>
+        <GlobalStyle/>
+        <Router />
+      </BrowserRouter>
+    </ThemeProvider>
+  )
+}
+ 
+export default App
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/common/Keyword/index.html b/frontend/coverage/lcov-report/src/components/common/Keyword/index.html new file mode 100644 index 0000000..39bb5d7 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/common/Keyword/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/common/Keyword + + + + + + + + + +
+
+

All files src/components/common/Keyword

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%3/3100%0/0100%1/1100%3/3
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/common/Keyword/index.tsx.html b/frontend/coverage/lcov-report/src/components/common/Keyword/index.tsx.html new file mode 100644 index 0000000..20a40a9 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/common/Keyword/index.tsx.html @@ -0,0 +1,145 @@ + + + + + + Code coverage report for src/components/common/Keyword/index.tsx + + + + + + + + + +
+
+

All files / src/components/common/Keyword index.tsx

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +1x +2x +  +  +  +  +  +  +  +  +  +1x
import React from 'react';
+import * as S from './styles';
+ 
+// Props que o componente Keyword aceita
+interface KeywordProps {
+  children: React.ReactNode;
+  onRemove: () => void;
+}
+ 
+export const Keyword: React.FC<KeywordProps> = ({ children, onRemove }) => {
+  return (
+    <S.KeywordTag>
+      {children}
+      <S.KeywordRemoveButton onClick={onRemove} aria-label={`Remover ${children}`}>
+        &times;
+      </S.KeywordRemoveButton>
+    </S.KeywordTag>
+  );
+};
+ 
+export const KeywordContainer = S.KeywordContainer;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/common/Modal/index.html b/frontend/coverage/lcov-report/src/components/common/Modal/index.html new file mode 100644 index 0000000..b6fb44d --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/common/Modal/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/common/Modal + + + + + + + + + +
+
+

All files src/components/common/Modal

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%12/12100%4/4100%4/4100%12/12
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/common/Modal/index.tsx.html b/frontend/coverage/lcov-report/src/components/common/Modal/index.tsx.html new file mode 100644 index 0000000..086df4c --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/common/Modal/index.tsx.html @@ -0,0 +1,223 @@ + + + + + + Code coverage report for src/components/common/Modal/index.tsx + + + + + + + + + +
+
+

All files / src/components/common/Modal index.tsx

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +1x +  +5x +5x +4x +  +1x +  +  +5x +5x +  +  +  +5x +1x +  +  +  +4x +2x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  + 
import React, { useEffect } from 'react';
+import { createPortal } from 'react-dom';
+import * as S from './styles';
+ 
+interface ModalProps {
+  isOpen: boolean;
+  onClose: () => void;
+  children: React.ReactNode;
+  title: string;
+}
+ 
+const Modal: React.FC<ModalProps> = ({ isOpen, onClose, title, children }) => {
+  // Bloqueia o scroll do body quando o modal está aberto
+  useEffect(() => {
+    if (isOpen) {
+      document.body.style.overflow = 'hidden';
+    } else {
+      document.body.style.overflow = 'unset';
+    }
+    
+    return () => {
+      document.body.style.overflow = 'unset';
+    };
+  }, [isOpen]);
+ 
+  if (!isOpen) {
+    return null;
+  }
+ 
+  // Impede que o clique no modal feche o modal (só o overlay)
+  const handleContentClick = (e: React.MouseEvent) => {
+    e.stopPropagation();
+  };
+ 
+  return createPortal(
+    <S.ModalOverlay onClick={onClose}>
+      <S.ModalContent onClick={handleContentClick}>
+        <S.CloseButton onClick={onClose}>&times;</S.CloseButton>
+        <S.ModalTitle>{title}</S.ModalTitle>
+        {children}
+      </S.ModalContent>
+    </S.ModalOverlay>,
+    document.body
+  );
+};
+ 
+export default Modal;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/common/Toast/index.html b/frontend/coverage/lcov-report/src/components/common/Toast/index.html new file mode 100644 index 0000000..16aa6e5 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/common/Toast/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/common/Toast + + + + + + + + + +
+
+

All files src/components/common/Toast

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%7/7100%0/0100%4/4100%7/7
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/common/Toast/index.tsx.html b/frontend/coverage/lcov-report/src/components/common/Toast/index.tsx.html new file mode 100644 index 0000000..7608030 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/common/Toast/index.tsx.html @@ -0,0 +1,199 @@ + + + + + + Code coverage report for src/components/common/Toast/index.tsx + + + + + + + + + +
+
+

All files / src/components/common/Toast index.tsx

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +4x +4x +1x +  +  +  +4x +4x +  +  +  +4x +  +  +  +  +  +  +  +  +  + 
import React, { useEffect } from 'react';
+import { ToastContainer, ToastMessage, CloseButton } from './styles';
+ 
+interface ToastProps {
+  message: string;
+  type: 'success' | 'error';
+  onClose: () => void; // Função para fechar o toast
+}
+ 
+export interface NotificationState {
+  message: string;
+  type: 'success' | 'error';
+}
+ 
+const Toast: React.FC<ToastProps> = ({ message, type, onClose }) => {
+  
+  // Efeito para fechar o toast automaticamente após 5 segundos
+  useEffect(() => {
+    const timer = setTimeout(() => {
+      onClose();
+    }, 5000); 
+ 
+    // Limpa o timer se o componente for desmontado 
+    return () => {
+      clearTimeout(timer);
+    };
+  }, [onClose]);
+ 
+  return (
+    <ToastContainer type={type}>
+      <ToastMessage>{message}</ToastMessage>
+      <CloseButton onClick={onClose}>
+        &times; 
+      </CloseButton>
+    </ToastContainer>
+  );
+};
+ 
+export default Toast;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/domain/CreationForm/index.html b/frontend/coverage/lcov-report/src/components/domain/CreationForm/index.html new file mode 100644 index 0000000..8b9d3b1 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/domain/CreationForm/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/domain/CreationForm + + + + + + + + + +
+
+

All files src/components/domain/CreationForm

+
+ +
+ 87.32% + Statements + 62/71 +
+ + +
+ 85.71% + Branches + 12/14 +
+ + +
+ 84.48% + Functions + 49/58 +
+ + +
+ 86.95% + Lines + 60/69 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
styles.ts +
+
87.32%62/7185.71%12/1484.48%49/5886.95%60/69
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/domain/CreationForm/styles.ts.html b/frontend/coverage/lcov-report/src/components/domain/CreationForm/styles.ts.html new file mode 100644 index 0000000..905a81c --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/domain/CreationForm/styles.ts.html @@ -0,0 +1,1390 @@ + + + + + + Code coverage report for src/components/domain/CreationForm/styles.ts + + + + + + + + + +
+
+

All files / src/components/domain/CreationForm styles.ts

+
+ +
+ 87.32% + Statements + 62/71 +
+ + +
+ 85.71% + Branches + 12/14 +
+ + +
+ 84.48% + Functions + 49/58 +
+ + +
+ 86.95% + Lines + 60/69 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436  +  +  +2x +20x +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +86x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +86x +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +33x +  +  +33x +  +  +  +  +  +33x +  +  +  +  +33x +33x +  +  +  +  +33x +33x +33x +  +  +  +  +  +2x +  +  +  +  +  +  +  +13x +  +  +  +  +  +  +  +  +  +13x +  +  +  +13x +  +  +  +  +  +2x +  +  +  +  +13x +  +  +13x +  +  +  +  +  +  +  +  +  +  +  +  +13x +13x +  +  +  +  +13x +13x +13x +  +  +  +  +  +13x +  +  +  +  +13x +13x +  +  +  +  +2x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +20x +20x +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +20x +  +  +20x +  +  +  +  +  +  +  +20x +  +  +  +  +20x +20x +  +  +  +  +20x +20x +20x +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +20x +  +  +  +  +20x +  +  +  +  +2x +  +  +20x +  +  +  +  +20x +  +  +  +  +  +  +20x +20x +  +  +  +20x +20x +  + 
import styled from 'styled-components';
+ 
+// O <form> container
+export const FormContainer = styled.form`
+  background: ${props => props.theme.white};
+  border-radius: 24px;
+  padding: 40px;
+  width: 100%;
+  max-width: 800px;
+  margin: 0 auto;
+  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08),
+              0 2px 8px rgba(0, 0, 0, 0.04);
+  border: 1px solid ${props => props.theme.placeholder}20;
+  
+  animation: slideUp 0.5s ease-out;
+  
+  @keyframes slideUp {
+    from {
+      opacity: 0;
+      transform: translateY(20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+`;
+ 
+// Wrapper para cada par de (label + input)
+export const InputGroup = styled.div`
+  margin-bottom: 28px;
+  width: 100%;
+  
+  animation: fadeIn 0.4s ease-out backwards;
+  animation-delay: calc(var(--index, 0) * 0.05s);
+  
+  @keyframes fadeIn {
+    from {
+      opacity: 0;
+      transform: translateY(10px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+`;
+ 
+// Label 
+export const Label = styled.label`
+  display: block;
+  font-size: 0.95em;
+  font-weight: 700;
+  color: ${props => props.theme.title}; 
+  margin-bottom: 10px;
+  text-transform: uppercase;
+  letter-spacing: 0.5px;
+  font-size: 0.85rem;
+  padding-left: 4px;
+  
+  /* Indicador visual opcional */
+  position: relative;
+  
+  &::after {
+    content: '';
+    position: absolute;
+    left: -12px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 3px;
+    height: 14px;
+    background: linear-gradient(180deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.button} 100%);
+    border-radius: 2px;
+    opacity: 0;
+    transition: opacity 0.2s ease;
+  }
+  
+  ${InputGroup}:focus-within &::after {
+    opacity: 1;
+  }
+`;
+ 
+// Input 
+export const Input = styled.input`
+  width: 100%;
+  padding: 14px 20px;
+  font-size: 1em;
+  
+  background-color: ${props => props.theme['gray-100']};
+  border: 2px solid transparent;
+  border-radius: 12px;
+  color: ${props => props.theme.title};
+  box-sizing: border-box;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  font-weight: 500;
+ 
+  &::placeholder {
+    color: ${props => props.theme.placeholder};
+    font-weight: 400;
+  }
+  
+  &:hover {
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.placeholder}40;
+  }
+  
+  &:focus {
+    outline: none;
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.button};
+    box-shadow: 0 0 0 4px ${props => props.theme.button}15,
+                0 2px 8px rgba(0, 0, 0, 0.04);
+    transform: translateY(-1px);
+  }
+`;
+ 
+export const SelectWrapper = styled.div`
+  position: relative;
+  width: 100%;
+ 
+  /* A seta de seleção (CSS) */
+  &::after {
+    content: '▼';
+    font-size: 0.85em;
+    color: ${props => props.theme.placeholder};
+    position: absolute;
+    right: 20px;
+    top: 50%;
+    transform: translateY(-50%);
+    pointer-events: none;
+    transition: all 0.3s ease;
+  }
+  
+  &:hover::after {
+    color: ${props => props.theme.button};
+  }
+  
+  &:focus-within::after {
+    color: ${props => props.theme.button};
+    transform: translateY(-50%) rotate(180deg);
+  }
+`;
+ 
+// Componente de Select 
+export const Select = styled.select`
+  width: 100%;
+  padding: 14px 20px;
+  font-size: 1em;
+  
+  background-color: ${props => props.theme['gray-100']};
+  border: 2px solid transparent;
+  border-radius: 12px;
+  color: ${props => props.theme.title};
+  box-sizing: border-box;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  font-weight: 500;
+  cursor: pointer;
+ 
+  appearance: none;
+  -webkit-appearance: none;
+  -moz-appearance: none;
+ 
+  padding-right: 50px;
+  
+  &:hover {
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.placeholder}40;
+  }
+ 
+  &:focus {
+    outline: none;
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.button};
+    box-shadow: 0 0 0 4px ${props => props.theme.button}15,
+                0 2px 8px rgba(0, 0, 0, 0.04);
+    transform: translateY(-1px);
+  }
+ 
+  &:invalid {
+    color: ${props => props.theme.placeholder};
+  }
+  
+  option {
+    padding: 10px;
+    background: ${props => props.theme.white};
+    color: ${props => props.theme.title};
+  }
+`;
+ 
+// Wrapper para o input de busca E a lista de resultados 
+export const SearchWrapper = styled.div`
+  position: relative;
+  width: 100%;
+`;
+ 
+// Lista de resultados de busca que aparece abaixo do input 
+export const SearchResultsList = styled.ul`
+  position: absolute;
+  top: calc(100% + 4px);
+  left: 0;
+  right: 0;
+  background: ${props => props.theme.white};
+  border: 2px solid ${props => props.theme.button}20;
+  border-radius: 12px;
+  max-height: 240px;
+  overflow-y: auto;
+  margin: 0;
+  padding: 6px;
+  z-index: 100;
+  list-style: none;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12),
+              0 2px 8px rgba(0, 0, 0, 0.08);
+  
+  animation: slideDown 0.2s ease-out;
+  
+  @keyframes slideDown {
+    from {
+      opacity: 0;
+      transform: translateY(-8px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+  
+  /* Estilização da scrollbar */
+  &::-webkit-scrollbar {
+    width: 8px;
+  }
+ 
+  &::-webkit-scrollbar-track {
+    background: transparent;
+  }
+ 
+  &::-webkit-scrollbar-thumb {
+    background: ${props => props.theme['gray-300']};
+    border-radius: 4px;
+  }
+ 
+  &::-webkit-scrollbar-thumb:hover {
+    background: ${props => props.theme['gray-400']};
+  }
+`;
+ 
+// Item individual na lista de resultados 
+export const SearchResultItem = styled.li`
+  padding: 12px 16px;
+  cursor: pointer;
+  border-radius: 8px;
+  color: ${props => props.theme.title};
+  font-weight: 500;
+  transition: all 0.2s ease;
+  position: relative;
+  
+  /* Barra lateral que aparece no hover */
+  &::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    width: 3px;
+    background: ${props => props.theme.button};
+    border-radius: 0 2px 2px 0;
+    transform: scaleY(0);
+    transition: transform 0.2s ease;
+  }
+ 
+  &:hover {
+    background-color: ${props => props.theme['gray-100']};
+    padding-left: 20px;
+    
+    &::before {
+      transform: scaleY(1);
+    }
+  }
+  
+  &:active {
+    background-color: ${props => props.theme['gray-100']};
+  }
+`;
+ 
+// Mensagem de erro 
+export const ErrorMessage = styled.span`
+  font-size: 0.85em;
+  margin-top: 8px;
+  color: ${props => props.theme['red-500'] || '#ef4444'};
+  font-weight: 600;
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  padding-left: 4px;
+  
+  /* Ícone de alerta */
+  &::before {
+    content: '⚠';
+    font-size: 1.1em;
+  }
+`;
+ 
+// Botão de submissão
+export const SubmitButton = styled.button`
+  padding: 16px 40px;
+  font-size: 1.05em;
+  font-weight: 700;
+  color: ${props => props.theme.white};
+  background: linear-gradient(135deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.button} 100%);
+  border: none;
+  border-radius: 12px;
+  cursor: pointer;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  margin-top: 16px;
+  box-shadow: 0 4px 16px ${props => props.theme.button}40;
+  position: relative;
+  overflow: hidden;
+  
+  /* Efeito de brilho deslizante */
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -100%;
+    width: 100%;
+    height: 100%;
+    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
+    transition: left 0.5s;
+  }
+  
+  &:hover::before {
+    left: 100%;
+  }
+ 
+  &:hover {
+    transform: translateY(-3px);
+    box-shadow: 0 8px 24px ${props => props.theme.button}50;
+  }
+  
+  &:active {
+    transform: translateY(-1px);
+  }
+  
+  &:disabled {
+    opacity: 0.6;
+    cursor: not-allowed;
+    transform: none;
+    box-shadow: 0 2px 8px ${props => props.theme.button}20;
+    
+    &:hover {
+      transform: none;
+    }
+  }
+`;
+ 
+// Estilo para o campo de texto de várias linhas (Descrição)
+export const TextArea = styled.textarea`
+  width: 100%;
+  padding: 16px 20px;
+  font-size: 1em;
+  font-family: inherit;
+  line-height: 1.6;
+  
+  background-color: ${props => props.theme['gray-100']};
+  border: 2px solid transparent;
+  border-radius: 12px;
+  color: ${props => props.theme.title};
+  box-sizing: border-box;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  resize: vertical;
+  min-height: 150px;
+  font-weight: 500;
+ 
+  &::placeholder {
+    color: ${props => props.theme.placeholder};
+    font-weight: 400;
+  }
+  
+  &:hover {
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.placeholder}40;
+  }
+  
+  &:focus {
+    outline: none;
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.button};
+    box-shadow: 0 0 0 4px ${props => props.theme.button}15,
+                0 2px 8px rgba(0, 0, 0, 0.04);
+    transform: translateY(-1px);
+  }
+  
+  /* Estilização da scrollbar */
+  &::-webkit-scrollbar {
+    width: 10px;
+  }
+ 
+  &::-webkit-scrollbar-track {
+    background: ${props => props.theme['gray-100']};
+    border-radius: 0 10px 10px 0;
+  }
+ 
+  &::-webkit-scrollbar-thumb {
+    background: ${props => props.theme['gray-300']};
+    border-radius: 10px;
+  }
+ 
+  &::-webkit-scrollbar-thumb:hover {
+    background: ${props => props.theme.button};
+  }
+`;
+ 
+// Contador de caracteres
+export const CharacterCount = styled.div`
+  text-align: right;
+  font-size: 0.85em;
+  color: ${props => props.theme['gray-500'] || props.theme.placeholder};
+  margin-top: 6px;
+  margin-right: 4px;
+  font-weight: 600;
+  padding: 4px 8px;
+  background: ${props => props.theme['gray-100']};
+  border-radius: 6px;
+  display: inline-block;
+  float: right;
+  
+  /* Muda de cor quando próximo do limite */
+  &[data-warning="true"] {
+    color: ${props => props.theme['yellow-600'] || '#d97706'};
+    background: ${props => props.theme['yellow-50'] || '#fef3c7'};
+  }
+  
+  &[data-limit="true"] {
+    color: ${props => props.theme['red-500'] || '#ef4444'};
+    background: ${props =>  '#fee2e2'};
+  }
+`;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/domain/Postcard/index.html b/frontend/coverage/lcov-report/src/components/domain/Postcard/index.html new file mode 100644 index 0000000..033cc09 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/domain/Postcard/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/domain/Postcard + + + + + + + + + +
+
+

All files src/components/domain/Postcard

+
+ +
+ 69.23% + Statements + 72/104 +
+ + +
+ 58.9% + Branches + 43/73 +
+ + +
+ 64.28% + Functions + 18/28 +
+ + +
+ 72.16% + Lines + 70/97 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
69.23%72/10458.9%43/7364.28%18/2872.16%70/97
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/domain/Postcard/index.tsx.html b/frontend/coverage/lcov-report/src/components/domain/Postcard/index.tsx.html new file mode 100644 index 0000000..5c76ebb --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/domain/Postcard/index.tsx.html @@ -0,0 +1,1132 @@ + + + + + + Code coverage report for src/components/domain/Postcard/index.tsx + + + + + + + + + +
+
+

All files / src/components/domain/Postcard index.tsx

+
+ +
+ 69.23% + Statements + 72/104 +
+ + +
+ 58.9% + Branches + 43/73 +
+ + +
+ 64.28% + Functions + 18/28 +
+ + +
+ 72.16% + Lines + 70/97 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +21x +  +  +  +  +  +  +1x +12x +  +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +21x +21x +21x +21x +21x +  +  +21x +21x +21x +21x +21x +  +21x +  +21x +  +21x +10x +2x +  +  +  +  +2x +2x +2x +  +  +  +  +  +  +21x +  +  +  +  +  +13x +4x +  +13x +13x +  +  +  +21x +1x +  +1x +1x +  +  +  +  +  +21x +2x +2x +  +2x +  +2x +  +  +2x +1x +  +  +1x +1x +  +  +1x +  +  +  +21x +1x +  +1x +  +  +  +  +1x +  +1x +1x +1x +  +1x +1x +1x +  +  +  +  +  +  +1x +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +12x +  +  +12x +  +  +12x +  +  +  +  +  +  +12x +  +  +  +  +  +  +  +  +21x +1x +  +  +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import React, { useState, useRef, useEffect } from 'react';
+import * as S from './styles';
+import * as D from '../../common/Dropdown/styles'; 
+import { useNavigate } from 'react-router-dom'; 
+import type { ProjectProps } from '../../../API/Project';
+import { DeleteProject } from '../../../API/Project';
+import Modal from '../../common/Modal';
+import type { NotificationState } from '../../common/Toast';
+import Toast from '../../common/Toast';
+import * as ModalS from '../../common/Modal/styles';
+import { CreateComment, GetComments, DeleteComment } from '../../../API/Comment';
+import type { CommentProps } from '../../../API/Comment';
+import { useAuth } from '../../../API/AuthContext';
+ 
+const TrashIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <polyline points="3 6 5 6 21 6"></polyline>
+    <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
+  </svg>
+);
+ 
+// Ícone de Comentário (Balão)
+const CommentIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/>
+  </svg>
+);
+ 
+ 
+// --- Ícone de Menu (Ellipsis) ---
+const EllipsisIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" />
+  </svg>
+);
+ 
+interface PostcardProps {
+  post: ProjectProps; 
+  showMenu: boolean;         // Verifica se o menu deve ser mostrado (se é dono do post)
+  onDelete?: (id: string) => Promise<void>; 
+  deleteLabel?: string;
+}
+ 
+// --- Componente Postcard ---
+export default function Postcard({ post, showMenu, onDelete, deleteLabel = 'Projeto' }: PostcardProps) {
+  const { currentUser } = useAuth();
+ 
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+  const menuRef = useRef<HTMLDivElement>(null);
+  const navigate = useNavigate(); // Inicialize o hook de navegação
+  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); // Estado para o modal de exclusão
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+  // Estados para o formulário de comentário
+  const [isCommentBoxOpen, setIsCommentBoxOpen] = useState(false);
+  const [commentText, setCommentText] = useState("");
+  const [isSubmittingComment, setIsSubmittingComment] = useState(false);
+  const MAX_COMMENT_CHARS = 500;
+  const [comments, setComments] = useState<CommentProps[]>([]);
+ 
+  const [commentToDelete, setCommentToDelete] = useState<string | null>(null);
+ 
+  const projectId = (post as any).id || (post as any).projectID;
+ 
+  useEffect(() => {
+    if (isCommentBoxOpen && projectId) {
+        loadComments();
+    }
+  }, [isCommentBoxOpen, projectId]);
+ 
+  async function loadComments() {
+      try {
+          const data = await GetComments(projectId);
+          setComments(data);
+      } catch (error) {
+          console.error("Erro ao carregar comentários", error);
+      }
+  }
+ 
+  // Lógica para fechar o menu ao clicar fora (sem alterações)
+  useEffect(() => {
+    function handleClickOutside(event: MouseEvent) {
+      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
+        setIsMenuOpen(false);
+      }
+    }
+    if (isMenuOpen) {
+      document.addEventListener('mousedown', handleClickOutside);
+    }
+    return () => {
+      document.removeEventListener('mousedown', handleClickOutside);
+    };
+  }, [isMenuOpen]);
+ 
+  const handleEditClick = () => {
+    const projectId = (post as any).id || (post as any).projectID;
+    
+    if (projectId) {
+        navigate(`/editProject/${projectId}`, { state: { projectToEdit: post } });
+    } else E{
+        console.error("Erro: ID do projeto não encontrado no objeto:", post);
+    }
+  };
+ 
+  const handleDeleteMainItem = async () => {
+    try {
+       const id = (post as any).id || (post as any).projectID || (post as any).commentID;
+       
+       Iif (!id) throw new Error("ID não encontrado.");
+ 
+       Iif (onDelete) {
+           await onDelete(id);
+       } else {
+           await DeleteProject(id);
+           setTimeout(() => navigate('/feed'), 1000);
+       }
+       
+       setNotification({ message: `${deleteLabel} excluído com sucesso!`, type: 'success' });
+       setIsDeleteModalOpen(false);
+ 
+    } catch (error) {
+      setNotification({ message: `Erro ao excluir ${deleteLabel?.toLowerCase()}.`, type: 'error' });
+    }
+  };
+ 
+  const handleCommentSubmit = async (e: React.FormEvent) => {
+    e.preventDefault();
+    
+    Iif (!projectId) {
+        setNotification({ message: 'Erro: Projeto sem ID.', type: 'error' });
+        return;
+    }
+ 
+    Iif (!commentText.trim()) return;
+ 
+    try {
+        setIsSubmittingComment(true);
+        await CreateComment(projectId, commentText);
+        
+        setNotification({ message: 'Comentário enviado!', type: 'success' });
+        setCommentText(""); // Limpa o campo
+        setIsCommentBoxOpen(false); 
+ 
+    } catch (error) {
+        if (error instanceof Error) {
+            setNotification({ message: error.message, type: 'error' });
+        }
+    } finally {
+        setIsSubmittingComment(false);
+    }
+  };
+ 
+  const handleConfirmDeleteInternalComment = async () => {
+    if (!commentToDelete) return;
+    try {
+        await DeleteComment(commentToDelete);
+        setNotification({ message: 'Comentário excluído.', type: 'success' });
+        setCommentToDelete(null); 
+        await loadComments(); 
+    } catch (error: any) {
+        setNotification({ message: error.message, type: 'error' });
+        setCommentToDelete(null);
+    }
+  };
+ 
+  const handleCardClick = (e: React.MouseEvent) => {
+    // Não navega se estiver na aba de comentários do perfil (deleteLabel 'Comentário')
+    Iif (deleteLabel !== 'Projeto') return;
+ 
+    // Não navega se o clique foi em um elemento interativo
+    const target = e.target as HTMLElement;
+    
+    // Verifica se clicou em botões, inputs, links ou no próprio menu
+    Eif (
+        target.closest('button') || 
+        target.closest('input') || 
+        target.closest('textarea') ||
+        target.closest('a') ||
+        target.closest(D.DropdownMenu as any) // Garante que itens do dropdown não disparem
+    ) {
+        return;
+    }
+ 
+    // Realiza a navegação
+    if (projectId) {
+        navigate(`/project/${projectId}`);
+    }
+  };
+ 
+  const formatDate = (dateString?: string) => {
+      Eif (!dateString) return "";
+      return new Date(dateString).toLocaleDateString('pt-BR', {
+          day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit'
+      });
+  };
+ 
+  return (
+    <S.PostCardWrapper onClick={handleCardClick}>
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+      
+      <S.PostHeader>
+        <img src={(post as any).avatarUrl || 'url_placeholder_avatar.png'} alt={post.title} /> 
+        <span>{post.title}</span> 
+        <small>• {(post as any).author?.title || 'Autor'}</small> 
+      </S.PostHeader>
+ 
+      <S.PostContent>
+        {showMenu && (
+          <S.MenuWrapper ref={menuRef}>
+            <S.MenuButton onClick={() => setIsMenuOpen(prev => !prev)}>
+              <EllipsisIcon />
+            </S.MenuButton>
+ 
+            {isMenuOpen && (
+              <D.DropdownMenu>
+                {deleteLabel === 'Projeto' && (
+                    <D.MenuItem onClick={handleEditClick}>Editar</D.MenuItem>
+                )}
+                <D.DangerMenuItem onClick={() => {
+                    setIsMenuOpen(false);
+                    setIsDeleteModalOpen(true);}}>
+                    Excluir
+                </D.DangerMenuItem>
+              </D.DropdownMenu>
+            )}
+          </S.MenuWrapper>
+        )}
+ 
+        <p>{post.description}</p>
+ 
+        <S.ActionRow>
+            <S.ActionButton onClick={() => setIsCommentBoxOpen(!isCommentBoxOpen)}>
+                <CommentIcon />
+                <span>Comentar</span>
+            </S.ActionButton>
+        </S.ActionRow>
+ 
+        {isCommentBoxOpen && (
+            <>
+                <S.CommentForm onSubmit={handleCommentSubmit}>
+                    <S.CommentTextArea 
+                        placeholder="Escreva seu comentário..."
+                        value={commentText}
+                        onChange={(e) => setCommentText(e.target.value)}
+                        maxLength={MAX_COMMENT_CHARS}
+                        disabled={isSubmittingComment}
+                    />
+                    <S.CommentFooter>
+                        <S.CharacterCount isLimit={commentText.length >= MAX_COMMENT_CHARS}>
+                            {commentText.length} / {MAX_COMMENT_CHARS}
+                        </S.CharacterCount>
+                        <S.SubmitCommentButton 
+                            type="submit" 
+                            disabled={isSubmittingComment || !commentText.trim()}
+                        >
+                            {isSubmittingComment ? 'Enviando...' : 'Enviar'}
+                        </S.SubmitCommentButton>
+                    </S.CommentFooter>
+                </S.CommentForm>
+ 
+                {/* LISTA DE COMENTÁRIOS */}
+                {comments.length > 0 && (
+                    <S.CommentsSection>
+                        {comments.map((comment) => {
+                            // Verifica se o usuário atual é o autor do comentário
+                            const isAuthor = currentUser?.id && String(currentUser.id) === String(comment.authorID);
+ 
+                            return (
+                                <S.CommentItem key={comment.commentID || Math.random()}>
+                                    <S.CommentAvatar /> 
+                                    <S.CommentBubble>
+                                        <S.CommentHeader>
+                                            <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
+                                                <strong>{comment.username || "Usuário"}</strong>
+                                                <span>{formatDate(comment.createdAt)}</span>
+                                            </div>
+                                            
+                                            {/* Botão de Deletar (Só aparece para o dono) */}
+                                            {isAuthor && (
+                                                <S.DeleteCommentButton 
+                                                    onClick={() => setCommentToDelete(comment.commentID!)}
+                                                    title="Excluir comentário"
+                                                >
+                                                    <TrashIcon />
+                                                </S.DeleteCommentButton>
+                                            )}
+                                        </S.CommentHeader>
+                                        <S.CommentText>{comment.content}</S.CommentText>
+                                    </S.CommentBubble>
+                                </S.CommentItem>
+                            );
+                        })}
+                    </S.CommentsSection>
+                )}
+            </>
+        )}
+ 
+      </S.PostContent>
+      <Modal 
+        isOpen={isDeleteModalOpen} 
+        onClose={() => setIsDeleteModalOpen(false)}
+        title={`Excluir ${deleteLabel}`}
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Tem certeza que deseja excluir este {deleteLabel?.toLowerCase()}?
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton onClick={() => setIsDeleteModalOpen(false)}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton onClick={handleDeleteMainItem} style={{ backgroundColor: '#e74c3c' }}>
+                    Excluir
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+ 
+      <Modal 
+        isOpen={!!commentToDelete} 
+        onClose={() => setCommentToDelete(null)}
+        title="Excluir Comentário"
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Deseja realmente apagar este comentário?
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton onClick={() => setCommentToDelete(null)}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton 
+                    onClick={handleConfirmDeleteInternalComment}
+                    style={{ backgroundColor: '#e74c3c' }}
+                >
+                    Excluir
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+ 
+    </S.PostCardWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/domain/Searchbar/index.html b/frontend/coverage/lcov-report/src/components/domain/Searchbar/index.html new file mode 100644 index 0000000..545b03d --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/domain/Searchbar/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/domain/Searchbar + + + + + + + + + +
+
+

All files src/components/domain/Searchbar

+
+ +
+ 91.07% + Statements + 51/56 +
+ + +
+ 83.33% + Branches + 30/36 +
+ + +
+ 78.94% + Functions + 15/19 +
+ + +
+ 90.9% + Lines + 50/55 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
91.07%51/5683.33%30/3678.94%15/1990.9%50/55
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/domain/Searchbar/index.tsx.html b/frontend/coverage/lcov-report/src/components/domain/Searchbar/index.tsx.html new file mode 100644 index 0000000..69d7e0e --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/domain/Searchbar/index.tsx.html @@ -0,0 +1,568 @@ + + + + + + Code coverage report for src/components/domain/Searchbar/index.tsx + + + + + + + + + +
+
+

All files / src/components/domain/Searchbar index.tsx

+
+ +
+ 91.07% + Statements + 51/56 +
+ + +
+ 83.33% + Branches + 30/36 +
+ + +
+ 78.94% + Functions + 15/19 +
+ + +
+ 90.9% + Lines + 50/55 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162  +  +  +  +  +  +  +  +  +  +  +47x +47x +  +47x +  +47x +47x +  +  +47x +47x +  +  +47x +47x +  +47x +6x +6x +6x +6x +  +6x +  +  +  +  +6x +6x +  +  +  +6x +  +  +  +  +  +47x +20x +8x +8x +8x +  +  +12x +  +  +12x +3x +  +  +  +  +  +12x +3x +  +  +  +12x +12x +  +  +  +  +47x +  +1x +1x +  +  +6x +6x +  +  +  +47x +1x +1x +1x +  +  +47x +1x +1x +1x +  +  +47x +  +47x +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import React, { useState, useEffect, useRef } from 'react';
+import { FiSearch } from 'react-icons/fi';
+import * as S from './styles';
+import { useNavigate } from 'react-router-dom';
+ 
+import { GetAllCommunities } from '../../../API/Community';
+import { GetFeedProjects } from '../../../API/Project';
+import type { CommunityProps } from '../../../API/Community';
+import type { ProjectProps } from '../../../API/Project';
+ 
+export default function Searchbar() {
+    const [query, setQuery] = useState('');
+    const navigate = useNavigate();
+ 
+    const wrapperRef = useRef<HTMLDivElement>(null);
+ 
+    const [isFocused, setIsFocused] = useState(false);
+    const [isLoading, setIsLoading] = useState(false);
+ 
+    // Dados brutos (cache local)
+    const [allCommunities, setAllCommunities] = useState<CommunityProps[]>([]);
+    const [allProjects, setAllProjects] = useState<ProjectProps[]>([]);
+ 
+    // Dados filtrados para exibição
+    const [filteredCommunities, setFilteredCommunities] = useState<CommunityProps[]>([]);
+    const [filteredProjects, setFilteredProjects] = useState<ProjectProps[]>([]);
+ 
+    const handleFocus = async () => {
+        setIsFocused(true);
+        Eif (allCommunities.length === 0 && allProjects.length === 0) {
+            setIsLoading(true);
+            try {
+                // Busca em paralelo
+                const [communitiesData, projectsData] = await Promise.all([
+                    GetAllCommunities().catch(() => []), // Se falhar, retorna array vazio
+                    GetFeedProjects().catch(() => [])
+                ]);
+                
+                setAllCommunities(communitiesData);
+                setAllProjects(projectsData);
+            } catch (error) {
+                console.error("Erro ao carregar dados para pesquisa", error);
+            } finally {
+                setIsLoading(false);
+            }
+        }
+    };
+ 
+    // Efeito para filtrar sempre que a query ou os dados mudarem
+    useEffect(() => {
+        if (!query.trim()) {
+            setFilteredCommunities([]);
+            setFilteredProjects([]);
+            return;
+        }
+ 
+        const lowerQuery = query.toLowerCase();
+ 
+        // Filtra Comunidades (pelo nome ou descrição ou tecnologias)
+        const filteredComms = allCommunities.filter(comm => 
+            comm.name.toLowerCase().includes(lowerQuery) ||
+            comm.description?.toLowerCase().includes(lowerQuery) ||
+            comm.technologies?.some(tech => tech.toLowerCase().includes(lowerQuery))
+        );
+ 
+        // Filtra Projetos (pelo título ou tecnologias)
+        const filteredProjs = allProjects.filter(proj => 
+            proj.title.toLowerCase().includes(lowerQuery) ||
+            proj.technologies?.some(tech => tech.toLowerCase().includes(lowerQuery))
+        );
+ 
+        setFilteredCommunities(filteredComms.slice(0, 5)); // Limita a 5 resultados
+        setFilteredProjects(filteredProjs.slice(0, 5));    // Limita a 5 resultados
+ 
+    }, [query, allCommunities, allProjects]);
+ 
+    // Fecha ao clicar fora
+    useEffect(() => {
+        function handleClickOutside(event: MouseEvent) {
+            Eif (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
+                setIsFocused(false);
+            }
+        }
+        document.addEventListener('mousedown', handleClickOutside);
+        return () => document.removeEventListener('mousedown', handleClickOutside);
+    }, []);
+ 
+    // Navegação
+    const handleNavigateToCommunity = (communityId: string) => {
+        navigate(`/r/${communityId}`);
+        setIsFocused(false);
+        setQuery('');
+    };
+ 
+    const handleNavigateToProject = (projectId: string) => {
+        navigate(`/project/${projectId}`); 
+        console.log("Navegar para projeto:", projectId);
+        setIsFocused(false);
+    };
+ 
+    const hasResults = filteredCommunities.length > 0 || filteredProjects.length > 0;
+ 
+    return (
+        <S.SearchWrapper ref={wrapperRef}>
+            <FiSearch size={20} />
+            <S.SearchInput
+                type="text"
+                placeholder="Busque comunidades e projetos..."
+                value={query}
+                onChange={(e) => setQuery(e.target.value)}
+                onFocus={handleFocus}
+            />
+ 
+            {/* Renderiza o dropdown apenas se estiver focado e houver texto */}
+            {isFocused && query.length > 0 && (
+                <S.ResultsDropdown>
+                    {isLoading ? (
+                        <S.NoResults>Carregando...</S.NoResults>
+                    ) : !hasResults ? (
+                        <S.NoResults>Nenhum resultado encontrado.</S.NoResults>
+                    ) : (
+                        <>
+                            {/* Seção de Comunidades */}
+                            {filteredCommunities.length > 0 && (
+                                <S.ResultSection>
+                                    <h4>Comunidades</h4>
+                                    {filteredCommunities.map(comm => (
+                                        <S.ResultItem 
+                                            key={comm.communityID} 
+                                            onClick={() => handleNavigateToCommunity(comm.communityID)}
+                                        >
+                                            <span>{comm.name}</span>
+                                            {/* Opcional: mostrar tecnologia principal */}
+                                            {comm.technologies?.[0] && <small>{comm.technologies[0]}</small>}
+                                        </S.ResultItem>
+                                    ))}
+                                </S.ResultSection>
+                            )}
+ 
+                            {/* Seção de Projetos */}
+                            {filteredProjects.length > 0 && (
+                                <S.ResultSection>
+                                    <h4>Projetos</h4>
+                                    {filteredProjects.map((proj: any) => (
+                                        <S.ResultItem 
+                                            key={proj.id || proj.projectID} 
+                                            onClick={() => handleNavigateToProject(proj.id || proj.projectID)}
+                                        >
+                                            <span>{proj.title}</span>
+                                            <small>por {proj.authorUsername || 'Usuário'}</small>
+                                        </S.ResultItem>
+                                    ))}
+                                </S.ResultSection>
+                            )}
+                        </>
+                    )}
+                </S.ResultsDropdown>
+            )}
+        </S.SearchWrapper>
+    );
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/domain/TagInput/index.html b/frontend/coverage/lcov-report/src/components/domain/TagInput/index.html new file mode 100644 index 0000000..31f8318 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/domain/TagInput/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/domain/TagInput + + + + + + + + + +
+
+

All files src/components/domain/TagInput

+
+ +
+ 94.28% + Statements + 33/35 +
+ + +
+ 76.19% + Branches + 16/21 +
+ + +
+ 92.85% + Functions + 13/14 +
+ + +
+ 93.93% + Lines + 31/33 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
94.28%33/3576.19%16/2192.85%13/1493.93%31/33
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/domain/TagInput/index.tsx.html b/frontend/coverage/lcov-report/src/components/domain/TagInput/index.tsx.html new file mode 100644 index 0000000..290c74a --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/domain/TagInput/index.tsx.html @@ -0,0 +1,418 @@ + + + + + + Code coverage report for src/components/domain/TagInput/index.tsx + + + + + + + + + +
+
+

All files / src/components/domain/TagInput index.tsx

+
+ +
+ 94.28% + Statements + 33/35 +
+ + +
+ 76.19% + Branches + 16/21 +
+ + +
+ 92.85% + Functions + 13/14 +
+ + +
+ 93.93% + Lines + 31/33 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +20x +20x +20x +  +20x +9x +3x +11x +  +  +3x +  +6x +  +  +  +  +20x +  +  +  +  +  +5x +5x +5x +  +  +  +  +20x +  +2x +1x +1x +  +1x +1x +1x +1x +1x +  +  +  +  +20x +2x +1x +  +  +20x +  +  +  +  +18x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  + 
import React, { useState, useEffect, useRef } from 'react';
+import * as S from '../CreationForm/styles'; 
+import { Keyword, KeywordContainer } from '../../common/Keyword';
+ 
+interface TagInputProps {
+  value: string[];
+  onChange: (value: string[]) => void;
+  
+  searchList: string[]; 
+  limit: number;         
+  placeholder: string;   
+}
+ 
+ 
+export default function TagInput({ 
+  value: selectedTags = [], 
+  onChange, 
+  searchList, 
+  limit,      
+  placeholder 
+}: TagInputProps) {
+  
+  const [searchQuery, setSearchQuery] = useState('');
+  const [searchResults, setSearchResults] = useState<string[]>([]);
+  const [error, setError] = useState('');
+  const wrapperRef = useRef<HTMLDivElement>(null);
+ 
+  useEffect(() => {
+    if (searchQuery.length > 0) {
+      const filtered = searchList.filter(item =>
+        item.toLowerCase().includes(searchQuery.toLowerCase()) &&
+        !selectedTags.includes(item) // Não mostra o que já foi selecionado
+      );
+      setSearchResults(filtered);
+    } else {
+      setSearchResults([]);
+    }
+  }, [searchQuery, selectedTags, searchList]); 
+ 
+  // Lógica para fechar a lista de resultados ao clicar fora
+  useEffect(() => {
+    function handleClickOutside(event: MouseEvent) {
+      if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
+        setSearchResults([]); // Fecha a lista
+      }
+    }
+    document.addEventListener('mousedown', handleClickOutside);
+    return () => {
+      document.removeEventListener('mousedown', handleClickOutside);
+    };
+  }, [wrapperRef]);
+ 
+  // Adiciona uma tag
+  const handleAddTag = (tag: string) => {
+    // Usa o 'limit' da prop
+    if (selectedTags.length >= limit) {
+      setError(`Limite de ${limit} itens atingido.`);
+      return;
+    }
+    Eif (!selectedTags.includes(tag)) {
+      onChange([...selectedTags, tag]); // Atualiza o react-hook-form
+      setSearchQuery(''); 
+      setSearchResults([]);
+      setError(''); 
+    }
+  };
+ 
+  // Remove uma tag
+  const handleRemoveTag = (tagToRemove: string) => {
+    onChange(selectedTags.filter(tag => tag !== tagToRemove));
+    setError(''); 
+  };
+ 
+  return (
+    <S.SearchWrapper ref={wrapperRef}>
+      {selectedTags.length > 0 && (
+        <KeywordContainer>
+          {selectedTags.map(tag => (
+            <Keyword 
+              key={tag} 
+              onRemove={() => handleRemoveTag(tag)}
+            >
+              {tag}
+            </Keyword>
+          ))}
+        </KeywordContainer>
+      )}
+      
+      <div style={{ height: selectedTags.length > 0 ? '12px' : '0' }} />
+ 
+      <S.Input
+        type="text"
+        placeholder={placeholder} 
+        value={searchQuery}
+        onChange={(e) => setSearchQuery(e.target.value)}
+        disabled={selectedTags.length >= limit} 
+      />
+ 
+      {searchResults.length > 0 && (
+        <S.SearchResultsList>
+          {searchResults.map(tag => (
+            <S.SearchResultItem key={tag} onClick={() => handleAddTag(tag)}>
+              {tag}
+            </S.SearchResultItem>
+          ))}
+        </S.SearchResultsList>
+      )}
+ 
+      {error && <S.ErrorMessage>{error}</S.ErrorMessage>}
+    </S.SearchWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/layout/Header/index.html b/frontend/coverage/lcov-report/src/components/layout/Header/index.html new file mode 100644 index 0000000..e17fdc4 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/layout/Header/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/layout/Header + + + + + + + + + +
+
+

All files src/components/layout/Header

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/layout/Header/index.tsx.html b/frontend/coverage/lcov-report/src/components/layout/Header/index.tsx.html new file mode 100644 index 0000000..8400417 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/layout/Header/index.tsx.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/components/layout/Header/index.tsx + + + + + + + + + +
+
+

All files / src/components/layout/Header index.tsx

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { FiPlus } from 'react-icons/fi';
+import Searchbar from '../../domain/Searchbar';
+import * as S from './styles';
+ 
+ 
+interface HeaderProps {
+    onCreateClick: () => void; 
+}
+ 
+export default function Header({ onCreateClick }: HeaderProps) {
+    return (
+        <S.HeaderContainer>
+            <S.SearchContainer>
+                <Searchbar />
+            </S.SearchContainer>
+ 
+            <S.ActionsContainer>
+                <S.CreateButton onClick={onCreateClick}> 
+                    <FiPlus size={20} />
+                    <span>Create</span>
+                </S.CreateButton>
+ 
+                <S.ProfileIcon to={`/profile`}> 
+                </S.ProfileIcon>
+            </S.ActionsContainer>
+        </S.HeaderContainer>
+    );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/layout/HeaderHome/index.html b/frontend/coverage/lcov-report/src/components/layout/HeaderHome/index.html new file mode 100644 index 0000000..a83a922 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/layout/HeaderHome/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/layout/HeaderHome + + + + + + + + + +
+
+

All files src/components/layout/HeaderHome

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/layout/HeaderHome/index.tsx.html b/frontend/coverage/lcov-report/src/components/layout/HeaderHome/index.tsx.html new file mode 100644 index 0000000..fedef8d --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/layout/HeaderHome/index.tsx.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for src/components/layout/HeaderHome/index.tsx + + + + + + + + + +
+
+

All files / src/components/layout/HeaderHome index.tsx

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import * as S from './styles';
+ 
+export default function HeaderHome() {
+    return (
+        <S.HeaderContainer>
+ 
+            <S.ActionsContainer>
+                <S.Button to="/login"> 
+                    Login
+                </S.Button>
+ 
+                <S.Button to="/register"> 
+                    Register
+                </S.Button>
+            </S.ActionsContainer>
+        </S.HeaderContainer>
+    );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/layout/Sidebar/index.html b/frontend/coverage/lcov-report/src/components/layout/Sidebar/index.html new file mode 100644 index 0000000..03f8991 --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/layout/Sidebar/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/layout/Sidebar + + + + + + + + + +
+
+

All files src/components/layout/Sidebar

+
+ +
+ 93.75% + Statements + 15/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 93.75% + Lines + 15/16 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
93.75%15/1675%3/4100%5/593.75%15/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/components/layout/Sidebar/index.tsx.html b/frontend/coverage/lcov-report/src/components/layout/Sidebar/index.tsx.html new file mode 100644 index 0000000..8cf5baa --- /dev/null +++ b/frontend/coverage/lcov-report/src/components/layout/Sidebar/index.tsx.html @@ -0,0 +1,298 @@ + + + + + + Code coverage report for src/components/layout/Sidebar/index.tsx + + + + + + + + + +
+
+

All files / src/components/layout/Sidebar index.tsx

+
+ +
+ 93.75% + Statements + 15/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 93.75% + Lines + 15/16 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +9x +9x +9x +  +9x +2x +  +  +9x +  +8x +8x +  +8x +8x +8x +  +  +  +  +  +  +8x +8x +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState } from 'react';
+import { FiHome, FiChevronDown } from 'react-icons/fi';
+import { GetUserCommunities } from '../../../API/Community';
+import * as S from './styles';
+import type { CommunityProps } from '../../../API/Community';
+import { useAuth } from '../../../API/AuthContext';
+import { useEffect } from 'react';
+ 
+export default function Sidebar() {
+    // Estado para controlar se a lista de comunidades está visível
+    const [isCommunitiesOpen, setIsCommunitiesOpen] = useState(true);
+    const { currentUser } = useAuth();
+    const [userCommunities, setUserCommunities] = useState<CommunityProps[]>([]);
+ 
+    const toggleCommunities = () => {
+        setIsCommunitiesOpen(!isCommunitiesOpen);
+    };
+ 
+      useEffect(() => {
+        // Função assíncrona para buscar todos os dados
+        const fetchCommunities = async () => {
+          try {;
+            
+            const apiUserCommunities = await GetUserCommunities();
+            console.log("Comunidades do usuário:", apiUserCommunities);
+            setUserCommunities(apiUserCommunities);
+    
+          } catch (error) {
+            console.error("Falha ao buscar comunidades:", error);
+          } 
+          
+        };
+        Eif(currentUser)
+          fetchCommunities();
+      }, [currentUser]); 
+ 
+    return (
+        <S.SidebarContainer>
+            <S.SidebarNav>
+                
+                <S.HomeLink to="/feed">
+                    <FiHome size={22} />
+                    <span>Home</span>
+                </S.HomeLink>
+ 
+                <S.CommunitiesHeader onClick={toggleCommunities} isOpen={isCommunitiesOpen}>
+                    <span>COMUNIDADES</span>
+                    <FiChevronDown size={20} />
+                </S.CommunitiesHeader>
+ 
+                {isCommunitiesOpen && (
+                    <S.CommunitiesList>
+                        {userCommunities.map((community) => (
+                            <S.CommunityLink
+                                to={`/r/${community.communityID}`}
+                                key={community.communityID}
+                            >
+                                <S.CommunityIcon
+                                    alt={`${community.name} icon`}
+                                />
+                                <span>{community.name}</span>
+                            </S.CommunityLink>
+                        ))}
+                    </S.CommunitiesList>
+                )}
+ 
+            </S.SidebarNav>
+        </S.SidebarContainer>
+    );
+}
+ 
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/index.html b/frontend/coverage/lcov-report/src/index.html new file mode 100644 index 0000000..f9962bb --- /dev/null +++ b/frontend/coverage/lcov-report/src/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
App.tsx +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/CommunityPage/index.html b/frontend/coverage/lcov-report/src/pages/CommunityPage/index.html new file mode 100644 index 0000000..afeec33 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/CommunityPage/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/pages/CommunityPage + + + + + + + + + +
+
+

All files src/pages/CommunityPage

+
+ +
+ 83.94% + Statements + 115/137 +
+ + +
+ 68.42% + Branches + 39/57 +
+ + +
+ 88.05% + Functions + 59/67 +
+ + +
+ 85.24% + Lines + 104/122 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
71.05%54/7658.13%25/4365.21%15/2373.13%49/67
styles.ts +
+
100%61/61100%14/14100%44/44100%55/55
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/CommunityPage/index.tsx.html b/frontend/coverage/lcov-report/src/pages/CommunityPage/index.tsx.html new file mode 100644 index 0000000..67fa26d --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/CommunityPage/index.tsx.html @@ -0,0 +1,838 @@ + + + + + + Code coverage report for src/pages/CommunityPage/index.tsx + + + + + + + + + +
+
+

All files / src/pages/CommunityPage index.tsx

+
+ +
+ 71.05% + Statements + 54/76 +
+ + +
+ 58.13% + Branches + 25/43 +
+ + +
+ 65.21% + Functions + 15/23 +
+ + +
+ 73.13% + Lines + 49/67 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +14x +  +14x +14x +14x +  +14x +14x +14x +  +14x +  +14x +  +4x +4x +4x +4x +4x +4x +  +  +  +  +4x +  +  +14x +  +  +  +  +  +6x +6x +  +  +14x +1x +  +1x +1x +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +14x +  +  +  +14x +1x +1x +1x +1x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +14x +1x +  +1x +1x +  +  +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +14x +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useParams, useNavigate } from 'react-router-dom';
+import Sidebar from '../../components/layout/Sidebar';
+import Postcard from '../../components/domain/Postcard';
+import * as S from './styles';
+import { FiMoreHorizontal } from 'react-icons/fi'; 
+import { useEffect, useState, useRef } from 'react';
+import { GetCommunityById, JoinCommunity, DeleteCommunity, LeaveCommunity } from '../../API/Community';
+import type { NotificationState } from '../../components/common/Toast';
+import Toast from '../../components/common/Toast';
+import type { CommunityProps } from '../../API/Community';
+import * as D from '../../components/common/Dropdown/styles';
+import Modal from '../../components/common/Modal';
+import * as ModalS from '../../components/common/Modal/styles';
+ 
+export default function CommunityPage() {
+  const { communityID } = useParams<{ communityID: string }>();
+  const navigate = useNavigate();
+ 
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+  const [community, setCommunity] = useState<any>(null);
+  const [posts, setPosts] = useState<any[]>([]);
+ 
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
+  const menuRef = useRef<HTMLDivElement>(null);
+ 
+  const [isLeaveModalOpen, setIsLeaveModalOpen] = useState(false);
+ 
+  useEffect(() => {
+    async function loadData() {
+        console.log("Carregando dados da comunidade para ID:", communityID);
+        Iif (!communityID) return;
+        try {
+            const data = await GetCommunityById(communityID);
+            setCommunity(data.community);
+            setPosts(data.posts);
+        } catch (error) {
+            console.error(error);
+        } 
+    }
+    loadData();
+  }, [communityID]);
+ 
+  useEffect(() => {
+    function handleClickOutside(event: MouseEvent) {
+      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
+        setIsMenuOpen(false);
+      }
+    }
+    if (isMenuOpen) document.addEventListener('mousedown', handleClickOutside);
+    return () => document.removeEventListener('mousedown', handleClickOutside);
+  }, [isMenuOpen]);
+ 
+  const handleJoin = async () => {
+    Iif (!community) return;
+ 
+    try {
+        await JoinCommunity(community.communityID);
+        
+        // Atualiza a interface após entrar na comunidade
+        setCommunity((prev: CommunityProps | null) => prev ? ({
+            ...prev,
+            isMember: true, // Esconde o botão
+            memberCount: (prev.memberCount || 0) + 1 // Atualiza o contador visualmente
+        }) : null);
+ 
+        setNotification({ message: 'Você entrou na comunidade!', type: 'success' });
+ 
+    } catch (error) {
+        if (error instanceof Error) {
+            setNotification({ message: error.message, type: 'error' });
+        }
+    }
+  };
+ 
+  const handleEdit = () => {
+    navigate('/editCommunity', { state: { communityToEdit: community } });
+  };
+ 
+  const handleDelete = async () => {
+    Iif (!community) return;
+    try {
+        await DeleteCommunity(community.communityID);
+        setNotification({ message: 'Comunidade excluída com sucesso.', type: 'success' });
+        setIsDeleteModalOpen(false);
+        
+        // Redireciona para home após excluir
+        setTimeout(() => {
+            navigate('/feed');
+        }, 1500);
+ 
+    } catch (error) {
+        if (error instanceof Error) {
+            setNotification({ message: error.message, type: 'error' });
+        }
+        setIsDeleteModalOpen(false);
+    }
+  };
+ 
+  const handleLeave = async () => {
+    Iif (!community) return;
+ 
+    try {
+        await LeaveCommunity(community.communityID);
+        
+        // Atualiza a interface otimisticamente
+        setCommunity((prev: CommunityProps | null) => prev ? ({
+            ...prev,
+            isMember: false, // O usuário não é mais membro
+            memberCount: Math.max((prev.memberCount || 0) - 1, 0) // Decrementa contador
+        }) : null);
+ 
+        setNotification({ message: 'Você saiu da comunidade.', type: 'success' });
+        setIsLeaveModalOpen(false); // Fecha o modal
+ 
+    } catch (error) {
+        if (error instanceof Error) {
+            setNotification({ message: error.message, type: 'error' });
+        }
+        setIsLeaveModalOpen(false);
+    }
+  };
+ 
+  if (!community) return <div>Comunidade não encontrada</div>;
+ 
+  return (
+    <S.PageWrapper>
+      <Sidebar />
+ 
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <S.MainContent>
+        <S.Banner />
+        
+        <S.HeaderContainer>
+          <S.Avatar /> 
+          <S.HeaderInfo>
+            <h1>{community.name}</h1>
+            <span>{community.memberCount} membros</span>
+          </S.HeaderInfo>
+ 
+          <S.HeaderActions>
+            {!community.isMember && (
+            <S.JoinButton onClick={handleJoin}>
+                Join
+            </S.JoinButton>
+            )}
+            {community.isMember && !community.isAdmin && (
+                <S.LeaveButton onClick={() => setIsLeaveModalOpen(true)}>
+                    Sair
+                </S.LeaveButton>
+            )}
+           {community.isAdmin && (
+                <S.MenuWrapper ref={menuRef}>
+                    <S.OptionsButton onClick={() => setIsMenuOpen(!isMenuOpen)}>
+                        <FiMoreHorizontal />
+                    </S.OptionsButton>
+ 
+                    {isMenuOpen && (
+                        <D.DropdownMenu>
+                            <D.MenuItem onClick={handleEdit}>
+                                Editar Comunidade
+                            </D.MenuItem>
+                            <D.Separator />
+                            <D.DangerMenuItem onClick={() => {
+                                setIsMenuOpen(false);
+                                setIsDeleteModalOpen(true);
+                            }}>
+                                Excluir Comunidade
+                            </D.DangerMenuItem>
+                        </D.DropdownMenu>
+                    )}
+                </S.MenuWrapper>
+            )}
+          </S.HeaderActions>
+        </S.HeaderContainer>
+ 
+        <S.ContentGrid>
+          <S.FeedColumn>
+            {posts.map(post => (
+              <S.FeedCardWrapper key={post.projectID || post.id}>
+                <Postcard post={post} showMenu={false} />
+              </S.FeedCardWrapper>
+            ))}
+          </S.FeedColumn>
+ 
+          <S.InfoSidebar>
+            <h3>DESCRIPTION</h3>
+            <p>{community.description}</p>
+ 
+            <h3>KEYWORDS</h3>
+            <S.KeywordsContainer>
+              {community.technologies?.map((keyword: string) => (
+                <S.KeywordTag key={keyword}>{keyword}</S.KeywordTag>
+              ))}
+            </S.KeywordsContainer>
+          </S.InfoSidebar>
+        </S.ContentGrid>
+      </S.MainContent>
+ 
+      <Modal 
+        isOpen={isDeleteModalOpen} 
+        onClose={() => setIsDeleteModalOpen(false)}
+        title="Excluir Comunidade"
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Tem certeza que deseja excluir a comunidade <strong>{community.name}</strong>?<br/>
+                Todos os posts e vínculos serão removidos.
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton onClick={() => setIsDeleteModalOpen(false)}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton onClick={handleDelete} style={{ backgroundColor: '#e74c3c' }}>
+                    Excluir
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+ 
+      <Modal 
+        isOpen={isLeaveModalOpen} 
+        onClose={() => setIsLeaveModalOpen(false)}
+        title="Sair da Comunidade"
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Tem certeza que deseja sair da comunidade <strong>{community.name}</strong>?
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton onClick={() => setIsLeaveModalOpen(false)}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton 
+                    onClick={handleLeave} 
+                    style={{ backgroundColor: '#e74c3c' }} // Botão vermelho
+                >
+                    Sair
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+    </S.PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/CommunityPage/styles.ts.html b/frontend/coverage/lcov-report/src/pages/CommunityPage/styles.ts.html new file mode 100644 index 0000000..a4dd44a --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/CommunityPage/styles.ts.html @@ -0,0 +1,1426 @@ + + + + + + Code coverage report for src/pages/CommunityPage/styles.ts + + + + + + + + + +
+
+

All files / src/pages/CommunityPage styles.ts

+
+ +
+ 100% + Statements + 61/61 +
+ + +
+ 100% + Branches + 14/14 +
+ + +
+ 100% + Functions + 44/44 +
+ + +
+ 100% + Lines + 55/55 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448  +  +1x +  +  +10x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +10x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +10x +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +3x +3x +3x +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +1x +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +4x +4x +4x +  +  +  +  +  +  +  +  +  +4x +4x +  +4x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +10x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +10x +10x +  +  +  +  +10x +  +  +  +  +10x +  +10x +  +  +  +1x +  +  +  +  + 
import styled from 'styled-components';
+ 
+export const PageWrapper = styled.div`
+  display: flex;
+  min-height: 100vh;
+  background: linear-gradient(135deg, ${props => props.theme.white} 0%, ${props => props.theme['gray-100'] || props.theme['gray-100']} 100%);
+`;
+ 
+export const MainContent = styled.main`
+  flex: 1;
+  margin-left: 250px;
+  display: flex;
+  flex-direction: column;
+  
+  animation: fadeIn 0.5s ease-out;
+  
+  @keyframes fadeIn {
+    from {
+      opacity: 0;
+    }
+    to {
+      opacity: 1;
+    }
+  }
+`;
+ 
+// --- Área do Topo (Banner + Avatar + Título) ---
+ 
+export const Banner = styled.div`
+  width: 100%;
+  height: 220px;
+  background: linear-gradient(135deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.placeholder} 100%);
+  position: relative;
+  overflow: hidden;
+  
+  /* Padrão decorativo com formas geométricas */
+  &::before {
+    content: '';
+    position: absolute;
+    top: -50%;
+    right: -10%;
+    width: 600px;
+    height: 600px;
+    background: radial-gradient(circle, rgba(255, 255, 255, 0.15) 0%, transparent 70%);
+    border-radius: 50%;
+  }
+  
+  &::after {
+    content: '';
+    position: absolute;
+    bottom: -30%;
+    left: -5%;
+    width: 400px;
+    height: 400px;
+    background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
+    border-radius: 50%;
+  }
+`;
+ 
+export const HeaderContainer = styled.div`
+  display: flex;
+  align-items: flex-end;
+  padding: 0 40px;
+  margin-top: -60px;
+  margin-bottom: 32px;
+  gap: 24px;
+  position: relative;
+  z-index: 2;
+  flex-wrap: wrap;
+  
+  animation: slideUp 0.6s ease-out;
+  
+  @keyframes slideUp {
+    from {
+      opacity: 0;
+      transform: translateY(30px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+`;
+ 
+export const Avatar = styled.div`
+  width: 130px;
+  height: 130px;
+  border-radius: 24px;
+  background: linear-gradient(135deg, ${props => props.theme.sidebar} 0%, ${props => props.theme.button} 100%);
+  border: 5px solid ${props => props.theme.white};
+  flex-shrink: 0;
+  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2),
+              0 4px 12px rgba(0, 0, 0, 0.15);
+  position: relative;
+  
+  /* Efeito de brilho */
+  &::after {
+    content: '';
+    position: absolute;
+    top: 15%;
+    left: 15%;
+    width: 35%;
+    height: 35%;
+    background: radial-gradient(circle, rgba(255, 255, 255, 0.4) 0%, transparent 70%);
+    border-radius: 50%;
+  }
+  
+  transition: transform 0.3s ease, box-shadow 0.3s ease;
+  
+  &:hover {
+    transform: scale(1.05) rotate(2deg);
+    box-shadow: 0 15px 40px rgba(0, 0, 0, 0.25),
+                0 6px 16px rgba(0, 0, 0, 0.2);
+  }
+`;
+ 
+export const HeaderInfo = styled.div`
+  display: flex;
+  flex-direction: column;
+  padding-bottom: 12px;
+  flex: 1;
+  gap: 14px;
+  min-width: 0;
+ 
+  h1 {
+    font-size: 2.8rem;
+    font-weight: 800;
+    color: ${props => props.theme.black};
+    margin: 0;
+    margin-bottom: 8px;
+    line-height: 1.1;
+    letter-spacing: -0.02em;
+    
+    background: linear-gradient(135deg, ${props => props.theme.white} 0%, ${props => props.theme.button} 100%);
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    background-clip: text;
+    
+    position: relative;
+    word-wrap: break-word;
+    overflow-wrap: break-word;
+    
+    /* Underline decorativo */
+    &::after {
+      content: '';
+      position: absolute;
+      bottom: -10px;
+      left: 0;
+      width: 80px;
+      height: 5px;
+      background: linear-gradient(90deg, ${props => props.theme.button} 0%, transparent 100%);
+      border-radius: 3px;
+    }
+  }
+ 
+  span {
+    color: ${props => props.theme['gray-600'] || props.theme['gray-500']};
+    font-size: 1rem;
+    font-weight: 600;
+    padding: 6px 14px;
+    background: ${props => props.theme['gray-100']};
+    border-radius: 20px;
+    width: fit-content;
+    display: flex;
+    align-items: center;
+    gap: 6px;
+    
+    /* Ícone decorativo */
+    &::before {
+      content: '👥';
+      font-size: 0.9em;
+    }
+  }
+`;
+ 
+export const HeaderActions = styled.div`
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  padding-bottom: 15px;
+`;
+ 
+export const JoinButton = styled.button`
+  padding: 12px 32px;
+  border-radius: 12px;
+  border: 2px solid ${props => props.theme.button};
+  background: ${props => props.theme.button};
+  color: ${props => props.theme.white};
+  font-weight: 700;
+  font-size: 1rem;
+  cursor: pointer;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  box-shadow: 0 4px 12px ${props => props.theme.button}40;
+  position: relative;
+  overflow: hidden;
+  
+  /* Efeito de brilho deslizante */
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -100%;
+    width: 100%;
+    height: 100%;
+    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
+    transition: left 0.5s;
+  }
+  
+  &:hover::before {
+    left: 100%;
+  }
+ 
+  &:hover {
+    transform: translateY(-3px);
+    box-shadow: 0 8px 20px ${props => props.theme.button}50;
+    background: ${props => props.theme['hover-button'] || props.theme.button};
+  }
+  
+  &:active {
+    transform: translateY(-1px);
+  }
+`;
+ 
+export const LeaveButton = styled.button`
+  padding: 12px 32px;
+  border-radius: 12px;
+  border: 2px solid ${props => props.theme['red-500']};
+  background: transparent;
+  color: ${props => props.theme['red-500']};
+  font-weight: 700;
+  font-size: 1rem;
+  cursor: pointer;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  position: relative;
+  overflow: hidden;
+ 
+  &::before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 0;
+    height: 0;
+    background: ${props => props.theme['red-500']};
+    border-radius: 50%;
+    transform: translate(-50%, -50%);
+    transition: width 0.4s, height 0.4s;
+    z-index: -1;
+  }
+ 
+  &:hover::before {
+    width: 300%;
+    height: 300%;
+  }
+ 
+  &:hover {
+    color: ${props => props.theme.white};
+    border-color: ${props => props.theme['red-500']};
+    box-shadow: 0 4px 16px ${props => props.theme['red-500']}40;
+    transform: translateY(-2px);
+  }
+  
+  &:active {
+    transform: translateY(0);
+  }
+  
+  > * {
+    position: relative;
+    z-index: 1;
+  }
+`;
+ 
+export const OptionsButton = styled.button`
+  width: 48px;
+  height: 48px;
+  border-radius: 12px;
+  border: 2px solid ${props => props.theme.button};
+  background: ${props => props.theme.white};
+  color: ${props => props.theme.button};
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  font-size: 1.3rem;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ 
+  &:hover {
+    background-color: ${props => props.theme.button};
+    color: ${props => props.theme.white};
+    transform: scale(1.1) rotate(90deg);
+    box-shadow: 0 4px 16px ${props => props.theme.button}30;
+  }
+  
+  &:active {
+    transform: scale(1.05) rotate(90deg);
+  }
+`;
+ 
+// --- Grid de Conteúdo (Feed + Info Lateral) ---
+ 
+export const ContentGrid = styled.div`
+  display: grid;
+  grid-template-columns: 1fr 340px;
+  gap: 28px;
+  padding: 0 40px 40px 40px;
+  max-width: 1400px;
+  width: 100%;
+  box-sizing: border-box;
+ 
+  @media (max-width: 900px) {
+    grid-template-columns: 1fr;
+  }
+`;
+ 
+export const FeedColumn = styled.div`
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  
+  animation: slideInLeft 0.5s ease-out;
+  
+  @keyframes slideInLeft {
+    from {
+      opacity: 0;
+      transform: translateX(-20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateX(0);
+    }
+  }
+`;
+ 
+export const FeedCardWrapper = styled.div`
+  background: linear-gradient(135deg, ${props => props.theme.background} 0%, ${props => props.theme['gray-100'] || props.theme.background} 100%);
+  border-radius: 18px;
+  padding: 10px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+  transition: all 0.3s ease;
+  
+  &:hover {
+    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
+    transform: translateY(-2px);
+  }
+`;
+ 
+// --- Sidebar de Informações (Direita) ---
+ 
+export const InfoSidebar = styled.aside`
+  background: ${props => props.theme.white};
+  border: 2px solid ${props => props.theme.button}25;
+  border-radius: 20px;
+  padding: 28px;
+  height: fit-content;
+  position: sticky;
+  top: 20px;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
+  overflow-wrap: break-word;
+  word-wrap: break-word;
+  word-break: break-word;
+  
+  animation: slideInRight 0.5s ease-out;
+  
+  @keyframes slideInRight {
+    from {
+      opacity: 0;
+      transform: translateX(20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateX(0);
+    }
+  }
+  
+  h3 {
+    color: ${props => props.theme.title};
+    font-size: 0.85rem;
+    font-weight: 800;
+    letter-spacing: 1.5px;
+    text-transform: uppercase;
+    margin-bottom: 16px;
+    margin-top: 28px;
+    position: relative;
+    padding-left: 12px;
+    
+    /* Barra lateral decorativa */
+    &::before {
+      content: '';
+      position: absolute;
+      left: 0;
+      top: 50%;
+      transform: translateY(-50%);
+      width: 4px;
+      height: 18px;
+      background: linear-gradient(180deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.button} 100%);
+      border-radius: 2px;
+    }
+  }
+ 
+  h3:first-child {
+    margin-top: 0;
+  }
+ 
+  p {
+    color: ${props => props.theme['gray-700'] || props.theme.black};
+    font-size: 0.95rem;
+    line-height: 1.7;
+    margin-bottom: 16px;
+    padding-left: 12px;
+    word-wrap: break-word;
+    overflow-wrap: break-word;
+    word-break: break-word;
+    white-space: pre-wrap;
+  }
+`;
+ 
+export const KeywordsContainer = styled.div`
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+  padding-left: 12px;
+`;
+ 
+export const KeywordTag = styled.span`
+  border: 2px solid ${props => props.theme.keyword};
+  color: ${props => props.theme.keyword};
+  border-radius: 10px;
+  padding: 8px 18px;
+  font-size: 0.85rem;
+  font-weight: 700;
+  background: ${props => props.theme.keyword}10;
+  transition: all 0.2s ease;
+  cursor: default;
+  
+  &:hover {
+    background: ${props => props.theme.keyword}20;
+    transform: translateY(-2px);
+    box-shadow: 0 4px 8px ${props => props.theme.keyword}20;
+  }
+`;
+ 
+export const MenuWrapper = styled.div`
+  position: relative;
+  display: flex;
+  align-items: center;
+  z-index: 10;
+`;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/CreateCommunity/index.html b/frontend/coverage/lcov-report/src/pages/CreateCommunity/index.html new file mode 100644 index 0000000..7b28d76 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/CreateCommunity/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/CreateCommunity + + + + + + + + + +
+
+

All files src/pages/CreateCommunity

+
+ +
+ 81.81% + Statements + 27/33 +
+ + +
+ 90.9% + Branches + 20/22 +
+ + +
+ 71.42% + Functions + 5/7 +
+ + +
+ 81.81% + Lines + 27/33 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
81.81%27/3390.9%20/2271.42%5/781.81%27/33
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/CreateCommunity/index.tsx.html b/frontend/coverage/lcov-report/src/pages/CreateCommunity/index.tsx.html new file mode 100644 index 0000000..8797a5d --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/CreateCommunity/index.tsx.html @@ -0,0 +1,502 @@ + + + + + + Code coverage report for src/pages/CreateCommunity/index.tsx + + + + + + + + + +
+
+

All files / src/pages/CreateCommunity index.tsx

+
+ +
+ 81.81% + Statements + 27/33 +
+ + +
+ 90.9% + Branches + 20/22 +
+ + +
+ 71.42% + Functions + 5/7 +
+ + +
+ 81.81% + Lines + 27/33 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +  +7x +7x +  +7x +  +  +  +  +  +  +  +  +  +7x +7x +7x +7x +7x +  +7x +  +2x +2x +2x +  +  +  +  +2x +  +  +7x +2x +2x +  +1x +1x +1x +  +  +1x +1x +1x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {useState, useEffect} from 'react';
+import { useNavigate, useLocation } from 'react-router-dom';
+import { useForm, Controller } from 'react-hook-form';
+import Sidebar from '../../components/layout/Sidebar';
+import { PageWrapper, ContentWrapper } from '../Feed/styles'; 
+import * as S from '../../components/domain/CreationForm/styles'; 
+import TagInput from '../../components/domain/TagInput';
+import type { NotificationState } from '../../components/common/Toast';
+import { GetKeywords } from '../../API/Keywords';
+import  Toast  from '../../components/common/Toast';
+import type { CommunityProps } from '../../API/Community';
+import { NewCommunity, UpdateCommunity } from '../../API/Community';
+ 
+export default function CreateCommunity() {
+  const navigate = useNavigate();
+  const location = useLocation();
+ 
+  const communityToEdit = location.state?.communityToEdit as CommunityProps | undefined;
+  const isEditMode = !!communityToEdit;
+  
+  const { register, handleSubmit, control, watch } = useForm<CommunityProps>({
+    // Preenche os valores iniciais com os dados da comunidade se estiver editando
+    defaultValues: {
+      communityID: communityToEdit?.communityID || "",
+      name: communityToEdit?.name || "",
+      description: communityToEdit?.description || "",
+      technologies: communityToEdit?.technologies || []
+    }
+  });
+ 
+  const descriptionValue = watch('description');
+  const descriptionLength = descriptionValue ? descriptionValue.length : 0;
+  const MAX_CHARS = 500;
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+  const [keywords, setKeywords] = useState<string[]>([]); 
+ 
+  useEffect(() => {
+      async function loadTechs() {
+        try {
+          const techsFromDB = await GetKeywords();
+          setKeywords(techsFromDB);
+        } catch (error) {
+          console.error("Falha ao carregar tecnologias:", error);
+        }
+      }
+      loadTechs();
+    }, []);
+ 
+  const onSubmit = (data: CommunityProps) => {
+    try{
+      if (isEditMode && communityToEdit) {
+        // --- MODO EDIÇÃO ---
+        console.log("Atualizando Comunidade:", communityToEdit.communityID, data);
+        UpdateCommunity(communityToEdit.communityID, data);
+        setNotification({ message: 'Comunidade atualizada com sucesso!', type: 'success' });
+      } else {
+        // --- MODO CRIAÇÃO ---
+        console.log("Criando Comunidade:", data);
+        NewCommunity(data);
+        setNotification({ message: 'Comunidade criada com sucesso!', type: 'success' });
+      }
+ 
+      setTimeout(() => {
+          navigate('/feed'); 
+      }, 1000);
+ 
+    } catch (error) {
+      console.error('Erro ao criar comunidade:', error);
+      if (error instanceof Error){
+        setNotification({ message: error.message, type: 'error' });
+      }
+    }
+    
+  };
+ 
+  return (
+    <PageWrapper>
+      <Sidebar />
+ 
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <ContentWrapper>
+        <S.FormContainer onSubmit={handleSubmit(onSubmit)}>
+ 
+          <h2>{isEditMode ? 'Editar Comunidade' : 'Criar Comunidade'}</h2>
+          
+          <S.InputGroup>
+            <S.Label htmlFor="name">Nome da Comunidade</S.Label>
+            <S.Input id="name" {...register('name', { required: true })} />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="description">Descrição do Projeto</S.Label>
+              <S.TextArea 
+                id="description"
+                placeholder="Descreva sua comunidade..."
+                maxLength={MAX_CHARS}
+                {...register('description', {
+                  maxLength: {
+                  value: MAX_CHARS,
+                  message: `A descrição não pode exceder ${MAX_CHARS} caracteres`
+                }
+                })}
+                />
+                <S.CharacterCount>
+                {descriptionLength} / {MAX_CHARS}
+                </S.CharacterCount>
+          </S.InputGroup>
+          
+          <S.InputGroup>
+            <S.Label htmlFor="keywords">Palavras-chave</S.Label>
+            
+            <Controller
+              name="technologies"
+              control={control}
+              render={({ field }) => (
+                <TagInput 
+                  value={field.value}
+                  onChange={field.onChange}
+                  searchList={keywords}
+                  limit={10} 
+                  placeholder="Adicione até 10 palavras-chave..."
+                />
+              )}
+            />
+          </S.InputGroup>
+ 
+          <S.SubmitButton type="submit">{isEditMode ? 'Salvar Alterações' : 'Criar Comunidade'}</S.SubmitButton>
+ 
+        </S.FormContainer>
+      </ContentWrapper>
+    </PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/CreateProject/index.html b/frontend/coverage/lcov-report/src/pages/CreateProject/index.html new file mode 100644 index 0000000..4fd7006 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/CreateProject/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/CreateProject + + + + + + + + + +
+
+

All files src/pages/CreateProject

+
+ +
+ 84.44% + Statements + 38/45 +
+ + +
+ 87.09% + Branches + 27/31 +
+ + +
+ 80% + Functions + 8/10 +
+ + +
+ 86.04% + Lines + 37/43 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
84.44%38/4587.09%27/3180%8/1086.04%37/43
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/CreateProject/index.tsx.html b/frontend/coverage/lcov-report/src/pages/CreateProject/index.tsx.html new file mode 100644 index 0000000..5b2fabb --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/CreateProject/index.tsx.html @@ -0,0 +1,703 @@ + + + + + + Code coverage report for src/pages/CreateProject/index.tsx + + + + + + + + + +
+
+

All files / src/pages/CreateProject index.tsx

+
+ +
+ 84.44% + Statements + 38/45 +
+ + +
+ 87.09% + Branches + 27/31 +
+ + +
+ 80% + Functions + 8/10 +
+ + +
+ 86.04% + Lines + 37/43 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +13x +13x +13x +  +13x +  +  +13x +  +13x +  +13x +  +  +  +13x +13x +6x +  +6x +6x +  +  +13x +  +  +  +  +  +  +  +  +  +  +13x +13x +13x +13x +  +  +13x +  +4x +4x +4x +  +  +  +  +4x +  +  +  +13x +  +2x +  +  +  +  +2x +2x +  +1x +1x +1x +  +  +1x +1x +1x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +13x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState, useEffect } from 'react';
+import { useForm, Controller } from 'react-hook-form';
+import Sidebar from '../../components/layout/Sidebar';
+import { PageWrapper, ContentWrapper } from '../Feed/styles'; 
+import * as S from '../../components/domain/CreationForm/styles'; 
+import TagInput from '../../components/domain/TagInput';
+import { IMaskInput } from 'react-imask';
+import { NewProject, UpdateProject } from '../../API/Project'; 
+import type { ProjectProps } from '../../API/Project';
+import  Toast  from '../../components/common/Toast';
+import { useNavigate, useLocation, useParams } from 'react-router-dom';
+import type { NotificationState } from '../../components/common/Toast';
+import { GetKeywords } from '../../API/Keywords';
+import { parseDate } from '../../API/Project';
+ 
+interface ProjectFormProps extends Omit<ProjectProps, 'startDate'> {
+  startDate: string; 
+}
+ 
+export default function CreateProject() {
+  const navigate = useNavigate();
+  const location = useLocation(); // Hook para ler o state
+  const [keywords, setKeywords] = useState<string[]>([]); 
+ 
+  const { projectId: paramId } = useParams<{ projectId?: string }>(); 
+ 
+  // Recupera o projeto do estado
+  const projectToEdit = location.state?.projectToEdit as (ProjectProps & { id?: string; projectID?: string }) | undefined;
+  // Define se é modo edição
+  const isEditMode = !!projectToEdit;
+ 
+  const validProjectId = projectToEdit?.id 
+                      || projectToEdit?.projectID 
+                      || (paramId !== 'undefined' ? paramId : undefined);
+ 
+  const formatDateToString = (date?: Date | string) => {
+    if (!date) return "";
+    const d = new Date(date);
+    // Verifica se é data válida
+    Iif (isNaN(d.getTime())) return "";
+    return d.toLocaleDateString('pt-BR'); // Retorna "20/11/2025"
+  };
+ 
+  const { register, handleSubmit, control, watch } = useForm<ProjectFormProps>({
+    // Preenche os valores padrão se estiver em modo de edição
+    defaultValues: {
+      title: projectToEdit?.title || "",
+      description: projectToEdit?.description || "",
+      technologies: projectToEdit?.technologies || [], 
+      status: projectToEdit?.status || "",
+      startDate: formatDateToString(projectToEdit?.startDate)
+    }
+  });
+ 
+  const descriptionValue = watch('description');
+  const descriptionLength = descriptionValue ? descriptionValue.length : 0;
+  const MAX_CHARS = 2500;
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+  // Carrega as tecnologias disponíveis do backend
+  useEffect(() => {
+    async function loadTechs() {
+      try {
+        const techsFromDB = await GetKeywords();
+        setKeywords(techsFromDB);
+      } catch (error) {
+        console.error("Falha ao carregar tecnologias:", error);
+      }
+    }
+    loadTechs();
+  }, []);
+ 
+  // Lida com CRIAR ou ATUALIZAR
+  const onSubmit = (data: ProjectFormProps) => {
+ 
+    const finalData: ProjectProps = {
+        ...data,
+        startDate: parseDate(data.startDate) 
+    };
+ 
+    try {
+      if (isEditMode && validProjectId) {
+        // MODO DE EDIÇÃO
+        console.log("Atualizando Projeto:", validProjectId, finalData);
+        UpdateProject(validProjectId, finalData); 
+        setNotification({ message: 'Projeto atualizado com sucesso!', type: 'success' });
+      } else {
+        // MODO DE CRIAÇÃO
+        console.log("Criando Projeto:", finalData);
+        NewProject(finalData); 
+        setNotification({ message: 'Projeto criado com sucesso!', type: 'success' });
+      }
+      
+      // Redireciona após o sucesso
+      setTimeout(() => {
+          navigate('/feed'); 
+      }, 1000);
+ 
+    } catch(error) {
+      console.error('Erro ao salvar projeto:', error);
+      if (error instanceof Error){
+        setNotification({ message: error.message, type: 'error' });
+      }
+    }
+  };
+ 
+  return (
+    <PageWrapper>
+      <Sidebar />
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <ContentWrapper>
+        <S.FormContainer onSubmit={handleSubmit(onSubmit)}>
+          
+          <h2>{isEditMode ? 'Editar Projeto' : 'Criar Projeto'}</h2>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="title">Nome do Projeto</S.Label>
+            <S.Input id="title" {...register('title', { required: true })} />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="description">Descrição do Projeto</S.Label>
+            <S.TextArea 
+              id="description"
+              placeholder="Descreva seu projeto..."
+              maxLength={MAX_CHARS}
+              {...register('description', {
+                maxLength: {
+                  value: MAX_CHARS,
+                  message: `A descrição não pode exceder ${MAX_CHARS} caracteres`
+                }
+              })}
+            />
+            <S.CharacterCount>
+              {descriptionLength} / {MAX_CHARS}
+            </S.CharacterCount>
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="startDate">Data de Início</S.Label>
+            <Controller
+              name="startDate"
+              control={control}
+              render={({ field: { onChange, value } }) => (
+                <S.Input
+                  as={IMaskInput}
+                  mask="00/00/0000"
+                  id="startDate"
+                  placeholder="DD/MM/AAAA"
+                  value={value} 
+                  onAccept={(value: string) => onChange(value)}
+                  disabled={isEditMode} 
+                />
+              )} 
+            />
+          </S.InputGroup>
+          
+          <S.InputGroup>
+            <S.Label htmlFor="technologies">Tecnologias (Palavras-chave)</S.Label>
+            <Controller
+              name="technologies"
+              control={control}
+              render={({ field }) => (
+                <TagInput 
+                  value={field.value}
+                  onChange={field.onChange}
+                  searchList={keywords}
+                  limit={6}
+                  placeholder="Adicione até 6 tecnologias..."
+                />
+              )}
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="status">Status</S.Label>
+            <S.SelectWrapper>
+              <S.Select 
+                id="status" 
+                {...register('status', { required: true })}
+                required 
+              >
+                <option value="" disabled>Selecione um status...</option>
+                <option value="em-andamento">Em andamento</option>
+                <option value="pausado">Pausado</option>
+                <option value="finalizado">Finalizado</option>
+              </S.Select>
+            </S.SelectWrapper>
+          </S.InputGroup>
+ 
+          {/* 10. Botão de submit dinâmico */}
+          <S.SubmitButton type="submit">
+            {isEditMode ? 'Atualizar Projeto' : 'Criar Projeto'}
+          </S.SubmitButton>
+ 
+        </S.FormContainer>
+      </ContentWrapper>
+    </PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/EditProfile/index.html b/frontend/coverage/lcov-report/src/pages/EditProfile/index.html new file mode 100644 index 0000000..0da85e0 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/EditProfile/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/EditProfile + + + + + + + + + +
+
+

All files src/pages/EditProfile

+
+ +
+ 87.09% + Statements + 27/31 +
+ + +
+ 55.55% + Branches + 10/18 +
+ + +
+ 66.66% + Functions + 4/6 +
+ + +
+ 93.1% + Lines + 27/29 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
87.09%27/3155.55%10/1866.66%4/693.1%27/29
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/EditProfile/index.tsx.html b/frontend/coverage/lcov-report/src/pages/EditProfile/index.tsx.html new file mode 100644 index 0000000..7851a34 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/EditProfile/index.tsx.html @@ -0,0 +1,460 @@ + + + + + + Code coverage report for src/pages/EditProfile/index.tsx + + + + + + + + + +
+
+

All files / src/pages/EditProfile index.tsx

+
+ +
+ 87.09% + Statements + 27/31 +
+ + +
+ 55.55% + Branches + 10/18 +
+ + +
+ 66.66% + Functions + 4/6 +
+ + +
+ 93.1% + Lines + 27/29 +
+ + +
+

+ 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 +123 +124 +125 +126  +  +  +  +  +  +  +  +  +  +  +  +  +8x +8x +8x +  +  +8x +3x +3x +3x +3x +  +  +8x +  +  +8x +3x +3x +3x +3x +3x +3x +  +  +  +8x +2x +2x +2x +  +1x +  +1x +  +  +1x +  +  +  +  +1x +1x +1x +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState, useEffect } from 'react';
+import { useForm } from 'react-hook-form';
+import { useNavigate } from 'react-router-dom';
+import Sidebar from '../../components/layout/Sidebar';
+import { PageWrapper, ContentWrapper } from '../Feed/styles';
+import * as S from '../../components/domain/CreationForm/styles'; 
+import Toast from '../../components/common/Toast';
+import type { NotificationState } from '../../components/common/Toast';
+import { useAuth } from '../../API/AuthContext';
+import { UpdateProfile } from '../../API/User';
+import type { UserProfileData } from '../../API/User';
+ 
+export default function EditProfile() {
+  const { currentUser, updateUser } = useAuth(); 
+  const navigate = useNavigate();
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+  // Formata a data para o input (YYYY-MM-DD) 
+const formatDateForInput = (dateString?: string) => {
+  Iif (!dateString) return "";
+  const date = new Date(dateString);
+  Iif (isNaN(date.getTime())) return "";
+  return date.toISOString().split('T')[0];
+};
+ 
+  const { register, handleSubmit, setValue } = useForm<UserProfileData>();
+ 
+  // Preenche o formulário com os dados atuais
+  useEffect(() => {
+    Eif (currentUser) {
+      setValue('nomeCompleto', currentUser.nomeCompleto || '');
+      setValue('username', currentUser.username || '');
+      setValue('email', currentUser.email || '');
+      setValue('telefone', (currentUser as any).phone || ''); 
+      setValue('dataNascimento', formatDateForInput((currentUser as any).birthDate)); 
+    }
+  }, [currentUser, setValue]);
+ 
+  const onSubmit = async (data: UserProfileData) => {
+    try {
+      console.log("Atualizando perfil:", data);
+      await UpdateProfile(data);
+      
+      setNotification({ message: 'Perfil atualizado com sucesso!', type: 'success' });
+      
+      updateUser(data);
+ 
+      // Redireciona
+      setTimeout(() => {
+          navigate('/profile');
+      }, 1000);
+ 
+    } catch (error) {
+      console.error(error);
+      Eif (error instanceof Error) {
+        setNotification({ message: error.message, type: 'error' });
+      }
+    }
+  };
+ 
+  return (
+    <PageWrapper>
+      <Sidebar />
+      {notification && (
+        <Toast 
+            message={notification.message} 
+            type={notification.type} 
+            onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <ContentWrapper>
+        <S.FormContainer onSubmit={handleSubmit(onSubmit)}>
+          <h2>Editar Perfil</h2>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="nomeCompleto">Nome Completo</S.Label>
+            <S.Input 
+                id="nomeCompleto" 
+                {...register('nomeCompleto', { required: true })} 
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="username">Nome de Usuário</S.Label>
+            <S.Input 
+                id="username" 
+                {...register('username', { required: true })} 
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="email">Email</S.Label>
+            <S.Input 
+                id="email" 
+                type="email"
+                {...register('email', { required: true })} 
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="telefone">Telefone</S.Label>
+            <S.Input 
+                id="telefone" 
+                {...register('telefone')} 
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="dataNascimento">Data de Nascimento</S.Label>
+            <S.Input 
+                id="dataNascimento" 
+                type="date"
+                {...register('dataNascimento')} 
+            />
+          </S.InputGroup>
+ 
+          <S.SubmitButton type="submit">
+            Salvar Alterações
+          </S.SubmitButton>
+ 
+        </S.FormContainer>
+      </ContentWrapper>
+    </PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Feed/index.html b/frontend/coverage/lcov-report/src/pages/Feed/index.html new file mode 100644 index 0000000..a712d82 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Feed/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/pages/Feed + + + + + + + + + +
+
+

All files src/pages/Feed

+
+ +
+ 86.27% + Statements + 44/51 +
+ + +
+ 69.23% + Branches + 9/13 +
+ + +
+ 74.07% + Functions + 20/27 +
+ + +
+ 87.75% + Lines + 43/49 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
92.3%24/2669.23%9/1377.77%7/992.3%24/26
styles.ts +
+
80%20/25100%0/072.22%13/1882.6%19/23
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Feed/index.tsx.html b/frontend/coverage/lcov-report/src/pages/Feed/index.tsx.html new file mode 100644 index 0000000..1f9c28e --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Feed/index.tsx.html @@ -0,0 +1,436 @@ + + + + + + Code coverage report for src/pages/Feed/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Feed index.tsx

+
+ +
+ 92.3% + Statements + 24/26 +
+ + +
+ 69.23% + Branches + 9/13 +
+ + +
+ 77.77% + Functions + 7/9 +
+ + +
+ 92.3% + Lines + 24/26 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +18x +18x +18x +18x +18x +  +18x +  +6x +6x +6x +5x +  +1x +1x +1x +  +  +6x +  +  +6x +  +  +18x +1x +1x +  +  +18x +1x +1x +  +  +18x +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState, useEffect } from 'react';
+import { useNavigate } from 'react-router-dom';
+import Modal from '../../components/common/Modal';
+import Postcard from '../../components/domain/Postcard';
+import Header from '../../components/layout/Header';
+import Sidebar from '../../components/layout/Sidebar';
+import * as S from './styles';
+import * as ModalS from '../../components/common/Modal/styles';
+import { GetFeedProjects } from '../../API/Project';
+import type { ProjectProps } from '../../API/Project';
+import Toast from '../../components/common/Toast'; 
+import type { NotificationState } from '../../components/common/Toast';
+ 
+export default function Feed() {
+    const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
+    const [isLoading, setIsLoading] = useState(true);
+    const navigate = useNavigate();
+    const [posts, setPosts] = useState<ProjectProps[]>([]);
+    const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+    useEffect(() => {
+        async function loadFeed() {
+            setIsLoading(true);
+            try {
+                const feedData = await GetFeedProjects();
+                setPosts(feedData || []);
+            } catch (error) {
+                console.error("Erro ao carregar feed:", error);
+                Eif (error instanceof Error) {
+                    setNotification({ message: "Não foi possível carregar o feed.", type: 'error' });
+                }
+            } finally {
+                setIsLoading(false);
+            }
+        }
+        loadFeed();
+    }, []);
+ 
+    const handleCreateProject = () => {
+        setIsCreateModalOpen(false);
+        navigate('/createProject');
+    };
+ 
+    const handleCreateCommunity = () => {
+        setIsCreateModalOpen(false);
+        navigate('/createCommunity');
+    };
+ 
+    return (
+        <S.PageWrapper>
+            {notification && (
+                <Toast 
+                    message={notification.message} 
+                    type={notification.type} 
+                    onClose={() => setNotification(null)} 
+                />
+            )}
+            
+            <Header onCreateClick={() => setIsCreateModalOpen(true)}/>
+            <Sidebar />
+ 
+            <S.ContentWrapper>
+                <S.FeedContainer>
+                    <S.PostList>
+                        {isLoading ? (
+                            <S.LoadingContainer>
+                                <div className="spinner"></div>
+                                <p>Carregando feed...</p>
+                            </S.LoadingContainer>
+                        ) : posts.length > 0 ? (
+                            posts.map((post, index) => (
+                                <Postcard 
+                                    key={(post as unknown as ProjectProps).id || (post as any).projectID || index} 
+                                    post={post} 
+                                    showMenu={false} 
+                                />
+                            ))
+                        ) : (
+                            <S.EmptyFeedMessage>
+                                <svg 
+                                    viewBox="0 0 24 24" 
+                                    fill="none" 
+                                    stroke="currentColor" 
+                                    strokeWidth="2"
+                                    strokeLinecap="round" 
+                                    strokeLinejoin="round"
+                                >
+                                    <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
+                                    <line x1="9" y1="9" x2="15" y2="15"/>
+                                    <line x1="15" y1="9" x2="9" y2="15"/>
+                                </svg>
+                                <h3>Nenhum post encontrado</h3>
+                                <p style={{ color: '#ccc', textAlign: 'center', marginTop: '20px' }}>
+                                    Nenhum post encontrado. Entre em comunidades para ver atualizações!
+                                </p>
+                            </S.EmptyFeedMessage>
+                        )}
+                    </S.PostList>
+                </S.FeedContainer>
+            </S.ContentWrapper>
+ 
+            <Modal 
+                isOpen={isCreateModalOpen} 
+                onClose={() => setIsCreateModalOpen(false)}
+                title="O que você deseja criar?"
+            >
+                <ModalS.ModalActions>
+                    <ModalS.ChoiceButton onClick={handleCreateProject}>
+                        Criar Projeto
+                    </ModalS.ChoiceButton>
+                    <ModalS.ChoiceButton onClick={handleCreateCommunity}>
+                        Criar Comunidade
+                    </ModalS.ChoiceButton>
+                </ModalS.ModalActions>
+            </Modal>
+        </S.PageWrapper>
+    );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Feed/styles.ts.html b/frontend/coverage/lcov-report/src/pages/Feed/styles.ts.html new file mode 100644 index 0000000..e060a2f --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Feed/styles.ts.html @@ -0,0 +1,709 @@ + + + + + + Code coverage report for src/pages/Feed/styles.ts + + + + + + + + + +
+
+

All files / src/pages/Feed styles.ts

+
+ +
+ 80% + Statements + 20/25 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 72.22% + Functions + 13/18 +
+ + +
+ 82.6% + Lines + 19/23 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209  +  +  +4x +44x +  +  +  +  +  +  +  +  +  +  +44x +44x +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +16x +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +10x +10x +  +  +  +  +  +  +  +  +  +10x +  +  + 
import styled from 'styled-components';
+ 
+// Wrapper para a página inteira
+export const PageWrapper = styled.div`
+    background: linear-gradient(135deg, ${props => props.theme['gray-100']} 0%, ${props => props.theme['gray-100']}f0 100%);
+    min-height: 100vh;
+    position: relative;
+    
+    &::before {
+        content: '';
+        position: fixed;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        background: radial-gradient(circle at 20% 50%, ${props => props.theme.keyword}08 0%, transparent 50%),
+                    radial-gradient(circle at 80% 80%, ${props => props.theme.button}08 0%, transparent 50%);
+        pointer-events: none;
+        z-index: 0;
+    }
+`;
+ 
+// Wrapper para o conteúdo principal
+export const ContentWrapper = styled.main`
+    margin-left: 250px; 
+    margin-top: 60px;  
+    padding: 32px 24px;
+    box-sizing: border-box;
+    position: relative;
+    z-index: 1;
+    animation: fadeIn 0.5s ease-out;
+ 
+    @keyframes fadeIn {
+        from {
+            opacity: 0;
+            transform: translateY(10px);
+        }
+        to {
+            opacity: 1;
+            transform: translateY(0);
+        }
+    }
+ 
+    @media (max-width: 768px) {
+        margin-left: 0;
+        padding: 20px 16px;
+    }
+`;
+ 
+// Container principal do feed com posts
+export const FeedContainer = styled.main`
+    width: 100%;
+    max-width: 800px; 
+    margin: 0 auto; 
+    background: ${props => props.theme.background};
+    backdrop-filter: blur(10px);
+    border-radius: 20px;
+    padding: 28px;
+    box-sizing: border-box;
+    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12),
+                0 2px 8px rgba(0, 0, 0, 0.08),
+                0 0 0 1px ${props => props.theme.placeholder}15;
+    position: relative;
+    transition: all 0.3s ease;
+ 
+    &::before {
+        content: '';
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        height: 3px;
+ 
+        background-size: 200% 100%;
+        border-radius: 20px 20px 0 0;
+        animation: gradientShift 3s ease infinite;
+    }
+ 
+    @keyframes gradientShift {
+        0%, 100% { background-position: 0% 50%; }
+        50% { background-position: 100% 50%; }
+    }
+ 
+    &:hover {
+        box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15),
+                    0 4px 12px rgba(0, 0, 0, 0.1),
+                    0 0 0 1px ${props => props.theme.placeholder}25;
+    }
+ 
+    @media (max-width: 768px) {
+        padding: 20px;
+        border-radius: 16px;
+    }
+`;
+ 
+// Lista que agrupa os posts
+export const PostList = styled.div`
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+    position: relative;
+ 
+    /* Animação de entrada para cada post */
+    & > * {
+        animation: slideInUp 0.4s ease-out backwards;
+    }
+ 
+    & > *:nth-child(1) { animation-delay: 0.05s; }
+    & > *:nth-child(2) { animation-delay: 0.1s; }
+    & > *:nth-child(3) { animation-delay: 0.15s; }
+    & > *:nth-child(4) { animation-delay: 0.2s; }
+    & > *:nth-child(5) { animation-delay: 0.25s; }
+    
+    @keyframes slideInUp {
+        from {
+            opacity: 0;
+            transform: translateY(20px);
+        }
+        to {
+            opacity: 1;
+            transform: translateY(0);
+        }
+    }
+`;
+ 
+// Mensagem de feed vazio
+export const EmptyFeedMessage = styled.div`
+    text-align: center;
+    padding: 60px 24px;
+    color: ${props => props.theme.placeholder};
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 16px;
+ 
+    svg {
+        width: 80px;
+        height: 80px;
+        opacity: 0.5;
+        margin-bottom: 8px;
+    }
+ 
+    h3 {
+        color: ${props => props.theme.subtitle};
+        font-size: 1.3rem;
+        font-weight: 600;
+        margin: 0 0 8px 0;
+    }
+ 
+    p {
+        color: ${props => props.theme.placeholder};
+        font-size: 0.95rem;
+        line-height: 1.5;
+        max-width: 400px;
+        margin: 0;
+    }
+`;
+ 
+// Header do feed 
+export const FeedHeader = styled.div`
+    margin-bottom: 24px;
+    padding-bottom: 20px;
+    border-bottom: 1px solid ${props => props.theme.placeholder}20;
+ 
+    h1 {
+        color: ${props => props.theme.white};
+        font-size: 1.8rem;
+        font-weight: 700;
+        margin: 0 0 8px 0;
+        background: linear-gradient(135deg, ${props => props.theme.white}, ${props => props.theme.subtitle});
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+        background-clip: text;
+    }
+ 
+    p {
+        color: ${props => props.theme.placeholder};
+        font-size: 0.9rem;
+        margin: 0;
+    }
+`;
+ 
+// Container para loading state
+export const LoadingContainer = styled.div`
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 60px 24px;
+    gap: 16px;
+ 
+    .spinner {
+        width: 40px;
+        height: 40px;
+        border: 3px solid ${props => props.theme.placeholder}30;
+        border-top-color: ${props => props.theme.keyword};
+        border-radius: 50%;
+        animation: spin 0.8s linear infinite;
+    }
+ 
+    @keyframes spin {
+        to { transform: rotate(360deg); }
+    }
+ 
+    p {
+        color: ${props => props.theme.placeholder};
+        font-size: 0.9rem;
+    }
+`;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Home/index.html b/frontend/coverage/lcov-report/src/pages/Home/index.html new file mode 100644 index 0000000..c3e5258 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Home/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/Home + + + + + + + + + +
+
+

All files src/pages/Home

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Home/index.tsx.html b/frontend/coverage/lcov-report/src/pages/Home/index.tsx.html new file mode 100644 index 0000000..77b1f50 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Home/index.tsx.html @@ -0,0 +1,124 @@ + + + + + + Code coverage report for src/pages/Home/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Home index.tsx

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +  +  +1x +  +  +  +  +  +  +  +  + 
import HeaderHome from '../../components/layout/HeaderHome';
+import * as S from './styles';
+ 
+export default function Home() {
+    return (
+        <S.HomePageContainer>
+            <HeaderHome />
+            <S.ContentWrapper>
+                <S.SiteTitle>CTable</S.SiteTitle>
+                <S.Tagline>Descubra, compartilhe, aprenda, converse: um novo mundo se abre para os amantes de computação.</S.Tagline>
+            </S.ContentWrapper>
+    </S.HomePageContainer>
+    );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Login/index.html b/frontend/coverage/lcov-report/src/pages/Login/index.html new file mode 100644 index 0000000..97a41f6 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Login/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/Login + + + + + + + + + +
+
+

All files src/pages/Login

+
+ +
+ 87.5% + Statements + 14/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 50% + Functions + 2/4 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
87.5%14/1675%3/450%2/487.5%14/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Login/index.tsx.html b/frontend/coverage/lcov-report/src/pages/Login/index.tsx.html new file mode 100644 index 0000000..ebca6fe --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Login/index.tsx.html @@ -0,0 +1,340 @@ + + + + + + Code coverage report for src/pages/Login/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Login index.tsx

+
+ +
+ 87.5% + Statements + 14/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 50% + Functions + 2/4 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +10x +  +10x +10x +  +  +2x +2x +2x +  +1x +  +  +1x +  +1x +  +  +  +  +1x +  +  +1x +1x +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {useState} from 'react';
+import {
+  FormPageContainer,
+  FormWrapper,
+  FormTitle,
+  StyledForm,
+  StyledInput,
+  SubmitButton,
+  RedirectLink
+} from '../../components/domain/Form/styles';
+import { useForm} from 'react-hook-form';
+import  Toast  from '../../components/common/Toast';
+import { useNavigate } from 'react-router-dom';
+import type { LoginProps } from '../../API/Auth';
+import { useAuth } from '../../API/AuthContext';
+import type { NotificationState } from '../../components/common/Toast';
+ 
+export default function LoginPage() {
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+  const { login } = useAuth();
+    
+  const { register, handleSubmit, formState: {isSubmitting} } = useForm<LoginProps>();
+  const navigate = useNavigate();
+  
+    async function onSubmit(data: LoginProps) {
+      console.log(data);
+      try{
+        await login(data);
+        
+        console.log('Usuário registrado com sucesso');
+        
+        // Define estado para mostrar notificação de sucesso
+        setNotification({ message: 'Usuário registrado com sucesso!', type: 'success' });
+    
+        setTimeout(() => {
+        navigate('/feed'); // Navega para a página de feed
+        }, 1000);
+        
+      } catch (error) { 
+        console.error('Erro ao registrar usuário:', error);
+        
+        // Define estado para mostrar notificação de erro
+        Eif (error instanceof Error){
+        setNotification({ message: error.message, type: 'error' });
+        }
+      } 
+  }
+ 
+  return (
+    <FormPageContainer>
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+      <FormWrapper>
+        <FormTitle>Login</FormTitle>
+        
+        <StyledForm onSubmit={handleSubmit(onSubmit)}>
+          <StyledInput 
+            type="text" 
+            placeholder="Email ou usuário" 
+            required 
+            {...register('username')}
+          />
+          <StyledInput 
+            type="password" 
+            placeholder="Senha" 
+            required 
+            {...register('senha')}
+          />
+          
+          <SubmitButton disabled = {isSubmitting} type="submit">Entrar</SubmitButton>
+        </StyledForm>
+ 
+        <RedirectLink>
+          Não tem uma conta? <a href="/register">Cadastre-se</a>
+        </RedirectLink>
+      </FormWrapper>
+    </FormPageContainer>
+  );
+}
+ 
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Profile/index.html b/frontend/coverage/lcov-report/src/pages/Profile/index.html new file mode 100644 index 0000000..7a9a57c --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Profile/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/pages/Profile + + + + + + + + + +
+
+

All files src/pages/Profile

+
+ +
+ 92.43% + Statements + 110/119 +
+ + +
+ 82.25% + Branches + 51/62 +
+ + +
+ 89.58% + Functions + 43/48 +
+ + +
+ 94.54% + Lines + 104/110 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
89.88%80/8971.05%27/3882.75%24/2992.85%78/84
styles.ts +
+
100%30/30100%24/24100%19/19100%26/26
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Profile/index.tsx.html b/frontend/coverage/lcov-report/src/pages/Profile/index.tsx.html new file mode 100644 index 0000000..92214fd --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Profile/index.tsx.html @@ -0,0 +1,931 @@ + + + + + + Code coverage report for src/pages/Profile/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Profile index.tsx

+
+ +
+ 89.88% + Statements + 80/89 +
+ + +
+ 71.05% + Branches + 27/38 +
+ + +
+ 82.75% + Functions + 24/29 +
+ + +
+ 92.85% + Lines + 78/84 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +40x +  +  +  +  +1x +40x +  +  +  +1x +40x +  +  +  +  +  +  +  +  +42x +42x +42x +42x +  +42x +  +  +42x +42x +  +42x +42x +42x +  +42x +  +40x +40x +40x +  +40x +40x +  +39x +  +39x +39x +  +  +1x +  +  +  +40x +40x +  +  +  +42x +  +1x +1x +  +  +25x +7x +  +25x +25x +  +  +  +42x +1x +1x +  +  +42x +1x +  +  +1x +1x +  +  +  +42x +1x +1x +  +  +42x +  +3x +3x +  +3x +3x +1x +  +1x +  +1x +  +  +  +  +  +2x +2x +1x +1x +1x +  +1x +  +1x +  +3x +3x +  +  +  +  +42x +42x +37x +35x +  +  +2x +2x +  +  +  +  +  +5x +  +5x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +42x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState, useRef, useEffect } from 'react';
+import Sidebar from '../../components/layout/Sidebar'; 
+import Postcard from '../../components/domain/Postcard'; 
+import * as S from './styles'; 
+import * as D from '../../components/common/Dropdown/styles';
+import type { ProjectProps } from '../../API/Project';
+import type { CommentProps } from '../../API/Comment';
+import { GetUserProjects } from '../../API/Project';
+import { GetUserComments, DeleteComment } from '../../API/Comment';
+import { useAuth } from '../../API/AuthContext';
+import { useNavigate } from 'react-router-dom';
+import { DeleteProfile } from '../../API/User';
+import Toast from '../../components/common/Toast';
+import Modal from '../../components/common/Modal';
+import * as ModalS from '../../components/common/Modal/styles';
+ 
+// --- ÍCONES ---
+const PostsIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
+    <polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><line x1="10" y1="9" x2="8" y2="9" />
+  </svg>
+);
+const CommentsIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
+  </svg>
+);
+const SettingsIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" />
+  </svg>
+);
+// -----------------------
+ 
+type ViewState = 'posts' | 'comments';
+ 
+export default function Profile() {
+  const { currentUser, logout } = useAuth();
+  const [view, setView] = useState<ViewState>('posts');
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+  const menuRef = useRef<HTMLDivElement>(null);
+ 
+  const navigate = useNavigate();
+ 
+  // Estados para os dados da API
+  const [userPosts, setUserPosts] = useState<ProjectProps[]>([]);
+  const [userComments, setUserComments] = useState<CommentProps[]>([]);
+ 
+  const [isDeleting, setIsDeleting] = useState(false);
+  const [isDeleteProfileModalOpen, setIsDeleteProfileModalOpen] = useState(false);
+  const [notification, setNotification] = useState<{message: string, type: 'success' | 'error'} | null>(null);
+ 
+  useEffect(() => {
+    // Função assíncrona para buscar todos os dados
+    console.log("Efeito de busca de dados do perfil disparado.");
+    const fetchProfileData = async () => {
+      try {;
+        
+        console.log("Usuário atual no Profile:", currentUser);
+        const apiUserPosts = await GetUserProjects();
+        
+        const apiUserComments: CommentProps[] = await GetUserComments();
+        
+        setUserPosts(apiUserPosts);
+        setUserComments(apiUserComments);
+ 
+      } catch (error) {
+        console.error("Falha ao buscar dados do perfil:", error);
+      } 
+      
+    };
+    Eif(currentUser)
+      fetchProfileData();
+  }, [currentUser]); 
+ 
+  // Lógica para fechar o menu ao clicar fora 
+  useEffect(() => {
+    function handleClickOutside(event: MouseEvent) {
+      Eif (menuRef.current && !menuRef.current.contains(event.target as Node)) {
+        setIsMenuOpen(false);
+      }
+    }
+    if (isMenuOpen) {
+      document.addEventListener('mousedown', handleClickOutside);
+    }
+    return () => {
+      document.removeEventListener('mousedown', handleClickOutside);
+    };
+  }, [isMenuOpen]);
+ 
+  const handleLogout = () => {
+    logout(); // Limpa o estado e o localStorage
+    navigate('/login'); // Redireciona para a tela de login
+  };
+ 
+  const handleDeleteComment = async (commentId: string) => {
+      await DeleteComment(commentId);
+      
+      // Remove o comentário deletado do estado local para sumir da tela instantaneamente
+      setUserComments((prevComments) => 
+          prevComments.filter(comment => comment.commentID !== commentId)
+      );
+  };
+ 
+  const handleEditProfile = () => {
+      setIsMenuOpen(false);
+      navigate('/editProfile');
+  };
+ 
+  const handleDeleteProfile = async () => {
+    
+    Iif (isDeleting) return;
+    setIsDeleting(true);
+ 
+      try {
+          await DeleteProfile();
+          setNotification({ message: "Perfil excluído com sucesso. Até logo!", type: 'success' });
+ 
+          setIsDeleteProfileModalOpen(false);
+          
+          setTimeout(() => {
+              logout(); // Desloga o usuário e limpa o storage
+              navigate('/login'); // Manda para login
+          }, 2000);
+ 
+      } catch (error) {
+          Eif (error instanceof Error) {
+              if (error.message.includes("não encontrado") || error.message.includes("not found")) {
+                  setNotification({ message: "Conta já encerrada. Redirecionando...", type: 'success' });
+                  setTimeout(() => { logout(); navigate('/login'); }, 2000);
+                  return;
+              }
+              setNotification({ message: error.message, type: 'error' });
+          }
+          setIsDeleteProfileModalOpen(false);
+      } finally {
+          setIsDeleting(false);
+          setIsDeleteProfileModalOpen(false);
+      }
+  };
+ 
+  // Função para renderizar o feed (posts ou comentários)
+  const renderFeed = () => {
+    if (view === 'posts') {
+      if (userPosts.length === 0) {
+        return <p style={{ color: '#fff', padding: '20px' }}>Nenhum projeto encontrado.</p>;
+      }
+ 
+     return userPosts.map((post, index) => (
+        <S.PostContainer key={index}>
+          <Postcard post={post} showMenu={true} />
+        </S.PostContainer>
+      ));
+    }
+ 
+    Eif (view === 'comments') {
+      // Mapeia 'userComments' 
+      return userComments.map(comment => (
+        <S.PostContainer key={comment.commentID || Math.random()}>
+          <Postcard 
+            post={{
+              id: comment.commentID,
+              title: `Comentou em: ${comment.projectTitle || 'Projeto'}`, 
+              description: comment.content, 
+              technologies: [],
+              status: '',
+              startDate: comment.createdAt,
+              // Passa o usuário atual como autor para o cabeçalho do card
+              author: { title: currentUser?.username || 'Você' } 
+            } as unknown as ProjectProps} 
+            showMenu={true} 
+            deleteLabel="Comentário"
+            onDelete={() => handleDeleteComment(comment.commentID!)}
+          />
+        </S.PostContainer>
+      ));
+    }
+ 
+    return null;
+  };
+ 
+  return (
+    <S.PageWrapper>
+      <Sidebar />
+ 
+      {notification && (
+        <Toast 
+            message={notification.message} 
+            type={notification.type} 
+            onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <S.ContentWrapper>
+ 
+        <S.ProfileHeader>
+            <S.ActionsWrapper ref={menuRef}>
+                <S.ProfileActions>
+                    <S.IconButton
+                        title="Ver publicações"
+                        $active={view === 'posts'}
+                        onClick={() => setView('posts')}
+                        >
+                        <PostsIcon />
+                    </S.IconButton>
+                    <S.IconButton
+                        title="Ver comentários"
+                        $active={view === 'comments'}
+                        onClick={() => setView('comments')}
+                        >
+                        <CommentsIcon />
+                    </S.IconButton>
+                    <S.IconButton
+                        title="Configurações"
+                        onClick={() => setIsMenuOpen(prev => !prev)}
+                        >
+                        <SettingsIcon />
+                    </S.IconButton>
+                </S.ProfileActions>
+ 
+                {isMenuOpen && (
+                <D.DropdownMenu>
+                    <D.MenuItem onClick={handleEditProfile}>Editar Perfil</D.MenuItem>
+                    <D.MenuItem onClick={handleLogout}>Sair</D.MenuItem>
+                    <D.Separator />
+                    <D.DangerMenuItem onClick={() => {
+                        setIsMenuOpen(false);
+                        setIsDeleteProfileModalOpen(true);
+                    }}>
+                        Excluir Perfil
+                    </D.DangerMenuItem>
+                </D.DropdownMenu>
+                )}
+ 
+            </S.ActionsWrapper>                
+        </S.ProfileHeader>
+        
+        <S.ProfileInfo>
+            <S.ProfileAvatar 
+              style={{ 
+                backgroundImage: undefined 
+              }} 
+            />
+            <S.Username>{currentUser?.username || 'Carregando...'}</S.Username>
+        </S.ProfileInfo>
+ 
+        <S.PostList>
+          {renderFeed()}
+        </S.PostList>
+        
+      </S.ContentWrapper>
+ 
+      <Modal 
+        isOpen={isDeleteProfileModalOpen} 
+        onClose={() => !isDeleting && setIsDeleteProfileModalOpen(false)}
+        title="Excluir Conta"
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Tem certeza que deseja excluir sua conta? <br/>
+                <strong>Todos os seus projetos, comunidades e comentários serão apagados permanentemente.</strong>
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton 
+                  onClick={() => setIsDeleteProfileModalOpen(false)}
+                  disabled={isDeleting}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton 
+                    onClick={handleDeleteProfile} 
+                    style={{ backgroundColor: '#e74c3c' }}
+                    disabled={isDeleting}
+                >
+                    {isDeleting ? 'Excluindo...' : 'Excluir Conta'}
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+ 
+    </S.PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Profile/styles.ts.html b/frontend/coverage/lcov-report/src/pages/Profile/styles.ts.html new file mode 100644 index 0000000..07d3824 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Profile/styles.ts.html @@ -0,0 +1,922 @@ + + + + + + Code coverage report for src/pages/Profile/styles.ts + + + + + + + + + +
+
+

All files / src/pages/Profile styles.ts

+
+ +
+ 100% + Statements + 30/30 +
+ + +
+ 100% + Branches + 24/24 +
+ + +
+ 100% + Functions + 19/19 +
+ + +
+ 100% + Lines + 26/26 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280  +  +  +1x +40x +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +40x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +40x +40x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +40x +  +  +40x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +40x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +120x +  +  +120x +  +  +  +120x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +120x +  +  +  +  +  +  +  +  +  +  +  +  +  +120x +  +  +120x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +120x +  +  +  +  +1x +  +  + 
import styled from 'styled-components';
+ 
+// Wrapper para a página inteira
+export const PageWrapper = styled.div`
+  background: linear-gradient(135deg, ${props => props.theme['gray-100']} 0%, ${props => props.theme['gray-100'] || props.theme['gray-100']} 100%);
+  min-height: 100vh;
+`;
+ 
+// Wrapper para o conteúdo principal
+export const ContentWrapper = styled.main`
+  margin-left: 250px; 
+  box-sizing: border-box;
+  padding-bottom: 60px;
+`;
+ 
+// Container principal com posts
+export const PostContainer = styled.main`
+    width: 100%;
+    max-width: 800px; 
+    margin: 0 auto; 
+    
+    background-color: ${props => props.theme.background};
+    border-radius: 16px;
+    padding: 24px;
+    box-sizing: border-box;
+    
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04),
+                0 1px 2px rgba(0, 0, 0, 0.06);
+    
+    transition: all 0.3s ease;
+    
+    &:hover {
+        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08),
+                    0 2px 4px rgba(0, 0, 0, 0.06);
+        transform: translateY(-2px);
+    }
+`;
+ 
+// Lista que agrupa os posts do perfil
+export const PostList = styled.div`
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  padding: 32px 24px;
+  
+  animation: fadeIn 0.4s ease-out;
+  
+  @keyframes fadeIn {
+    from {
+      opacity: 0;
+      transform: translateY(10px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+`;
+ 
+// Cabeçalho do perfil
+export const ProfileHeader = styled.header`
+  background: linear-gradient(135deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.button} 100%);
+  height: 160px;
+  position: relative;
+  z-index: 0;
+  
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+  
+  /* Padrão decorativo sutil */
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-image: 
+      radial-gradient(circle at 20% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
+      radial-gradient(circle at 80% 80%, rgba(255, 255, 255, 0.1) 0%, transparent 50%);
+    pointer-events: none;
+  }
+  
+  /* Posiciona os botões de ação */
+  display: flex;
+  justify-content: flex-end; 
+  align-items: flex-end; 
+  padding: 20px 32px; 
+`;
+ 
+// Container da foto + nome
+export const ProfileInfo = styled.div`
+  display: flex;
+  align-items: flex-end; 
+  gap: 20px;
+  
+  margin-top: -70px; 
+  margin-left: 32px; 
+  padding-bottom: 24px;
+  position: relative; 
+  z-index: 1; 
+  pointer-events: none; 
+  
+  animation: slideUp 0.5s ease-out;
+  
+  @keyframes slideUp {
+    from {
+      opacity: 0;
+      transform: translateY(20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+  
+  /* Reativa pointer-events apenas nos elementos internos */
+  > * {
+    pointer-events: auto;
+  }
+`;
+ 
+// A foto de perfil circular
+export const ProfileAvatar = styled.div`
+  width: 120px; 
+  height: 120px;
+  border-radius: 50%;
+  background: linear-gradient(135deg, ${props => props.theme.sidebar} 0%, ${props => props.theme.button} 100%);
+  border: 5px solid ${props => props.theme.background}; 
+  background-size: cover;
+  background-position: center;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15),
+              0 2px 8px rgba(0, 0, 0, 0.1);
+  
+  position: relative;
+  flex-shrink: 0;
+  
+  /* Efeito de brilho sutil */
+  &::after {
+    content: '';
+    position: absolute;
+    top: 10%;
+    left: 10%;
+    width: 40%;
+    height: 40%;
+    background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%);
+    border-radius: 50%;
+  }
+  
+  transition: transform 0.3s ease, box-shadow 0.3s ease;
+  
+  &:hover {
+    transform: scale(1.05);
+    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2),
+                0 4px 12px rgba(0, 0, 0, 0.15);
+  }
+`;
+ 
+// O nome do usuário
+export const Username = styled.h1`
+  font-size: 2.5em;
+  font-weight: 700;
+  color: ${props => props.theme.title}; 
+  margin: 0 0 10px 0; /* Margem inferior para alinhar com a base do avatar */
+  
+  background: linear-gradient(135deg, ${props => props.theme.title} 0%, ${props => props.theme.subtitle} 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+  
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  
+  position: relative;
+  
+  &::after {
+    content: '';
+    position: absolute;
+    bottom: -8px;
+    left: 0;
+    width: 60px;
+    height: 4px;
+    background: linear-gradient(90deg, ${props => props.theme.button} 0%, transparent 100%);
+    border-radius: 2px;
+  }
+`;
+ 
+// Container dos 3 botões de ação (dentro do banner)
+export const ProfileActions = styled.div`
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  position: relative;
+  z-index: 3;
+  
+  /* Backdrop blur para destacar os botões */
+  background: rgba(255, 255, 255, 0.1);
+  backdrop-filter: blur(10px);
+  padding: 8px;
+  border-radius: 50px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+`;
+ 
+// Botão de ícone
+export const IconButton = styled.button<{ $active?: boolean }>`
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  border: none;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  
+  background-color: ${props => props.$active 
+    ? props.theme['hover-button'] || props.theme.button
+    : props.theme.background};
+  color: ${props => props.$active 
+    ? '#FFFFFF'
+    : props.theme.button}; 
+ 
+  box-shadow: ${props => props.$active
+    ? '0 4px 12px rgba(0, 0, 0, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1)'
+    : '0 2px 8px rgba(0, 0, 0, 0.08)'};
+  
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ 
+  /* Efeito ripple */
+  &::before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 0;
+    height: 0;
+    border-radius: 50%;
+    background: ${props => props.$active 
+      ? 'rgba(255, 255, 255, 0.3)'
+      : 'rgba(0, 0, 0, 0.1)'};
+    transform: translate(-50%, -50%);
+    transition: width 0.6s, height 0.6s;
+  }
+ 
+  &:hover::before {
+    width: 100%;
+    height: 100%;
+  }
+ 
+  &:hover {
+    transform: translateY(-3px) scale(1.05);
+    box-shadow: ${props => props.$active
+      ? '0 6px 20px rgba(0, 0, 0, 0.2)'
+      : '0 4px 16px rgba(0, 0, 0, 0.12)'};
+    background-color: ${props => props.$active 
+      ? props.theme['hover-button'] || props.theme.button
+      : props.theme['gray-500'] || props.theme.background};
+  }
+ 
+  &:active {
+    transform: translateY(-1px) scale(1.02);
+  }
+ 
+  svg {
+    width: 22px;
+    height: 22px;
+    position: relative;
+    z-index: 1;
+    transition: transform 0.2s ease;
+  }
+ 
+  &:hover svg {
+    transform: ${props => props.$active ? 'rotate(5deg)' : 'scale(1.1)'};
+  }
+`;
+ 
+// Menus de ações flutuantes
+export const ActionsWrapper = styled.div`
+  position: relative; 
+  z-index: 5; /* Aumentado para ficar acima de tudo */
+`;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/ProjectPage/index.html b/frontend/coverage/lcov-report/src/pages/ProjectPage/index.html new file mode 100644 index 0000000..89599b1 --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/ProjectPage/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/ProjectPage + + + + + + + + + +
+
+

All files src/pages/ProjectPage

+
+ +
+ 90% + Statements + 18/20 +
+ + +
+ 75% + Branches + 6/8 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 94.11% + Lines + 16/17 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
90%18/2075%6/8100%4/494.11%16/17
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/ProjectPage/index.tsx.html b/frontend/coverage/lcov-report/src/pages/ProjectPage/index.tsx.html new file mode 100644 index 0000000..bf1429b --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/ProjectPage/index.tsx.html @@ -0,0 +1,367 @@ + + + + + + Code coverage report for src/pages/ProjectPage/index.tsx + + + + + + + + + +
+
+

All files / src/pages/ProjectPage index.tsx

+
+ +
+ 90% + Statements + 18/20 +
+ + +
+ 75% + Branches + 6/8 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 94.11% + Lines + 16/17 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +4x +4x +4x +  +4x +  +2x +2x +2x +2x +2x +  +  +  +2x +  +  +2x +  +  +4x +2x +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  + 
import { useEffect, useState } from 'react';
+import { useParams } from 'react-router-dom';
+import Sidebar from '../../components/layout/Sidebar';
+import * as S from './styles';
+import { GetProjectById } from '../../API/Project';
+import type { ProjectProps } from '../../API/Project';
+import { FiCalendar, FiUser } from 'react-icons/fi';
+ 
+export default function ProjectPage() {
+  const { projectId } = useParams<{ projectId: string }>();
+  const [project, setProject] = useState<ProjectProps | null>(null);
+  const [loading, setLoading] = useState(true);
+ 
+  useEffect(() => {
+    async function loadData() {
+        Iif (!projectId) return;
+        try {
+            setLoading(true);
+            const data = await GetProjectById(projectId);
+            setProject(data);
+        } catch (error) {
+            console.error("Erro ao carregar projeto:", error);
+        } finally {
+            setLoading(false);
+        }
+    }
+    loadData();
+  }, [projectId]);
+ 
+  if (loading) return <div>Carregando...</div>;
+  if (!project) return <div>Projeto não encontrado</div>;
+ 
+  // Formata data
+  const startDate = new Date(project.startDate).toLocaleDateString('pt-BR');
+ 
+  return (
+    <S.PageWrapper>
+      <Sidebar />
+      
+      <S.MainContent>
+        <S.Banner />
+        
+        <S.HeaderContainer>
+          {/* Ícone com a inicial do projeto */}
+          <S.ProjectIcon>
+            {project.title.charAt(0).toUpperCase()}
+          </S.ProjectIcon>
+          
+          <S.HeaderInfo>
+            <h1>{project.title}</h1>
+            <span>
+                <FiUser style={{ marginRight: 5, verticalAlign: 'middle' }}/>
+                Criado por <strong>{project.authorUsername || project.authorName}</strong>
+            </span>
+          </S.HeaderInfo>
+        </S.HeaderContainer>
+ 
+        <S.ContentGrid>
+          
+          {/* Coluna Principal: Descrição */}
+          <S.MainColumn>
+            <h2>Sobre o Projeto</h2>
+            <S.DescriptionBox>
+                {project.description}
+            </S.DescriptionBox>
+ 
+          </S.MainColumn>
+ 
+          <S.InfoSidebar>
+            <h3>Status</h3>
+            <S.StatusBadge status={project.status}>
+                {project.status.replace('-', ' ')}
+            </S.StatusBadge>
+ 
+            <h3>Início</h3>
+            <div style={{ display: 'flex', alignItems: 'center', gap: '8px', color: '#555' }}>
+                <FiCalendar />
+                <span>{startDate}</span>
+            </div>
+ 
+            <h3>Tecnologias</h3>
+            <S.KeywordsContainer>
+              {project.technologies?.map((tech) => (
+                <S.KeywordTag key={tech}>
+                  {tech}
+                </S.KeywordTag>
+              ))}
+            </S.KeywordsContainer>
+          </S.InfoSidebar>
+ 
+        </S.ContentGrid>
+      </S.MainContent>
+    </S.PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Register/index.html b/frontend/coverage/lcov-report/src/pages/Register/index.html new file mode 100644 index 0000000..cfe5a4b --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Register/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/Register + + + + + + + + + +
+
+

All files src/pages/Register

+
+ +
+ 87.5% + Statements + 14/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 60% + Functions + 3/5 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
87.5%14/1675%3/460%3/587.5%14/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov-report/src/pages/Register/index.tsx.html b/frontend/coverage/lcov-report/src/pages/Register/index.tsx.html new file mode 100644 index 0000000..0d4adaf --- /dev/null +++ b/frontend/coverage/lcov-report/src/pages/Register/index.tsx.html @@ -0,0 +1,421 @@ + + + + + + Code coverage report for src/pages/Register/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Register index.tsx

+
+ +
+ 87.5% + Statements + 14/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 60% + Functions + 3/5 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +8x +8x +  +  +2x +2x +2x +  +1x +  +  +1x +1x +  +  +  +  +1x +  +  +1x +1x +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState } from 'react';
+import { FormPageContainer, FormWrapper, FormTitle, StyledForm, StyledInput, SubmitButton, RedirectLink } from '../../components/domain/Form/styles';
+import { useForm, Controller} from 'react-hook-form';
+import { IMaskInput } from 'react-imask';
+import  Toast  from '../../components/common/Toast';
+import { useNavigate } from 'react-router-dom';
+import {Register as RegisterAPI} from '../../API/Auth'
+import type { RegisterProps } from '../../API/Auth';
+import type { NotificationState } from '../../components/common/Toast';
+ 
+export default function Register() {
+  // Estado para a notificação - usado no Toast
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+  
+  const { register, handleSubmit, formState: {isSubmitting}, control } = useForm<RegisterProps>();
+  const navigate = useNavigate();
+ 
+  async function onSubmit(data: RegisterProps) {
+    console.log(data);
+    try{
+      await RegisterAPI(data);
+      
+      console.log('Usuário registrado com sucesso:');
+      
+      // Define estado para mostrar notificação de sucesso
+      setNotification({ message: 'Usuário registrado com sucesso!', type: 'success' });
+      setTimeout(() => {
+        navigate('/feed'); // Navega para a página de feed
+      }, 1000);
+      
+    } catch (error) { 
+      console.error('Erro ao registrar usuário:', error);
+      
+      // Define estado para mostrar notificação de erro
+      Eif (error instanceof Error){
+        setNotification({ message: error.message, type: 'error' });
+      }
+    }
+  }
+ 
+  return (
+    <FormPageContainer>
+      
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <FormWrapper>
+        <FormTitle>Criar conta</FormTitle>
+        
+        <StyledForm onSubmit={handleSubmit(onSubmit)}>
+          <StyledInput 
+            type="text" 
+            placeholder="Nome completo" 
+            required 
+            {...register('nomeCompleto')}
+          />
+          <StyledInput 
+            type="text" 
+            placeholder="Nome de usuário (user)" 
+            required 
+            {...register('username')}
+          />
+          <StyledInput 
+            type="email" 
+            placeholder="Email" 
+            required 
+            {...register('email')}
+          />
+          <StyledInput 
+            type="password" 
+            placeholder="Senha" 
+            required 
+            {...register('senha')}
+          />
+          <StyledInput 
+            type="tel" 
+            placeholder="Telefone" 
+            required 
+            {...register('telefone')}
+          />
+          <Controller
+            name="dataNascimento"
+            control={control}
+            rules={{ required: true }} 
+            render={({ field }) => (
+              <StyledInput
+                {...field}
+                as={IMaskInput} 
+                mask="00/00/0000"
+                placeholder="Data de nascimento"
+                required
+              />
+            )}
+          />
+          
+          <SubmitButton disabled = {isSubmitting} type="submit">Cadastrar</SubmitButton>
+        </StyledForm>
+ 
+        <RedirectLink>
+          Já tem uma conta? <a href="/login">Faça login</a>
+        </RedirectLink>
+      </FormWrapper>
+    </FormPageContainer>
+  );
+}
+ 
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/lcov.info b/frontend/coverage/lcov.info new file mode 100644 index 0000000..4d81be0 --- /dev/null +++ b/frontend/coverage/lcov.info @@ -0,0 +1,2191 @@ +TN: +SF:src/App.tsx +FN:7,App +FNF:1 +FNH:1 +FNDA:2,App +DA:9,2 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/API/Comment.ts +FN:14,(anonymous_0) +FN:22,CreateComment +FN:42,GetComments +FN:56,GetUserComments +FN:67,DeleteComment +FNF:5 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,CreateComment +FNDA:0,GetComments +FNDA:0,GetUserComments +FNDA:0,DeleteComment +DA:14,1 +DA:15,0 +DA:23,0 +DA:25,0 +DA:30,0 +DA:34,0 +DA:35,0 +DA:37,0 +DA:43,0 +DA:45,0 +DA:47,0 +DA:49,0 +DA:50,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:68,0 +DA:70,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:77,0 +LF:24 +LH:1 +BRDA:34,0,0,0 +BRDA:34,0,1,0 +BRDA:34,1,0,0 +BRDA:34,1,1,0 +BRDA:74,2,0,0 +BRDA:74,2,1,0 +BRDA:74,3,0,0 +BRDA:74,3,1,0 +BRF:8 +BRH:0 +end_of_record +TN: +SF:src/API/Community.ts +FN:16,(anonymous_0) +FN:24,NewCommunity +FN:38,GetUserCommunities +FN:48,GetCommunityById +FN:61,JoinCommunity +FN:74,DeleteCommunity +FN:86,UpdateCommunity +FN:102,LeaveCommunity +FN:115,GetAllCommunities +FNF:9 +FNH:0 +FNDA:0,(anonymous_0) +FNDA:0,NewCommunity +FNDA:0,GetUserCommunities +FNDA:0,GetCommunityById +FNDA:0,JoinCommunity +FNDA:0,DeleteCommunity +FNDA:0,UpdateCommunity +FNDA:0,LeaveCommunity +FNDA:0,GetAllCommunities +DA:16,2 +DA:17,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:34,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:44,0 +DA:49,0 +DA:50,0 +DA:52,0 +DA:54,0 +DA:55,0 +DA:57,0 +DA:62,0 +DA:63,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:79,0 +DA:80,0 +DA:82,0 +DA:87,0 +DA:88,0 +DA:93,0 +DA:95,0 +DA:96,0 +DA:98,0 +DA:103,0 +DA:104,0 +DA:106,0 +DA:108,0 +DA:109,0 +DA:111,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:120,0 +DA:121,0 +LF:49 +LH:1 +BRDA:31,0,0,0 +BRDA:31,0,1,0 +BRDA:31,1,0,0 +BRDA:31,1,1,0 +BRDA:54,2,0,0 +BRDA:54,2,1,0 +BRDA:54,3,0,0 +BRDA:54,3,1,0 +BRDA:67,4,0,0 +BRDA:67,4,1,0 +BRDA:67,5,0,0 +BRDA:67,5,1,0 +BRDA:79,6,0,0 +BRDA:79,6,1,0 +BRDA:79,7,0,0 +BRDA:79,7,1,0 +BRDA:95,8,0,0 +BRDA:95,8,1,0 +BRDA:95,9,0,0 +BRDA:95,9,1,0 +BRDA:108,10,0,0 +BRDA:108,10,1,0 +BRDA:108,11,0,0 +BRDA:108,11,1,0 +BRF:24 +BRH:0 +end_of_record +TN: +SF:src/API/Project.ts +FN:16,parseDate +FN:24,(anonymous_1) +FN:32,NewProject +FN:45,UpdateProject +FN:61,GetFeedProjects +FN:75,DeleteProject +FN:87,GetUserProjects +FN:102,GetProjectById +FNF:8 +FNH:1 +FNDA:2,parseDate +FNDA:0,(anonymous_1) +FNDA:0,NewProject +FNDA:0,UpdateProject +FNDA:0,GetFeedProjects +FNDA:0,DeleteProject +FNDA:0,GetUserProjects +FNDA:0,GetProjectById +DA:18,2 +DA:21,2 +DA:24,4 +DA:25,0 +DA:33,0 +DA:34,0 +DA:36,0 +DA:38,0 +DA:39,0 +DA:41,0 +DA:46,0 +DA:47,0 +DA:51,0 +DA:53,0 +DA:54,0 +DA:56,0 +DA:63,0 +DA:64,0 +DA:66,0 +DA:68,0 +DA:70,0 +DA:71,0 +DA:76,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:88,0 +DA:89,0 +DA:91,0 +DA:93,0 +DA:95,0 +DA:96,0 +DA:98,0 +DA:103,0 +DA:104,0 +DA:106,0 +DA:108,0 +DA:109,0 +LF:39 +LH:3 +BRDA:38,0,0,0 +BRDA:38,0,1,0 +BRDA:38,1,0,0 +BRDA:38,1,1,0 +BRDA:53,2,0,0 +BRDA:53,2,1,0 +BRDA:53,3,0,0 +BRDA:53,3,1,0 +BRDA:80,4,0,0 +BRDA:80,4,1,0 +BRDA:80,5,0,0 +BRDA:80,5,1,0 +BRDA:95,6,0,0 +BRDA:95,6,1,0 +BRDA:95,7,0,0 +BRDA:95,7,1,0 +BRF:16 +BRH:0 +end_of_record +TN: +SF:src/API/api.ts +FNF:0 +FNH:0 +DA:3,5 +LF:1 +LH:1 +BRDA:4,0,0,5 +BRDA:4,0,1,5 +BRF:2 +BRH:2 +end_of_record +TN: +SF:src/components/common/Keyword/index.tsx +FN:10,(anonymous_0) +FNF:1 +FNH:1 +FNDA:2,(anonymous_0) +DA:10,1 +DA:11,2 +DA:21,1 +LF:3 +LH:3 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/components/common/Modal/index.tsx +FN:12,(anonymous_0) +FN:14,(anonymous_1) +FN:21,(anonymous_2) +FN:31,(anonymous_3) +FNF:4 +FNH:4 +FNDA:5,(anonymous_0) +FNDA:5,(anonymous_1) +FNDA:5,(anonymous_2) +FNDA:2,(anonymous_3) +DA:12,1 +DA:14,5 +DA:15,5 +DA:16,4 +DA:18,1 +DA:21,5 +DA:22,5 +DA:26,5 +DA:27,1 +DA:31,4 +DA:32,2 +DA:35,4 +LF:12 +LH:12 +BRDA:15,0,0,4 +BRDA:15,0,1,1 +BRDA:26,1,0,1 +BRDA:26,1,1,4 +BRF:4 +BRH:4 +end_of_record +TN: +SF:src/components/common/Toast/index.tsx +FN:15,(anonymous_0) +FN:18,(anonymous_1) +FN:19,(anonymous_2) +FN:24,(anonymous_3) +FNF:4 +FNH:4 +FNDA:4,(anonymous_0) +FNDA:4,(anonymous_1) +FNDA:1,(anonymous_2) +FNDA:4,(anonymous_3) +DA:15,1 +DA:18,4 +DA:19,4 +DA:20,1 +DA:24,4 +DA:25,4 +DA:29,4 +LF:7 +LH:7 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/components/domain/CreationForm/styles.ts +FN:5,(anonymous_0) +FN:13,(anonymous_1) +FN:54,(anonymous_2) +FN:72,(anonymous_3) +FN:72,(anonymous_4) +FN:89,(anonymous_5) +FN:92,(anonymous_6) +FN:98,(anonymous_7) +FN:103,(anonymous_8) +FN:104,(anonymous_9) +FN:109,(anonymous_10) +FN:110,(anonymous_11) +FN:111,(anonymous_12) +FN:125,(anonymous_13) +FN:135,(anonymous_14) +FN:139,(anonymous_15) +FN:150,(anonymous_16) +FN:153,(anonymous_17) +FN:166,(anonymous_18) +FN:167,(anonymous_19) +FN:172,(anonymous_20) +FN:173,(anonymous_21) +FN:174,(anonymous_22) +FN:180,(anonymous_23) +FN:185,(anonymous_24) +FN:186,(anonymous_25) +FN:202,(anonymous_26) +FN:203,(anonymous_27) +FN:237,(anonymous_28) +FN:242,(anonymous_29) +FN:251,(anonymous_30) +FN:264,(anonymous_31) +FN:271,(anonymous_32) +FN:280,(anonymous_33) +FN:288,(anonymous_34) +FN:307,(anonymous_35) +FN:308,(anonymous_36) +FN:308,(anonymous_37) +FN:314,(anonymous_38) +FN:336,(anonymous_39) +FN:347,(anonymous_40) +FN:363,(anonymous_41) +FN:366,(anonymous_42) +FN:374,(anonymous_43) +FN:379,(anonymous_44) +FN:380,(anonymous_45) +FN:385,(anonymous_46) +FN:386,(anonymous_47) +FN:387,(anonymous_48) +FN:398,(anonymous_49) +FN:403,(anonymous_50) +FN:408,(anonymous_51) +FN:416,(anonymous_52) +FN:421,(anonymous_53) +FN:428,(anonymous_54) +FN:429,(anonymous_55) +FN:433,(anonymous_56) +FN:434,(anonymous_57) +FNF:58 +FNH:49 +FNDA:20,(anonymous_0) +FNDA:20,(anonymous_1) +FNDA:86,(anonymous_2) +FNDA:86,(anonymous_3) +FNDA:86,(anonymous_4) +FNDA:33,(anonymous_5) +FNDA:33,(anonymous_6) +FNDA:33,(anonymous_7) +FNDA:33,(anonymous_8) +FNDA:33,(anonymous_9) +FNDA:33,(anonymous_10) +FNDA:33,(anonymous_11) +FNDA:33,(anonymous_12) +FNDA:13,(anonymous_13) +FNDA:13,(anonymous_14) +FNDA:13,(anonymous_15) +FNDA:13,(anonymous_16) +FNDA:13,(anonymous_17) +FNDA:13,(anonymous_18) +FNDA:13,(anonymous_19) +FNDA:13,(anonymous_20) +FNDA:13,(anonymous_21) +FNDA:13,(anonymous_22) +FNDA:13,(anonymous_23) +FNDA:13,(anonymous_24) +FNDA:13,(anonymous_25) +FNDA:0,(anonymous_26) +FNDA:0,(anonymous_27) +FNDA:0,(anonymous_28) +FNDA:0,(anonymous_29) +FNDA:0,(anonymous_30) +FNDA:0,(anonymous_31) +FNDA:0,(anonymous_32) +FNDA:0,(anonymous_33) +FNDA:0,(anonymous_34) +FNDA:20,(anonymous_35) +FNDA:20,(anonymous_36) +FNDA:20,(anonymous_37) +FNDA:20,(anonymous_38) +FNDA:20,(anonymous_39) +FNDA:20,(anonymous_40) +FNDA:20,(anonymous_41) +FNDA:20,(anonymous_42) +FNDA:20,(anonymous_43) +FNDA:20,(anonymous_44) +FNDA:20,(anonymous_45) +FNDA:20,(anonymous_46) +FNDA:20,(anonymous_47) +FNDA:20,(anonymous_48) +FNDA:20,(anonymous_49) +FNDA:20,(anonymous_50) +FNDA:20,(anonymous_51) +FNDA:20,(anonymous_52) +FNDA:20,(anonymous_53) +FNDA:20,(anonymous_54) +FNDA:20,(anonymous_55) +FNDA:20,(anonymous_56) +FNDA:20,(anonymous_57) +DA:4,2 +DA:5,20 +DA:13,20 +DA:30,2 +DA:50,2 +DA:54,86 +DA:72,86 +DA:84,2 +DA:89,33 +DA:92,33 +DA:98,33 +DA:103,33 +DA:104,33 +DA:109,33 +DA:110,33 +DA:111,33 +DA:117,2 +DA:125,13 +DA:135,13 +DA:139,13 +DA:145,2 +DA:150,13 +DA:153,13 +DA:166,13 +DA:167,13 +DA:172,13 +DA:173,13 +DA:174,13 +DA:180,13 +DA:185,13 +DA:186,13 +DA:191,2 +DA:197,2 +DA:202,0 +DA:203,0 +DA:237,0 +DA:242,0 +DA:247,2 +DA:251,0 +DA:264,0 +DA:271,0 +DA:280,0 +DA:285,2 +DA:288,0 +DA:303,2 +DA:307,20 +DA:308,20 +DA:314,20 +DA:336,20 +DA:347,20 +DA:356,2 +DA:363,20 +DA:366,20 +DA:374,20 +DA:379,20 +DA:380,20 +DA:385,20 +DA:386,20 +DA:387,20 +DA:398,20 +DA:403,20 +DA:408,20 +DA:413,2 +DA:416,20 +DA:421,20 +DA:428,20 +DA:429,20 +DA:433,20 +DA:434,20 +LF:69 +LH:60 +BRDA:72,0,0,86 +BRDA:72,0,1,86 +BRDA:288,1,0,0 +BRDA:288,1,1,0 +BRDA:308,2,0,20 +BRDA:308,2,1,20 +BRDA:416,3,0,20 +BRDA:416,3,1,20 +BRDA:428,4,0,20 +BRDA:428,4,1,20 +BRDA:429,5,0,20 +BRDA:429,5,1,20 +BRDA:433,6,0,20 +BRDA:433,6,1,20 +BRF:14 +BRH:12 +end_of_record +TN: +SF:src/components/domain/Postcard/index.tsx +FN:15,(anonymous_0) +FN:23,(anonymous_1) +FN:31,(anonymous_2) +FN:45,Postcard +FN:65,(anonymous_4) +FN:71,loadComments +FN:81,(anonymous_6) +FN:82,handleClickOutside +FN:90,(anonymous_8) +FN:95,(anonymous_9) +FN:105,(anonymous_10) +FN:115,(anonymous_11) +FN:126,(anonymous_12) +FN:153,(anonymous_13) +FN:166,(anonymous_14) +FN:190,(anonymous_15) +FN:203,(anonymous_16) +FN:216,(anonymous_17) +FN:216,(anonymous_18) +FN:225,(anonymous_19) +FN:238,(anonymous_20) +FN:250,(anonymous_21) +FN:270,(anonymous_22) +FN:287,(anonymous_23) +FN:307,(anonymous_24) +FN:315,(anonymous_25) +FN:327,(anonymous_26) +FN:335,(anonymous_27) +FNF:28 +FNH:18 +FNDA:0,(anonymous_0) +FNDA:21,(anonymous_1) +FNDA:12,(anonymous_2) +FNDA:21,Postcard +FNDA:10,(anonymous_4) +FNDA:2,loadComments +FNDA:13,(anonymous_6) +FNDA:0,handleClickOutside +FNDA:13,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:2,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:1,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:12,(anonymous_14) +FNDA:1,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:4,(anonymous_17) +FNDA:4,(anonymous_18) +FNDA:2,(anonymous_19) +FNDA:2,(anonymous_20) +FNDA:1,(anonymous_21) +FNDA:1,(anonymous_22) +FNDA:0,(anonymous_23) +FNDA:0,(anonymous_24) +FNDA:0,(anonymous_25) +FNDA:0,(anonymous_26) +FNDA:0,(anonymous_27) +DA:15,1 +DA:16,0 +DA:23,1 +DA:24,21 +DA:31,1 +DA:32,12 +DA:46,21 +DA:48,21 +DA:49,21 +DA:50,21 +DA:51,21 +DA:52,21 +DA:55,21 +DA:56,21 +DA:57,21 +DA:58,21 +DA:59,21 +DA:61,21 +DA:63,21 +DA:65,21 +DA:66,10 +DA:67,2 +DA:72,2 +DA:73,2 +DA:74,2 +DA:76,0 +DA:81,21 +DA:83,0 +DA:84,0 +DA:87,13 +DA:88,4 +DA:90,13 +DA:91,13 +DA:95,21 +DA:96,1 +DA:98,1 +DA:99,1 +DA:101,0 +DA:105,21 +DA:106,2 +DA:107,2 +DA:109,2 +DA:111,2 +DA:112,0 +DA:114,2 +DA:115,1 +DA:118,1 +DA:119,1 +DA:122,1 +DA:126,21 +DA:127,1 +DA:129,1 +DA:130,0 +DA:131,0 +DA:134,1 +DA:136,1 +DA:137,1 +DA:138,1 +DA:140,1 +DA:141,1 +DA:142,1 +DA:145,0 +DA:146,0 +DA:149,1 +DA:153,21 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:159,0 +DA:161,0 +DA:162,0 +DA:166,21 +DA:168,12 +DA:171,12 +DA:174,12 +DA:181,12 +DA:185,0 +DA:186,0 +DA:190,21 +DA:191,1 +DA:192,0 +DA:197,21 +DA:203,0 +DA:216,4 +DA:226,2 +DA:227,2 +DA:238,2 +DA:250,1 +DA:272,1 +DA:274,1 +DA:287,0 +DA:307,0 +DA:315,0 +DA:327,0 +DA:335,0 +LF:97 +LH:70 +BRDA:45,0,0,21 +BRDA:63,1,0,21 +BRDA:63,1,1,0 +BRDA:66,2,0,2 +BRDA:66,2,1,8 +BRDA:66,3,0,10 +BRDA:66,3,1,2 +BRDA:83,4,0,0 +BRDA:83,4,1,0 +BRDA:83,5,0,0 +BRDA:83,5,1,0 +BRDA:87,6,0,4 +BRDA:87,6,1,9 +BRDA:96,7,0,1 +BRDA:96,7,1,0 +BRDA:98,8,0,1 +BRDA:98,8,1,0 +BRDA:107,9,0,2 +BRDA:107,9,1,0 +BRDA:107,9,2,0 +BRDA:109,10,0,0 +BRDA:109,10,1,2 +BRDA:111,11,0,0 +BRDA:111,11,1,2 +BRDA:129,12,0,0 +BRDA:129,12,1,1 +BRDA:134,13,0,0 +BRDA:134,13,1,1 +BRDA:145,14,0,0 +BRDA:145,14,1,0 +BRDA:154,15,0,0 +BRDA:154,15,1,0 +BRDA:168,16,0,0 +BRDA:168,16,1,12 +BRDA:174,17,0,12 +BRDA:174,17,1,0 +BRDA:175,18,0,12 +BRDA:175,18,1,0 +BRDA:175,18,2,0 +BRDA:175,18,3,0 +BRDA:175,18,4,0 +BRDA:185,19,0,0 +BRDA:185,19,1,0 +BRDA:191,20,0,1 +BRDA:191,20,1,0 +BRDA:199,21,0,21 +BRDA:199,21,1,3 +BRDA:208,22,0,21 +BRDA:208,22,1,21 +BRDA:210,23,0,21 +BRDA:210,23,1,0 +BRDA:214,24,0,21 +BRDA:214,24,1,12 +BRDA:220,25,0,12 +BRDA:220,25,1,4 +BRDA:222,26,0,4 +BRDA:222,26,1,4 +BRDA:244,27,0,21 +BRDA:244,27,1,5 +BRDA:260,28,0,5 +BRDA:260,28,1,4 +BRDA:262,29,0,1 +BRDA:262,29,1,4 +BRDA:268,30,0,5 +BRDA:268,30,1,1 +BRDA:272,31,0,1 +BRDA:272,31,1,1 +BRDA:280,32,0,1 +BRDA:280,32,1,0 +BRDA:285,33,0,1 +BRDA:285,33,1,0 +BRDA:275,34,0,1 +BRDA:275,34,1,0 +BRF:73 +BRH:43 +end_of_record +TN: +SF:src/components/domain/Searchbar/index.tsx +FN:11,Searchbar +FN:28,(anonymous_1) +FN:35,(anonymous_2) +FN:36,(anonymous_3) +FN:50,(anonymous_4) +FN:60,(anonymous_5) +FN:63,(anonymous_6) +FN:67,(anonymous_7) +FN:69,(anonymous_8) +FN:78,(anonymous_9) +FN:79,handleClickOutside +FN:85,(anonymous_11) +FN:89,(anonymous_12) +FN:95,(anonymous_13) +FN:110,(anonymous_14) +FN:127,(anonymous_15) +FN:130,(anonymous_16) +FN:144,(anonymous_17) +FN:147,(anonymous_18) +FNF:19 +FNH:15 +FNDA:47,Searchbar +FNDA:6,(anonymous_1) +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:20,(anonymous_4) +FNDA:3,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:3,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:6,(anonymous_9) +FNDA:1,handleClickOutside +FNDA:6,(anonymous_11) +FNDA:1,(anonymous_12) +FNDA:1,(anonymous_13) +FNDA:7,(anonymous_14) +FNDA:1,(anonymous_15) +FNDA:1,(anonymous_16) +FNDA:3,(anonymous_17) +FNDA:1,(anonymous_18) +DA:12,47 +DA:13,47 +DA:15,47 +DA:17,47 +DA:18,47 +DA:21,47 +DA:22,47 +DA:25,47 +DA:26,47 +DA:28,47 +DA:29,6 +DA:30,6 +DA:31,6 +DA:32,6 +DA:34,6 +DA:35,0 +DA:36,0 +DA:39,6 +DA:40,6 +DA:42,0 +DA:44,6 +DA:50,47 +DA:51,20 +DA:52,8 +DA:53,8 +DA:54,8 +DA:57,12 +DA:60,12 +DA:61,3 +DA:63,0 +DA:67,12 +DA:68,3 +DA:69,0 +DA:72,12 +DA:73,12 +DA:78,47 +DA:80,1 +DA:81,1 +DA:84,6 +DA:85,6 +DA:89,47 +DA:90,1 +DA:91,1 +DA:92,1 +DA:95,47 +DA:96,1 +DA:97,1 +DA:98,1 +DA:101,47 +DA:103,47 +DA:110,7 +DA:128,1 +DA:130,1 +DA:145,3 +DA:147,1 +LF:55 +LH:50 +BRDA:30,0,0,6 +BRDA:30,0,1,0 +BRDA:30,1,0,6 +BRDA:30,1,1,6 +BRDA:51,2,0,8 +BRDA:51,2,1,12 +BRDA:61,3,0,3 +BRDA:61,3,1,2 +BRDA:61,3,2,2 +BRDA:68,4,0,3 +BRDA:68,4,1,0 +BRDA:80,5,0,1 +BRDA:80,5,1,0 +BRDA:80,6,0,1 +BRDA:80,6,1,1 +BRDA:101,7,0,47 +BRDA:101,7,1,45 +BRDA:115,8,0,47 +BRDA:115,8,1,31 +BRDA:115,8,2,23 +BRDA:117,9,0,12 +BRDA:117,9,1,11 +BRDA:119,10,0,7 +BRDA:119,10,1,4 +BRDA:124,11,0,4 +BRDA:124,11,1,1 +BRDA:134,12,0,1 +BRDA:134,12,1,0 +BRDA:141,13,0,4 +BRDA:141,13,1,3 +BRDA:147,14,0,1 +BRDA:147,14,1,0 +BRDA:150,15,0,3 +BRDA:150,15,1,2 +BRDA:146,16,0,3 +BRDA:146,16,1,0 +BRF:36 +BRH:30 +end_of_record +TN: +SF:src/components/domain/TagInput/index.tsx +FN:15,TagInput +FN:28,(anonymous_1) +FN:30,(anonymous_2) +FN:41,(anonymous_3) +FN:42,handleClickOutside +FN:48,(anonymous_5) +FN:54,(anonymous_6) +FN:69,(anonymous_7) +FN:70,(anonymous_8) +FN:78,(anonymous_9) +FN:81,(anonymous_10) +FN:95,(anonymous_11) +FN:101,(anonymous_12) +FN:102,(anonymous_13) +FNF:14 +FNH:13 +FNDA:20,TagInput +FNDA:9,(anonymous_1) +FNDA:11,(anonymous_2) +FNDA:5,(anonymous_3) +FNDA:0,handleClickOutside +FNDA:5,(anonymous_5) +FNDA:2,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:2,(anonymous_8) +FNDA:18,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:3,(anonymous_11) +FNDA:4,(anonymous_12) +FNDA:2,(anonymous_13) +DA:23,20 +DA:24,20 +DA:25,20 +DA:26,20 +DA:28,20 +DA:29,9 +DA:30,3 +DA:31,11 +DA:34,3 +DA:36,6 +DA:41,20 +DA:43,0 +DA:44,0 +DA:47,5 +DA:48,5 +DA:49,5 +DA:54,20 +DA:56,2 +DA:57,1 +DA:58,1 +DA:60,1 +DA:61,1 +DA:62,1 +DA:63,1 +DA:64,1 +DA:69,20 +DA:70,2 +DA:71,1 +DA:74,20 +DA:79,18 +DA:81,1 +DA:95,3 +DA:102,4 +LF:33 +LH:31 +BRDA:16,0,0,20 +BRDA:29,1,0,3 +BRDA:29,1,1,6 +BRDA:31,2,0,11 +BRDA:31,2,1,3 +BRDA:43,3,0,0 +BRDA:43,3,1,0 +BRDA:43,4,0,0 +BRDA:43,4,1,0 +BRDA:56,5,0,1 +BRDA:56,5,1,1 +BRDA:60,6,0,1 +BRDA:60,6,1,0 +BRDA:76,7,0,20 +BRDA:76,7,1,10 +BRDA:89,8,0,10 +BRDA:89,8,1,10 +BRDA:99,9,0,20 +BRDA:99,9,1,4 +BRDA:109,10,0,20 +BRDA:109,10,1,1 +BRF:21 +BRH:16 +end_of_record +TN: +SF:src/components/layout/Header/index.tsx +FN:10,Header +FNF:1 +FNH:1 +FNDA:2,Header +DA:11,2 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/components/layout/HeaderHome/index.tsx +FN:3,HeaderHome +FNF:1 +FNH:1 +FNDA:1,HeaderHome +DA:4,1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/components/layout/Sidebar/index.tsx +FN:9,Sidebar +FN:15,(anonymous_1) +FN:19,(anonymous_2) +FN:21,(anonymous_3) +FN:53,(anonymous_4) +FNF:5 +FNH:5 +FNDA:9,Sidebar +FNDA:2,(anonymous_1) +FNDA:8,(anonymous_2) +FNDA:8,(anonymous_3) +FNDA:4,(anonymous_4) +DA:11,9 +DA:12,9 +DA:13,9 +DA:15,9 +DA:16,2 +DA:19,9 +DA:21,8 +DA:22,8 +DA:24,8 +DA:25,8 +DA:26,8 +DA:29,0 +DA:33,8 +DA:34,8 +DA:37,9 +DA:54,4 +LF:16 +LH:15 +BRDA:33,0,0,8 +BRDA:33,0,1,0 +BRDA:51,1,0,9 +BRDA:51,1,1,8 +BRF:4 +BRH:3 +end_of_record +TN: +SF:src/pages/CommunityPage/index.tsx +FN:15,CommunityPage +FN:29,(anonymous_1) +FN:30,loadData +FN:44,(anonymous_3) +FN:45,handleClickOutside +FN:51,(anonymous_5) +FN:54,(anonymous_6) +FN:61,(anonymous_7) +FN:76,(anonymous_8) +FN:80,(anonymous_9) +FN:88,(anonymous_10) +FN:100,(anonymous_11) +FN:107,(anonymous_12) +FN:134,(anonymous_13) +FN:155,(anonymous_14) +FN:161,(anonymous_15) +FN:171,(anonymous_16) +FN:186,(anonymous_17) +FN:199,(anonymous_18) +FN:209,(anonymous_19) +FN:218,(anonymous_20) +FN:230,(anonymous_21) +FN:238,(anonymous_22) +FNF:23 +FNH:15 +FNDA:14,CommunityPage +FNDA:4,(anonymous_1) +FNDA:4,loadData +FNDA:6,(anonymous_3) +FNDA:0,handleClickOutside +FNDA:6,(anonymous_5) +FNDA:1,(anonymous_6) +FNDA:1,(anonymous_7) +FNDA:0,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:1,(anonymous_11) +FNDA:1,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:1,(anonymous_14) +FNDA:1,(anonymous_15) +FNDA:1,(anonymous_16) +FNDA:10,(anonymous_17) +FNDA:10,(anonymous_18) +FNDA:0,(anonymous_19) +FNDA:0,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:0,(anonymous_22) +DA:16,14 +DA:17,14 +DA:19,14 +DA:20,14 +DA:21,14 +DA:23,14 +DA:24,14 +DA:25,14 +DA:27,14 +DA:29,14 +DA:31,4 +DA:32,4 +DA:33,4 +DA:34,4 +DA:35,4 +DA:36,4 +DA:38,0 +DA:41,4 +DA:44,14 +DA:46,0 +DA:47,0 +DA:50,6 +DA:51,6 +DA:54,14 +DA:55,1 +DA:57,1 +DA:58,1 +DA:61,1 +DA:67,1 +DA:70,0 +DA:71,0 +DA:76,14 +DA:77,0 +DA:80,14 +DA:81,1 +DA:82,1 +DA:83,1 +DA:84,1 +DA:85,1 +DA:88,1 +DA:89,0 +DA:93,0 +DA:94,0 +DA:96,0 +DA:100,14 +DA:101,1 +DA:103,1 +DA:104,1 +DA:107,1 +DA:113,1 +DA:114,1 +DA:117,0 +DA:118,0 +DA:120,0 +DA:124,14 +DA:126,10 +DA:134,0 +DA:155,1 +DA:161,1 +DA:172,1 +DA:173,1 +DA:187,10 +DA:200,10 +DA:209,0 +DA:218,0 +DA:230,0 +DA:238,0 +LF:67 +LH:49 +BRDA:32,0,0,0 +BRDA:32,0,1,4 +BRDA:46,1,0,0 +BRDA:46,1,1,0 +BRDA:46,2,0,0 +BRDA:46,2,1,0 +BRDA:50,3,0,1 +BRDA:50,3,1,5 +BRDA:55,4,0,0 +BRDA:55,4,1,1 +BRDA:61,5,0,1 +BRDA:61,5,1,0 +BRDA:64,6,0,1 +BRDA:64,6,1,0 +BRDA:70,7,0,0 +BRDA:70,7,1,0 +BRDA:81,8,0,0 +BRDA:81,8,1,1 +BRDA:93,9,0,0 +BRDA:93,9,1,0 +BRDA:101,10,0,0 +BRDA:101,10,1,1 +BRDA:107,11,0,1 +BRDA:107,11,1,0 +BRDA:110,12,0,1 +BRDA:110,12,1,0 +BRDA:117,13,0,0 +BRDA:117,13,1,0 +BRDA:124,14,0,4 +BRDA:124,14,1,10 +BRDA:130,15,0,10 +BRDA:130,15,1,3 +BRDA:149,16,0,14 +BRDA:149,16,1,3 +BRDA:154,17,0,14 +BRDA:154,17,1,7 +BRDA:154,17,2,3 +BRDA:159,18,0,14 +BRDA:159,18,1,4 +BRDA:165,19,0,4 +BRDA:165,19,1,1 +BRDA:187,20,0,10 +BRDA:187,20,1,10 +BRF:43 +BRH:25 +end_of_record +TN: +SF:src/pages/CommunityPage/styles.ts +FN:6,(anonymous_0) +FN:6,(anonymous_1) +FN:32,(anonymous_2) +FN:32,(anonymous_3) +FN:89,(anonymous_4) +FN:89,(anonymous_5) +FN:90,(anonymous_6) +FN:128,(anonymous_7) +FN:134,(anonymous_8) +FN:134,(anonymous_9) +FN:151,(anonymous_10) +FN:157,(anonymous_11) +FN:161,(anonymous_12) +FN:186,(anonymous_13) +FN:187,(anonymous_14) +FN:188,(anonymous_15) +FN:193,(anonymous_16) +FN:215,(anonymous_17) +FN:216,(anonymous_18) +FN:227,(anonymous_19) +FN:229,(anonymous_20) +FN:244,(anonymous_21) +FN:257,(anonymous_22) +FN:258,(anonymous_23) +FN:259,(anonymous_24) +FN:277,(anonymous_25) +FN:278,(anonymous_26) +FN:279,(anonymous_27) +FN:289,(anonymous_28) +FN:290,(anonymous_29) +FN:292,(anonymous_30) +FN:336,(anonymous_31) +FN:336,(anonymous_32) +FN:351,(anonymous_33) +FN:352,(anonymous_34) +FN:377,(anonymous_35) +FN:396,(anonymous_36) +FN:396,(anonymous_37) +FN:406,(anonymous_38) +FN:426,(anonymous_39) +FN:427,(anonymous_40) +FN:432,(anonymous_41) +FN:437,(anonymous_42) +FN:439,(anonymous_43) +FNF:44 +FNH:44 +FNDA:10,(anonymous_0) +FNDA:10,(anonymous_1) +FNDA:10,(anonymous_2) +FNDA:10,(anonymous_3) +FNDA:10,(anonymous_4) +FNDA:10,(anonymous_5) +FNDA:10,(anonymous_6) +FNDA:10,(anonymous_7) +FNDA:10,(anonymous_8) +FNDA:10,(anonymous_9) +FNDA:10,(anonymous_10) +FNDA:10,(anonymous_11) +FNDA:10,(anonymous_12) +FNDA:3,(anonymous_13) +FNDA:3,(anonymous_14) +FNDA:3,(anonymous_15) +FNDA:3,(anonymous_16) +FNDA:3,(anonymous_17) +FNDA:3,(anonymous_18) +FNDA:3,(anonymous_19) +FNDA:3,(anonymous_20) +FNDA:3,(anonymous_21) +FNDA:3,(anonymous_22) +FNDA:3,(anonymous_23) +FNDA:3,(anonymous_24) +FNDA:4,(anonymous_25) +FNDA:4,(anonymous_26) +FNDA:4,(anonymous_27) +FNDA:4,(anonymous_28) +FNDA:4,(anonymous_29) +FNDA:4,(anonymous_30) +FNDA:10,(anonymous_31) +FNDA:10,(anonymous_32) +FNDA:10,(anonymous_33) +FNDA:10,(anonymous_34) +FNDA:10,(anonymous_35) +FNDA:10,(anonymous_36) +FNDA:10,(anonymous_37) +FNDA:10,(anonymous_38) +FNDA:10,(anonymous_39) +FNDA:10,(anonymous_40) +FNDA:10,(anonymous_41) +FNDA:10,(anonymous_42) +FNDA:10,(anonymous_43) +DA:3,1 +DA:6,10 +DA:9,1 +DA:29,1 +DA:32,10 +DA:60,1 +DA:85,1 +DA:89,10 +DA:90,10 +DA:117,1 +DA:128,10 +DA:134,10 +DA:151,10 +DA:157,10 +DA:161,10 +DA:176,1 +DA:183,1 +DA:186,3 +DA:187,3 +DA:188,3 +DA:193,3 +DA:215,3 +DA:216,3 +DA:224,1 +DA:227,3 +DA:229,3 +DA:244,3 +DA:257,3 +DA:258,3 +DA:259,3 +DA:273,1 +DA:277,4 +DA:278,4 +DA:279,4 +DA:289,4 +DA:290,4 +DA:292,4 +DA:302,1 +DA:316,1 +DA:335,1 +DA:336,10 +DA:350,1 +DA:351,10 +DA:352,10 +DA:377,10 +DA:396,10 +DA:406,10 +DA:418,1 +DA:425,1 +DA:426,10 +DA:427,10 +DA:432,10 +DA:437,10 +DA:439,10 +DA:443,1 +LF:55 +LH:55 +BRDA:6,0,0,10 +BRDA:6,0,1,10 +BRDA:32,1,0,10 +BRDA:32,1,1,10 +BRDA:157,2,0,10 +BRDA:157,2,1,10 +BRDA:216,3,0,3 +BRDA:216,3,1,3 +BRDA:336,4,0,10 +BRDA:336,4,1,10 +BRDA:396,5,0,10 +BRDA:396,5,1,10 +BRDA:406,6,0,10 +BRDA:406,6,1,10 +BRF:14 +BRH:14 +end_of_record +TN: +SF:src/pages/CreateCommunity/index.tsx +FN:14,CreateCommunity +FN:37,(anonymous_1) +FN:38,loadTechs +FN:49,(anonymous_3) +FN:63,(anonymous_4) +FN:84,(anonymous_5) +FN:122,(anonymous_6) +FNF:7 +FNH:5 +FNDA:7,CreateCommunity +FNDA:2,(anonymous_1) +FNDA:2,loadTechs +FNDA:2,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:10,(anonymous_6) +DA:15,7 +DA:16,7 +DA:18,7 +DA:19,7 +DA:21,7 +DA:31,7 +DA:32,7 +DA:33,7 +DA:34,7 +DA:35,7 +DA:37,7 +DA:39,2 +DA:40,2 +DA:41,2 +DA:43,0 +DA:46,2 +DA:49,7 +DA:50,2 +DA:51,2 +DA:53,1 +DA:54,1 +DA:55,1 +DA:58,1 +DA:59,1 +DA:60,1 +DA:63,2 +DA:64,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:76,7 +DA:84,0 +DA:123,10 +LF:33 +LH:27 +BRDA:24,0,0,7 +BRDA:24,0,1,4 +BRDA:25,1,0,7 +BRDA:25,1,1,4 +BRDA:26,2,0,7 +BRDA:26,2,1,4 +BRDA:27,3,0,7 +BRDA:27,3,1,4 +BRDA:32,4,0,5 +BRDA:32,4,1,2 +BRDA:51,5,0,1 +BRDA:51,5,1,1 +BRDA:51,6,0,2 +BRDA:51,6,1,1 +BRDA:69,7,0,0 +BRDA:69,7,1,0 +BRDA:80,8,0,7 +BRDA:80,8,1,2 +BRDA:91,9,0,3 +BRDA:91,9,1,4 +BRDA:134,10,0,3 +BRDA:134,10,1,4 +BRF:22 +BRH:20 +end_of_record +TN: +SF:src/pages/CreateProject/index.tsx +FN:20,CreateProject +FN:36,(anonymous_1) +FN:61,(anonymous_2) +FN:62,loadTechs +FN:74,(anonymous_4) +FN:95,(anonymous_5) +FN:114,(anonymous_6) +FN:151,(anonymous_7) +FN:158,(anonymous_8) +FN:170,(anonymous_9) +FNF:10 +FNH:8 +FNDA:13,CreateProject +FNDA:13,(anonymous_1) +FNDA:4,(anonymous_2) +FNDA:4,loadTechs +FNDA:2,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:0,(anonymous_6) +FNDA:15,(anonymous_7) +FNDA:2,(anonymous_8) +FNDA:15,(anonymous_9) +DA:21,13 +DA:22,13 +DA:23,13 +DA:25,13 +DA:28,13 +DA:30,13 +DA:32,13 +DA:36,13 +DA:37,13 +DA:38,6 +DA:40,6 +DA:41,6 +DA:44,13 +DA:55,13 +DA:56,13 +DA:57,13 +DA:58,13 +DA:61,13 +DA:63,4 +DA:64,4 +DA:65,4 +DA:67,0 +DA:70,4 +DA:74,13 +DA:76,2 +DA:81,2 +DA:82,2 +DA:84,1 +DA:85,1 +DA:86,1 +DA:89,1 +DA:90,1 +DA:91,1 +DA:95,2 +DA:96,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:107,13 +DA:114,0 +DA:152,15 +DA:158,2 +DA:171,15 +LF:43 +LH:37 +BRDA:32,0,0,13 +BRDA:32,0,1,7 +BRDA:32,0,2,7 +BRDA:34,1,0,7 +BRDA:34,1,1,0 +BRDA:37,2,0,7 +BRDA:37,2,1,6 +BRDA:40,3,0,0 +BRDA:40,3,1,6 +BRDA:47,4,0,13 +BRDA:47,4,1,7 +BRDA:48,5,0,13 +BRDA:48,5,1,10 +BRDA:49,6,0,13 +BRDA:49,6,1,10 +BRDA:50,7,0,13 +BRDA:50,7,1,7 +BRDA:56,8,0,5 +BRDA:56,8,1,8 +BRDA:82,9,0,1 +BRDA:82,9,1,1 +BRDA:82,10,0,2 +BRDA:82,10,1,1 +BRDA:101,11,0,0 +BRDA:101,11,1,0 +BRDA:110,12,0,13 +BRDA:110,12,1,2 +BRDA:121,13,0,6 +BRDA:121,13,1,7 +BRDA:200,14,0,6 +BRDA:200,14,1,7 +BRF:31 +BRH:27 +end_of_record +TN: +SF:src/pages/EditProfile/index.tsx +FN:13,EditProfile +FN:19,(anonymous_1) +FN:29,(anonymous_2) +FN:39,(anonymous_3) +FN:49,(anonymous_4) +FN:68,(anonymous_5) +FNF:6 +FNH:4 +FNDA:8,EditProfile +FNDA:3,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:2,(anonymous_3) +FNDA:0,(anonymous_4) +FNDA:0,(anonymous_5) +DA:14,8 +DA:15,8 +DA:16,8 +DA:19,8 +DA:20,3 +DA:21,3 +DA:22,3 +DA:23,3 +DA:26,8 +DA:29,8 +DA:30,3 +DA:31,3 +DA:32,3 +DA:33,3 +DA:34,3 +DA:35,3 +DA:39,8 +DA:40,2 +DA:41,2 +DA:42,2 +DA:44,1 +DA:46,1 +DA:49,1 +DA:50,0 +DA:54,1 +DA:55,1 +DA:56,1 +DA:61,8 +DA:68,0 +LF:29 +LH:27 +BRDA:20,0,0,0 +BRDA:20,0,1,3 +BRDA:22,1,0,0 +BRDA:22,1,1,3 +BRDA:30,2,0,3 +BRDA:30,2,1,0 +BRDA:31,3,0,3 +BRDA:31,3,1,0 +BRDA:32,4,0,3 +BRDA:32,4,1,0 +BRDA:33,5,0,3 +BRDA:33,5,1,0 +BRDA:34,6,0,3 +BRDA:34,6,1,0 +BRDA:55,7,0,1 +BRDA:55,7,1,0 +BRDA:64,8,0,8 +BRDA:64,8,1,2 +BRF:18 +BRH:10 +end_of_record +TN: +SF:src/pages/Feed/index.tsx +FN:14,Feed +FN:21,(anonymous_1) +FN:22,loadFeed +FN:39,(anonymous_3) +FN:44,(anonymous_4) +FN:55,(anonymous_5) +FN:59,(anonymous_6) +FN:71,(anonymous_7) +FN:104,(anonymous_8) +FNF:9 +FNH:7 +FNDA:18,Feed +FNDA:6,(anonymous_1) +FNDA:6,loadFeed +FNDA:1,(anonymous_3) +FNDA:1,(anonymous_4) +FNDA:0,(anonymous_5) +FNDA:2,(anonymous_6) +FNDA:2,(anonymous_7) +FNDA:0,(anonymous_8) +DA:15,18 +DA:16,18 +DA:17,18 +DA:18,18 +DA:19,18 +DA:21,18 +DA:23,6 +DA:24,6 +DA:25,6 +DA:26,5 +DA:28,1 +DA:29,1 +DA:30,1 +DA:33,6 +DA:36,6 +DA:39,18 +DA:40,1 +DA:41,1 +DA:44,18 +DA:45,1 +DA:46,1 +DA:49,18 +DA:55,0 +DA:59,2 +DA:72,2 +DA:104,0 +LF:26 +LH:24 +BRDA:26,0,0,5 +BRDA:26,0,1,0 +BRDA:29,1,0,1 +BRDA:29,1,1,0 +BRDA:51,2,0,18 +BRDA:51,2,1,1 +BRDA:65,3,0,12 +BRDA:65,3,1,6 +BRDA:70,4,0,1 +BRDA:70,4,1,5 +BRDA:73,5,0,2 +BRDA:73,5,1,0 +BRDA:73,5,2,0 +BRF:13 +BRH:9 +end_of_record +TN: +SF:src/pages/Feed/styles.ts +FN:5,(anonymous_0) +FN:5,(anonymous_1) +FN:16,(anonymous_2) +FN:17,(anonymous_3) +FN:55,(anonymous_4) +FN:62,(anonymous_5) +FN:87,(anonymous_6) +FN:130,(anonymous_7) +FN:144,(anonymous_8) +FN:151,(anonymous_9) +FN:163,(anonymous_10) +FN:166,(anonymous_11) +FN:170,(anonymous_12) +FN:170,(anonymous_13) +FN:177,(anonymous_14) +FN:195,(anonymous_15) +FN:196,(anonymous_16) +FN:206,(anonymous_17) +FNF:18 +FNH:13 +FNDA:44,(anonymous_0) +FNDA:44,(anonymous_1) +FNDA:44,(anonymous_2) +FNDA:44,(anonymous_3) +FNDA:16,(anonymous_4) +FNDA:16,(anonymous_5) +FNDA:16,(anonymous_6) +FNDA:5,(anonymous_7) +FNDA:5,(anonymous_8) +FNDA:5,(anonymous_9) +FNDA:0,(anonymous_10) +FNDA:0,(anonymous_11) +FNDA:0,(anonymous_12) +FNDA:0,(anonymous_13) +FNDA:0,(anonymous_14) +FNDA:10,(anonymous_15) +FNDA:10,(anonymous_16) +FNDA:10,(anonymous_17) +DA:4,4 +DA:5,44 +DA:16,44 +DA:17,44 +DA:24,4 +DA:51,4 +DA:55,16 +DA:62,16 +DA:87,16 +DA:97,4 +DA:127,4 +DA:130,5 +DA:144,5 +DA:151,5 +DA:160,4 +DA:163,0 +DA:166,0 +DA:170,0 +DA:177,0 +DA:184,4 +DA:195,10 +DA:196,10 +DA:206,10 +LF:23 +LH:19 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/pages/Home/index.tsx +FN:4,Home +FNF:1 +FNH:1 +FNDA:1,Home +DA:5,1 +LF:1 +LH:1 +BRF:0 +BRH:0 +end_of_record +TN: +SF:src/pages/Login/index.tsx +FN:18,LoginPage +FN:25,onSubmit +FN:35,(anonymous_2) +FN:55,(anonymous_3) +FNF:4 +FNH:2 +FNDA:10,LoginPage +FNDA:2,onSubmit +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +DA:19,10 +DA:20,10 +DA:22,10 +DA:23,10 +DA:26,2 +DA:27,2 +DA:28,2 +DA:30,1 +DA:33,1 +DA:35,1 +DA:36,0 +DA:40,1 +DA:43,1 +DA:44,1 +DA:49,10 +DA:55,0 +LF:16 +LH:14 +BRDA:43,0,0,1 +BRDA:43,0,1,0 +BRDA:51,1,0,10 +BRDA:51,1,1,2 +BRF:4 +BRH:3 +end_of_record +TN: +SF:src/pages/Profile/index.tsx +FN:18,(anonymous_0) +FN:24,(anonymous_1) +FN:29,(anonymous_2) +FN:38,Profile +FN:54,(anonymous_4) +FN:57,(anonymous_5) +FN:78,(anonymous_6) +FN:79,handleClickOutside +FN:87,(anonymous_8) +FN:92,(anonymous_9) +FN:97,(anonymous_10) +FN:101,(anonymous_11) +FN:102,(anonymous_12) +FN:106,(anonymous_13) +FN:111,(anonymous_14) +FN:122,(anonymous_15) +FN:131,(anonymous_16) +FN:144,(anonymous_17) +FN:150,(anonymous_18) +FN:159,(anonymous_19) +FN:174,(anonymous_20) +FN:191,(anonymous_21) +FN:203,(anonymous_22) +FN:210,(anonymous_23) +FN:216,(anonymous_24) +FN:216,(anonymous_25) +FN:227,(anonymous_26) +FN:256,(anonymous_27) +FN:266,(anonymous_28) +FNF:29 +FNH:24 +FNDA:40,(anonymous_0) +FNDA:40,(anonymous_1) +FNDA:40,(anonymous_2) +FNDA:42,Profile +FNDA:40,(anonymous_4) +FNDA:40,(anonymous_5) +FNDA:25,(anonymous_6) +FNDA:1,handleClickOutside +FNDA:25,(anonymous_8) +FNDA:1,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:1,(anonymous_11) +FNDA:1,(anonymous_12) +FNDA:1,(anonymous_13) +FNDA:3,(anonymous_14) +FNDA:0,(anonymous_15) +FNDA:0,(anonymous_16) +FNDA:42,(anonymous_17) +FNDA:2,(anonymous_18) +FNDA:2,(anonymous_19) +FNDA:1,(anonymous_20) +FNDA:0,(anonymous_21) +FNDA:0,(anonymous_22) +FNDA:2,(anonymous_23) +FNDA:7,(anonymous_24) +FNDA:7,(anonymous_25) +FNDA:4,(anonymous_26) +FNDA:0,(anonymous_27) +FNDA:1,(anonymous_28) +DA:18,1 +DA:19,40 +DA:24,1 +DA:25,40 +DA:29,1 +DA:30,40 +DA:39,42 +DA:40,42 +DA:41,42 +DA:42,42 +DA:44,42 +DA:47,42 +DA:48,42 +DA:50,42 +DA:51,42 +DA:52,42 +DA:54,42 +DA:56,40 +DA:57,40 +DA:58,40 +DA:60,40 +DA:61,40 +DA:63,39 +DA:65,39 +DA:66,39 +DA:69,1 +DA:73,40 +DA:74,40 +DA:78,42 +DA:80,1 +DA:81,1 +DA:84,25 +DA:85,7 +DA:87,25 +DA:88,25 +DA:92,42 +DA:93,1 +DA:94,1 +DA:97,42 +DA:98,1 +DA:101,1 +DA:102,1 +DA:106,42 +DA:107,1 +DA:108,1 +DA:111,42 +DA:113,3 +DA:114,3 +DA:116,3 +DA:117,3 +DA:118,1 +DA:120,1 +DA:122,1 +DA:123,0 +DA:124,0 +DA:128,2 +DA:129,2 +DA:130,1 +DA:131,1 +DA:132,1 +DA:134,1 +DA:136,1 +DA:138,3 +DA:139,3 +DA:144,42 +DA:145,42 +DA:146,37 +DA:147,35 +DA:150,2 +DA:151,2 +DA:157,5 +DA:159,5 +DA:160,2 +DA:174,1 +DA:180,0 +DA:183,42 +DA:191,0 +DA:203,0 +DA:210,2 +DA:216,7 +DA:228,4 +DA:229,4 +DA:256,0 +DA:266,1 +LF:84 +LH:78 +BRDA:73,0,0,40 +BRDA:73,0,1,0 +BRDA:80,1,0,1 +BRDA:80,1,1,0 +BRDA:80,2,0,1 +BRDA:80,2,1,1 +BRDA:84,3,0,7 +BRDA:84,3,1,18 +BRDA:113,4,0,0 +BRDA:113,4,1,3 +BRDA:128,5,0,2 +BRDA:128,5,1,0 +BRDA:129,6,0,1 +BRDA:129,6,1,1 +BRDA:129,7,0,2 +BRDA:129,7,1,1 +BRDA:145,8,0,37 +BRDA:145,8,1,5 +BRDA:146,9,0,35 +BRDA:146,9,1,2 +BRDA:157,10,0,5 +BRDA:157,10,1,0 +BRDA:164,11,0,2 +BRDA:164,11,1,0 +BRDA:170,12,0,2 +BRDA:170,12,1,0 +BRDA:160,13,0,2 +BRDA:160,13,1,0 +BRDA:187,14,0,42 +BRDA:187,14,1,4 +BRDA:222,15,0,42 +BRDA:222,15,1,7 +BRDA:245,16,0,42 +BRDA:245,16,1,0 +BRDA:256,17,0,0 +BRDA:256,17,1,0 +BRDA:275,18,0,3 +BRDA:275,18,1,39 +BRF:38 +BRH:27 +end_of_record +TN: +SF:src/pages/Profile/styles.ts +FN:5,(anonymous_0) +FN:5,(anonymous_1) +FN:22,(anonymous_2) +FN:62,(anonymous_3) +FN:62,(anonymous_4) +FN:127,(anonymous_5) +FN:127,(anonymous_6) +FN:128,(anonymous_7) +FN:162,(anonymous_8) +FN:165,(anonymous_9) +FN:165,(anonymous_10) +FN:181,(anonymous_11) +FN:215,(anonymous_12) +FN:218,(anonymous_13) +FN:222,(anonymous_14) +FN:237,(anonymous_15) +FN:251,(anonymous_16) +FN:254,(anonymous_17) +FN:272,(anonymous_18) +FNF:19 +FNH:19 +FNDA:40,(anonymous_0) +FNDA:40,(anonymous_1) +FNDA:3,(anonymous_2) +FNDA:40,(anonymous_3) +FNDA:40,(anonymous_4) +FNDA:40,(anonymous_5) +FNDA:40,(anonymous_6) +FNDA:40,(anonymous_7) +FNDA:40,(anonymous_8) +FNDA:40,(anonymous_9) +FNDA:40,(anonymous_10) +FNDA:40,(anonymous_11) +FNDA:120,(anonymous_12) +FNDA:120,(anonymous_13) +FNDA:120,(anonymous_14) +FNDA:120,(anonymous_15) +FNDA:120,(anonymous_16) +FNDA:120,(anonymous_17) +FNDA:120,(anonymous_18) +DA:4,1 +DA:5,40 +DA:10,1 +DA:17,1 +DA:22,3 +DA:40,1 +DA:61,1 +DA:62,40 +DA:91,1 +DA:123,1 +DA:127,40 +DA:128,40 +DA:159,1 +DA:162,40 +DA:165,40 +DA:181,40 +DA:187,1 +DA:203,1 +DA:215,120 +DA:218,120 +DA:222,120 +DA:237,120 +DA:251,120 +DA:254,120 +DA:272,120 +DA:277,1 +LF:26 +LH:26 +BRDA:5,0,0,40 +BRDA:5,0,1,40 +BRDA:62,1,0,40 +BRDA:62,1,1,40 +BRDA:215,2,0,40 +BRDA:215,2,1,80 +BRDA:216,3,0,40 +BRDA:216,3,1,40 +BRDA:218,4,0,40 +BRDA:218,4,1,80 +BRDA:222,5,0,40 +BRDA:222,5,1,80 +BRDA:237,6,0,40 +BRDA:237,6,1,80 +BRDA:251,7,0,40 +BRDA:251,7,1,80 +BRDA:254,8,0,40 +BRDA:254,8,1,80 +BRDA:255,9,0,40 +BRDA:255,9,1,40 +BRDA:256,10,0,80 +BRDA:256,10,1,80 +BRDA:272,11,0,40 +BRDA:272,11,1,80 +BRF:24 +BRH:24 +end_of_record +TN: +SF:src/pages/ProjectPage/index.tsx +FN:9,ProjectPage +FN:14,(anonymous_1) +FN:15,loadData +FN:83,(anonymous_3) +FNF:4 +FNH:4 +FNDA:4,ProjectPage +FNDA:2,(anonymous_1) +FNDA:2,loadData +FNDA:2,(anonymous_3) +DA:10,4 +DA:11,4 +DA:12,4 +DA:14,4 +DA:16,2 +DA:17,2 +DA:18,2 +DA:19,2 +DA:20,2 +DA:22,0 +DA:24,2 +DA:27,2 +DA:30,4 +DA:31,2 +DA:34,1 +DA:36,1 +DA:84,2 +LF:17 +LH:16 +BRDA:16,0,0,0 +BRDA:16,0,1,2 +BRDA:30,1,0,2 +BRDA:30,1,1,2 +BRDA:31,2,0,1 +BRDA:31,2,1,1 +BRDA:53,3,0,1 +BRDA:53,3,1,0 +BRF:8 +BRH:6 +end_of_record +TN: +SF:src/pages/Register/index.tsx +FN:11,Register +FN:19,onSubmit +FN:28,(anonymous_2) +FN:49,(anonymous_3) +FN:91,(anonymous_4) +FNF:5 +FNH:3 +FNDA:8,Register +FNDA:2,onSubmit +FNDA:0,(anonymous_2) +FNDA:0,(anonymous_3) +FNDA:10,(anonymous_4) +DA:13,8 +DA:16,8 +DA:17,8 +DA:20,2 +DA:21,2 +DA:22,2 +DA:24,1 +DA:27,1 +DA:28,1 +DA:29,0 +DA:33,1 +DA:36,1 +DA:37,1 +DA:42,8 +DA:49,0 +DA:92,10 +LF:16 +LH:14 +BRDA:36,0,0,1 +BRDA:36,0,1,0 +BRDA:45,1,0,8 +BRDA:45,1,1,2 +BRF:4 +BRH:3 +end_of_record diff --git a/frontend/coverage/src/API/Comment.ts.html b/frontend/coverage/src/API/Comment.ts.html new file mode 100644 index 0000000..f368e3c --- /dev/null +++ b/frontend/coverage/src/API/Comment.ts.html @@ -0,0 +1,319 @@ + + + + + + Code coverage report for src/API/Comment.ts + + + + + + + + + +
+
+

All files / src/API Comment.ts

+
+ +
+ 4.16% + Statements + 1/24 +
+ + +
+ 0% + Branches + 0/8 +
+ + +
+ 0% + Functions + 0/5 +
+ + +
+ 4.16% + Lines + 1/24 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import api from './api';
+import { isAxiosError } from 'axios';
+export interface CommentProps {
+  projectTitle?: string;
+  commentID?: string;
+  content: string;
+  createdAt?: string;
+  authorID?: string;
+  projectID?: string;
+  username?: string;
+  fullName?: string;
+}
+ 
+const getAuthHeader = () => {
+  return {
+    headers: {
+      'Authorization': `Bearer ${localStorage.getItem('token')}`
+    }
+  };
+};
+ 
+export async function CreateComment(projectId: string, content: string) {
+  try{
+ 
+    const response = await api.post(`/api/project/${projectId}/comments`, 
+      {content},
+      getAuthHeader()
+    );
+ 
+    return response.data;
+ 
+  }catch(error){
+ 
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao enviar comentário.");
+ 
+  }
+}
+ 
+export async function GetComments(projectId: string): Promise<CommentProps[]> {
+  try{
+  
+    const response = await api.get(`/api/project/${projectId}/comments`, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    console.error("Erro ao buscar comentários:", error);
+    throw new Error("Erro ao carregar comentários.");
+  }
+ 
+ 
+}
+ 
+export async function GetUserComments(): Promise<CommentProps[]> {
+  try{
+    const response = await api.get('/api/user/comments', getAuthHeader());
+ 
+    return response.data;
+  }catch(error){
+    console.error("Erro ao buscar comentários do usuário:", error);
+    throw new Error("Erro ao carregar comentários do usuário.");
+  }
+}
+ 
+export async function DeleteComment(commentId: string) {
+  try{
+  
+    const response = await api.delete(`/api/project/${commentId}/deletecomment`, getAuthHeader());
+ 
+    return response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao excluir comentário.");
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/API/Community.ts.html b/frontend/coverage/src/API/Community.ts.html new file mode 100644 index 0000000..46c1b07 --- /dev/null +++ b/frontend/coverage/src/API/Community.ts.html @@ -0,0 +1,451 @@ + + + + + + Code coverage report for src/API/Community.ts + + + + + + + + + +
+
+

All files / src/API Community.ts

+
+ +
+ 2.04% + Statements + 1/49 +
+ + +
+ 0% + Branches + 0/24 +
+ + +
+ 0% + Functions + 0/9 +
+ + +
+ 2.04% + Lines + 1/49 +
+ + +
+

+ 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 +123  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import api from './api';
+import { isAxiosError } from 'axios';
+ 
+export interface CommunityProps {
+    communityID: string;
+    name: string;
+    description: string;
+    technologies: string[];
+    createdAt: Date;
+    updatedAt: Date;
+    memberCount?: number; 
+    isMember?: boolean;
+    isAdmin?: boolean;
+}
+ 
+const getAuthHeader = () => {
+  return {
+    headers: {
+      'Authorization': `Bearer ${localStorage.getItem('token')}`
+    }
+  };
+};
+ 
+export async function NewCommunity(data: CommunityProps) { 
+ 
+    try{
+      console.log("Enviando dados da comunidade:", data);
+      const response = await api.post('/api/newcommunity', data, getAuthHeader());
+      return response.data
+    }catch(error){
+      if (isAxiosError(error) && error.response) {
+          throw new Error(error.response.data.message);
+      }
+      throw new Error("Erro ao criar comunidade.");
+    }
+}
+ 
+export async function GetUserCommunities(): Promise<CommunityProps[]> {
+  try{
+  const response = await api.get<CommunityProps[]>('/api/user/communities', getAuthHeader());
+  return response.data
+  }catch(error){
+    console.error("Erro ao obter comunidades:", error);
+    throw new Error('Erro ao obter comunidades');
+  }
+} 
+ 
+export async function GetCommunityById(communityId: string) {
+  try{
+    const response = await api.get(`/api/communities/data/${communityId}`, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response?.status === 404) {
+          throw new Error('Comunidade não encontrada');
+      }
+    throw new Error('Erro ao carregar a comunidade');
+  }
+}
+ 
+export async function JoinCommunity(communityId: string) {
+  try{
+    const response = await api.post(`/api/communities/${communityId}/join`, {}, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+          throw new Error(error.response.data.message);
+      }
+    throw new Error('Erro ao entrar na comunidade');
+  }
+}
+ 
+export async function DeleteCommunity(communityId: string) {
+  try{
+    const response = await api.delete(`/api/communities/deletecommunity/${communityId}`, getAuthHeader());
+    return response.data
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+          throw new Error(error.response.data.message);
+      }
+    throw new Error("Erro ao excluir comunidade.");
+  }
+}
+ 
+export async function UpdateCommunity(communityId: string, data: CommunityProps) {
+  try{
+    const response = await api.put(`/api/communities/updatecommunity/${communityId}`,
+      data,
+      getAuthHeader()
+    );
+ 
+    return response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+        throw new Error(error.response.data.message);
+      }
+    throw new Error("Erro ao atualizar comunidade.");
+  }
+}
+ 
+export async function LeaveCommunity(communityId: string) {
+  try{
+    const response = await api.delete(`/api/user/leavecommunity/${communityId}`, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+        throw new Error(error.response.data.message);
+      }
+    throw new Error("Erro ao sair da comunidade.");
+  }
+}
+ 
+export async function GetAllCommunities(): Promise<CommunityProps[]> {
+  try{
+    const response = await api.get<CommunityProps[]>('/api/communities', getAuthHeader());
+    return response.data
+  }catch(error){
+    console.error("Erro ao obter todas as comunidades:", error);
+    throw new Error('Erro ao obter todas as comunidades');
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/API/Project.ts.html b/frontend/coverage/src/API/Project.ts.html new file mode 100644 index 0000000..cac4475 --- /dev/null +++ b/frontend/coverage/src/API/Project.ts.html @@ -0,0 +1,415 @@ + + + + + + Code coverage report for src/API/Project.ts + + + + + + + + + +
+
+

All files / src/API Project.ts

+
+ +
+ 7.69% + Statements + 3/39 +
+ + +
+ 0% + Branches + 0/16 +
+ + +
+ 12.5% + Functions + 1/8 +
+ + +
+ 7.69% + Lines + 3/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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +2x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import api from './api';
+import { isAxiosError } from 'axios';
+ 
+export interface ProjectProps {
+  id?: string;
+  title: string;
+  description: string;
+  technologies: string[]; 
+  status: string;
+  startDate: Date;
+  authorUsername?: string; 
+  authorName?: string;
+  creatorID?: number;
+}
+ 
+export function parseDate(dataString: string): Date {
+  // Divide a string "20/11/2025" em partes
+  const [dia, mes, ano] = dataString.split('/');
+ 
+  // Cria a data: new Date(ano, mês - 1, dia)
+  return new Date(Number(ano), Number(mes) - 1, Number(dia));
+}
+ 
+const getAuthHeader = () => {
+  return {
+    headers: {
+      'Authorization': `Bearer ${localStorage.getItem('token')}`
+    }
+  };
+};
+ 
+export async function NewProject(data: ProjectProps) {
+  try{
+    const response = await api.post('/api/user/newproject', data, getAuthHeader());
+ 
+    return response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao criar projeto.");
+  }
+}
+ 
+export async function UpdateProject(projectId: string, data: ProjectProps) {
+  try{
+    const response = await api.put(`/api/user/updateproject/${projectId}`, 
+      data, 
+      getAuthHeader()
+    );
+    return response.data;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao atualizar projeto.");
+  }
+ 
+}
+ 
+export async function GetFeedProjects(): Promise<ProjectProps[]> {
+ 
+  try{
+    const response = await api.get('/api/user/home', getAuthHeader());
+ 
+    console.log("Dados do feed de projetos:", response.data);
+ 
+    return response.data.feed;
+  }catch(error){
+    console.error("Erro ao buscar feed:", error);
+    throw new Error("Erro ao carregar o feed de projetos.");
+  }
+}
+ 
+export async function DeleteProject(projectId: string) {
+  try{
+    await api.delete(`/api/user/deleteproject/${projectId}`, getAuthHeader());
+  }
+  catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao excluir projeto.");
+  }
+}
+ 
+export async function GetUserProjects(): Promise<ProjectProps[]> {
+  try{
+    const response = await api.get('/api/user/projects', getAuthHeader());
+    
+    console.log("Dados dos projetos do usuário:", response.data.projects);
+ 
+    return response.data.projects;
+  }catch(error){
+    if (isAxiosError(error) && error.response) {
+      throw new Error(error.response.data.message);
+    }
+    throw new Error("Erro ao buscar projetos do usuário.");
+  }
+}
+ 
+export async function GetProjectById(projectId: string): Promise<ProjectProps> {
+  try{
+    const response = await api.get(`/api/projects/${projectId}`, getAuthHeader());
+ 
+    return await response.data;
+  }catch(error){
+    console.error("Erro ao buscar projeto:", error);
+    throw new Error('Erro ao carregar projeto');
+  }
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/API/api.ts.html b/frontend/coverage/src/API/api.ts.html new file mode 100644 index 0000000..64a9f63 --- /dev/null +++ b/frontend/coverage/src/API/api.ts.html @@ -0,0 +1,103 @@ + + + + + + Code coverage report for src/API/api.ts + + + + + + + + + +
+
+

All files / src/API api.ts

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 2/2 +
+ + +
+ 100% + Functions + 0/0 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +5x +  +  +  + 
import axios from 'axios';
+ 
+const api = axios.create({
+  baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000',
+});
+ 
+export default api;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/API/index.html b/frontend/coverage/src/API/index.html new file mode 100644 index 0000000..fcd6baf --- /dev/null +++ b/frontend/coverage/src/API/index.html @@ -0,0 +1,161 @@ + + + + + + Code coverage report for src/API + + + + + + + + + +
+
+

All files src/API

+
+ +
+ 5.3% + Statements + 6/113 +
+ + +
+ 4% + Branches + 2/50 +
+ + +
+ 4.54% + Functions + 1/22 +
+ + +
+ 5.3% + Lines + 6/113 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
Comment.ts +
+
4.16%1/240%0/80%0/54.16%1/24
Community.ts +
+
2.04%1/490%0/240%0/92.04%1/49
Project.ts +
+
7.69%3/390%0/1612.5%1/87.69%3/39
api.ts +
+
100%1/1100%2/2100%0/0100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/App.tsx.html b/frontend/coverage/src/App.tsx.html new file mode 100644 index 0000000..630a562 --- /dev/null +++ b/frontend/coverage/src/App.tsx.html @@ -0,0 +1,142 @@ + + + + + + Code coverage report for src/App.tsx + + + + + + + + + +
+
+

All files / src App.tsx

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  + 
import { ThemeProvider } from "styled-components"
+import { defaultTheme } from './styles/themes/default'
+import { GlobalStyle } from './styles/global'
+import { Router } from "./Router"
+import { BrowserRouter } from "react-router-dom"
+ 
+function App() {
+ 
+  return (
+    <ThemeProvider theme={defaultTheme}>
+      <BrowserRouter>
+        <GlobalStyle/>
+        <Router />
+      </BrowserRouter>
+    </ThemeProvider>
+  )
+}
+ 
+export default App
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/common/Keyword/index.html b/frontend/coverage/src/components/common/Keyword/index.html new file mode 100644 index 0000000..e54d4fc --- /dev/null +++ b/frontend/coverage/src/components/common/Keyword/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/common/Keyword + + + + + + + + + +
+
+

All files src/components/common/Keyword

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%3/3100%0/0100%1/1100%3/3
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/common/Keyword/index.tsx.html b/frontend/coverage/src/components/common/Keyword/index.tsx.html new file mode 100644 index 0000000..bce4e54 --- /dev/null +++ b/frontend/coverage/src/components/common/Keyword/index.tsx.html @@ -0,0 +1,145 @@ + + + + + + Code coverage report for src/components/common/Keyword/index.tsx + + + + + + + + + +
+
+

All files / src/components/common/Keyword index.tsx

+
+ +
+ 100% + Statements + 3/3 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 3/3 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +1x +2x +  +  +  +  +  +  +  +  +  +1x
import React from 'react';
+import * as S from './styles';
+ 
+// Props que o componente Keyword aceita
+interface KeywordProps {
+  children: React.ReactNode;
+  onRemove: () => void;
+}
+ 
+export const Keyword: React.FC<KeywordProps> = ({ children, onRemove }) => {
+  return (
+    <S.KeywordTag>
+      {children}
+      <S.KeywordRemoveButton onClick={onRemove} aria-label={`Remover ${children}`}>
+        &times;
+      </S.KeywordRemoveButton>
+    </S.KeywordTag>
+  );
+};
+ 
+export const KeywordContainer = S.KeywordContainer;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/common/Modal/index.html b/frontend/coverage/src/components/common/Modal/index.html new file mode 100644 index 0000000..035bbda --- /dev/null +++ b/frontend/coverage/src/components/common/Modal/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/common/Modal + + + + + + + + + +
+
+

All files src/components/common/Modal

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%12/12100%4/4100%4/4100%12/12
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/common/Modal/index.tsx.html b/frontend/coverage/src/components/common/Modal/index.tsx.html new file mode 100644 index 0000000..019b982 --- /dev/null +++ b/frontend/coverage/src/components/common/Modal/index.tsx.html @@ -0,0 +1,223 @@ + + + + + + Code coverage report for src/components/common/Modal/index.tsx + + + + + + + + + +
+
+

All files / src/components/common/Modal index.tsx

+
+ +
+ 100% + Statements + 12/12 +
+ + +
+ 100% + Branches + 4/4 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 12/12 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +1x +  +5x +5x +4x +  +1x +  +  +5x +5x +  +  +  +5x +1x +  +  +  +4x +2x +  +  +4x +  +  +  +  +  +  +  +  +  +  +  + 
import React, { useEffect } from 'react';
+import { createPortal } from 'react-dom';
+import * as S from './styles';
+ 
+interface ModalProps {
+  isOpen: boolean;
+  onClose: () => void;
+  children: React.ReactNode;
+  title: string;
+}
+ 
+const Modal: React.FC<ModalProps> = ({ isOpen, onClose, title, children }) => {
+  // Bloqueia o scroll do body quando o modal está aberto
+  useEffect(() => {
+    if (isOpen) {
+      document.body.style.overflow = 'hidden';
+    } else {
+      document.body.style.overflow = 'unset';
+    }
+    
+    return () => {
+      document.body.style.overflow = 'unset';
+    };
+  }, [isOpen]);
+ 
+  if (!isOpen) {
+    return null;
+  }
+ 
+  // Impede que o clique no modal feche o modal (só o overlay)
+  const handleContentClick = (e: React.MouseEvent) => {
+    e.stopPropagation();
+  };
+ 
+  return createPortal(
+    <S.ModalOverlay onClick={onClose}>
+      <S.ModalContent onClick={handleContentClick}>
+        <S.CloseButton onClick={onClose}>&times;</S.CloseButton>
+        <S.ModalTitle>{title}</S.ModalTitle>
+        {children}
+      </S.ModalContent>
+    </S.ModalOverlay>,
+    document.body
+  );
+};
+ 
+export default Modal;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/common/Toast/index.html b/frontend/coverage/src/components/common/Toast/index.html new file mode 100644 index 0000000..ba638cd --- /dev/null +++ b/frontend/coverage/src/components/common/Toast/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/common/Toast + + + + + + + + + +
+
+

All files src/components/common/Toast

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%7/7100%0/0100%4/4100%7/7
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/common/Toast/index.tsx.html b/frontend/coverage/src/components/common/Toast/index.tsx.html new file mode 100644 index 0000000..1dd3cce --- /dev/null +++ b/frontend/coverage/src/components/common/Toast/index.tsx.html @@ -0,0 +1,199 @@ + + + + + + Code coverage report for src/components/common/Toast/index.tsx + + + + + + + + + +
+
+

All files / src/components/common/Toast index.tsx

+
+ +
+ 100% + Statements + 7/7 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 100% + Lines + 7/7 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +4x +4x +1x +  +  +  +4x +4x +  +  +  +4x +  +  +  +  +  +  +  +  +  + 
import React, { useEffect } from 'react';
+import { ToastContainer, ToastMessage, CloseButton } from './styles';
+ 
+interface ToastProps {
+  message: string;
+  type: 'success' | 'error';
+  onClose: () => void; // Função para fechar o toast
+}
+ 
+export interface NotificationState {
+  message: string;
+  type: 'success' | 'error';
+}
+ 
+const Toast: React.FC<ToastProps> = ({ message, type, onClose }) => {
+  
+  // Efeito para fechar o toast automaticamente após 5 segundos
+  useEffect(() => {
+    const timer = setTimeout(() => {
+      onClose();
+    }, 5000); 
+ 
+    // Limpa o timer se o componente for desmontado 
+    return () => {
+      clearTimeout(timer);
+    };
+  }, [onClose]);
+ 
+  return (
+    <ToastContainer type={type}>
+      <ToastMessage>{message}</ToastMessage>
+      <CloseButton onClick={onClose}>
+        &times; 
+      </CloseButton>
+    </ToastContainer>
+  );
+};
+ 
+export default Toast;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/domain/CreationForm/index.html b/frontend/coverage/src/components/domain/CreationForm/index.html new file mode 100644 index 0000000..829d38b --- /dev/null +++ b/frontend/coverage/src/components/domain/CreationForm/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/domain/CreationForm + + + + + + + + + +
+
+

All files src/components/domain/CreationForm

+
+ +
+ 87.32% + Statements + 62/71 +
+ + +
+ 85.71% + Branches + 12/14 +
+ + +
+ 84.48% + Functions + 49/58 +
+ + +
+ 86.95% + Lines + 60/69 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
styles.ts +
+
87.32%62/7185.71%12/1484.48%49/5886.95%60/69
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/domain/CreationForm/styles.ts.html b/frontend/coverage/src/components/domain/CreationForm/styles.ts.html new file mode 100644 index 0000000..b43ceb0 --- /dev/null +++ b/frontend/coverage/src/components/domain/CreationForm/styles.ts.html @@ -0,0 +1,1390 @@ + + + + + + Code coverage report for src/components/domain/CreationForm/styles.ts + + + + + + + + + +
+
+

All files / src/components/domain/CreationForm styles.ts

+
+ +
+ 87.32% + Statements + 62/71 +
+ + +
+ 85.71% + Branches + 12/14 +
+ + +
+ 84.48% + Functions + 49/58 +
+ + +
+ 86.95% + Lines + 60/69 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436  +  +  +2x +20x +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +86x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +86x +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +33x +  +  +33x +  +  +  +  +  +33x +  +  +  +  +33x +33x +  +  +  +  +33x +33x +33x +  +  +  +  +  +2x +  +  +  +  +  +  +  +13x +  +  +  +  +  +  +  +  +  +13x +  +  +  +13x +  +  +  +  +  +2x +  +  +  +  +13x +  +  +13x +  +  +  +  +  +  +  +  +  +  +  +  +13x +13x +  +  +  +  +13x +13x +13x +  +  +  +  +  +13x +  +  +  +  +13x +13x +  +  +  +  +2x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +20x +20x +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +20x +  +  +20x +  +  +  +  +  +  +  +20x +  +  +  +  +20x +20x +  +  +  +  +20x +20x +20x +  +  +  +  +  +  +  +  +  +  +20x +  +  +  +  +20x +  +  +  +  +20x +  +  +  +  +2x +  +  +20x +  +  +  +  +20x +  +  +  +  +  +  +20x +20x +  +  +  +20x +20x +  + 
import styled from 'styled-components';
+ 
+// O <form> container
+export const FormContainer = styled.form`
+  background: ${props => props.theme.white};
+  border-radius: 24px;
+  padding: 40px;
+  width: 100%;
+  max-width: 800px;
+  margin: 0 auto;
+  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08),
+              0 2px 8px rgba(0, 0, 0, 0.04);
+  border: 1px solid ${props => props.theme.placeholder}20;
+  
+  animation: slideUp 0.5s ease-out;
+  
+  @keyframes slideUp {
+    from {
+      opacity: 0;
+      transform: translateY(20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+`;
+ 
+// Wrapper para cada par de (label + input)
+export const InputGroup = styled.div`
+  margin-bottom: 28px;
+  width: 100%;
+  
+  animation: fadeIn 0.4s ease-out backwards;
+  animation-delay: calc(var(--index, 0) * 0.05s);
+  
+  @keyframes fadeIn {
+    from {
+      opacity: 0;
+      transform: translateY(10px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+`;
+ 
+// Label 
+export const Label = styled.label`
+  display: block;
+  font-size: 0.95em;
+  font-weight: 700;
+  color: ${props => props.theme.title}; 
+  margin-bottom: 10px;
+  text-transform: uppercase;
+  letter-spacing: 0.5px;
+  font-size: 0.85rem;
+  padding-left: 4px;
+  
+  /* Indicador visual opcional */
+  position: relative;
+  
+  &::after {
+    content: '';
+    position: absolute;
+    left: -12px;
+    top: 50%;
+    transform: translateY(-50%);
+    width: 3px;
+    height: 14px;
+    background: linear-gradient(180deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.button} 100%);
+    border-radius: 2px;
+    opacity: 0;
+    transition: opacity 0.2s ease;
+  }
+  
+  ${InputGroup}:focus-within &::after {
+    opacity: 1;
+  }
+`;
+ 
+// Input 
+export const Input = styled.input`
+  width: 100%;
+  padding: 14px 20px;
+  font-size: 1em;
+  
+  background-color: ${props => props.theme['gray-100']};
+  border: 2px solid transparent;
+  border-radius: 12px;
+  color: ${props => props.theme.title};
+  box-sizing: border-box;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  font-weight: 500;
+ 
+  &::placeholder {
+    color: ${props => props.theme.placeholder};
+    font-weight: 400;
+  }
+  
+  &:hover {
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.placeholder}40;
+  }
+  
+  &:focus {
+    outline: none;
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.button};
+    box-shadow: 0 0 0 4px ${props => props.theme.button}15,
+                0 2px 8px rgba(0, 0, 0, 0.04);
+    transform: translateY(-1px);
+  }
+`;
+ 
+export const SelectWrapper = styled.div`
+  position: relative;
+  width: 100%;
+ 
+  /* A seta de seleção (CSS) */
+  &::after {
+    content: '▼';
+    font-size: 0.85em;
+    color: ${props => props.theme.placeholder};
+    position: absolute;
+    right: 20px;
+    top: 50%;
+    transform: translateY(-50%);
+    pointer-events: none;
+    transition: all 0.3s ease;
+  }
+  
+  &:hover::after {
+    color: ${props => props.theme.button};
+  }
+  
+  &:focus-within::after {
+    color: ${props => props.theme.button};
+    transform: translateY(-50%) rotate(180deg);
+  }
+`;
+ 
+// Componente de Select 
+export const Select = styled.select`
+  width: 100%;
+  padding: 14px 20px;
+  font-size: 1em;
+  
+  background-color: ${props => props.theme['gray-100']};
+  border: 2px solid transparent;
+  border-radius: 12px;
+  color: ${props => props.theme.title};
+  box-sizing: border-box;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  font-weight: 500;
+  cursor: pointer;
+ 
+  appearance: none;
+  -webkit-appearance: none;
+  -moz-appearance: none;
+ 
+  padding-right: 50px;
+  
+  &:hover {
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.placeholder}40;
+  }
+ 
+  &:focus {
+    outline: none;
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.button};
+    box-shadow: 0 0 0 4px ${props => props.theme.button}15,
+                0 2px 8px rgba(0, 0, 0, 0.04);
+    transform: translateY(-1px);
+  }
+ 
+  &:invalid {
+    color: ${props => props.theme.placeholder};
+  }
+  
+  option {
+    padding: 10px;
+    background: ${props => props.theme.white};
+    color: ${props => props.theme.title};
+  }
+`;
+ 
+// Wrapper para o input de busca E a lista de resultados 
+export const SearchWrapper = styled.div`
+  position: relative;
+  width: 100%;
+`;
+ 
+// Lista de resultados de busca que aparece abaixo do input 
+export const SearchResultsList = styled.ul`
+  position: absolute;
+  top: calc(100% + 4px);
+  left: 0;
+  right: 0;
+  background: ${props => props.theme.white};
+  border: 2px solid ${props => props.theme.button}20;
+  border-radius: 12px;
+  max-height: 240px;
+  overflow-y: auto;
+  margin: 0;
+  padding: 6px;
+  z-index: 100;
+  list-style: none;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12),
+              0 2px 8px rgba(0, 0, 0, 0.08);
+  
+  animation: slideDown 0.2s ease-out;
+  
+  @keyframes slideDown {
+    from {
+      opacity: 0;
+      transform: translateY(-8px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+  
+  /* Estilização da scrollbar */
+  &::-webkit-scrollbar {
+    width: 8px;
+  }
+ 
+  &::-webkit-scrollbar-track {
+    background: transparent;
+  }
+ 
+  &::-webkit-scrollbar-thumb {
+    background: ${props => props.theme['gray-300']};
+    border-radius: 4px;
+  }
+ 
+  &::-webkit-scrollbar-thumb:hover {
+    background: ${props => props.theme['gray-400']};
+  }
+`;
+ 
+// Item individual na lista de resultados 
+export const SearchResultItem = styled.li`
+  padding: 12px 16px;
+  cursor: pointer;
+  border-radius: 8px;
+  color: ${props => props.theme.title};
+  font-weight: 500;
+  transition: all 0.2s ease;
+  position: relative;
+  
+  /* Barra lateral que aparece no hover */
+  &::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 0;
+    bottom: 0;
+    width: 3px;
+    background: ${props => props.theme.button};
+    border-radius: 0 2px 2px 0;
+    transform: scaleY(0);
+    transition: transform 0.2s ease;
+  }
+ 
+  &:hover {
+    background-color: ${props => props.theme['gray-100']};
+    padding-left: 20px;
+    
+    &::before {
+      transform: scaleY(1);
+    }
+  }
+  
+  &:active {
+    background-color: ${props => props.theme['gray-100']};
+  }
+`;
+ 
+// Mensagem de erro 
+export const ErrorMessage = styled.span`
+  font-size: 0.85em;
+  margin-top: 8px;
+  color: ${props => props.theme['red-500'] || '#ef4444'};
+  font-weight: 600;
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  padding-left: 4px;
+  
+  /* Ícone de alerta */
+  &::before {
+    content: '⚠';
+    font-size: 1.1em;
+  }
+`;
+ 
+// Botão de submissão
+export const SubmitButton = styled.button`
+  padding: 16px 40px;
+  font-size: 1.05em;
+  font-weight: 700;
+  color: ${props => props.theme.white};
+  background: linear-gradient(135deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.button} 100%);
+  border: none;
+  border-radius: 12px;
+  cursor: pointer;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  margin-top: 16px;
+  box-shadow: 0 4px 16px ${props => props.theme.button}40;
+  position: relative;
+  overflow: hidden;
+  
+  /* Efeito de brilho deslizante */
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -100%;
+    width: 100%;
+    height: 100%;
+    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
+    transition: left 0.5s;
+  }
+  
+  &:hover::before {
+    left: 100%;
+  }
+ 
+  &:hover {
+    transform: translateY(-3px);
+    box-shadow: 0 8px 24px ${props => props.theme.button}50;
+  }
+  
+  &:active {
+    transform: translateY(-1px);
+  }
+  
+  &:disabled {
+    opacity: 0.6;
+    cursor: not-allowed;
+    transform: none;
+    box-shadow: 0 2px 8px ${props => props.theme.button}20;
+    
+    &:hover {
+      transform: none;
+    }
+  }
+`;
+ 
+// Estilo para o campo de texto de várias linhas (Descrição)
+export const TextArea = styled.textarea`
+  width: 100%;
+  padding: 16px 20px;
+  font-size: 1em;
+  font-family: inherit;
+  line-height: 1.6;
+  
+  background-color: ${props => props.theme['gray-100']};
+  border: 2px solid transparent;
+  border-radius: 12px;
+  color: ${props => props.theme.title};
+  box-sizing: border-box;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  resize: vertical;
+  min-height: 150px;
+  font-weight: 500;
+ 
+  &::placeholder {
+    color: ${props => props.theme.placeholder};
+    font-weight: 400;
+  }
+  
+  &:hover {
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.placeholder}40;
+  }
+  
+  &:focus {
+    outline: none;
+    background-color: ${props => props.theme.white};
+    border-color: ${props => props.theme.button};
+    box-shadow: 0 0 0 4px ${props => props.theme.button}15,
+                0 2px 8px rgba(0, 0, 0, 0.04);
+    transform: translateY(-1px);
+  }
+  
+  /* Estilização da scrollbar */
+  &::-webkit-scrollbar {
+    width: 10px;
+  }
+ 
+  &::-webkit-scrollbar-track {
+    background: ${props => props.theme['gray-100']};
+    border-radius: 0 10px 10px 0;
+  }
+ 
+  &::-webkit-scrollbar-thumb {
+    background: ${props => props.theme['gray-300']};
+    border-radius: 10px;
+  }
+ 
+  &::-webkit-scrollbar-thumb:hover {
+    background: ${props => props.theme.button};
+  }
+`;
+ 
+// Contador de caracteres
+export const CharacterCount = styled.div`
+  text-align: right;
+  font-size: 0.85em;
+  color: ${props => props.theme['gray-500'] || props.theme.placeholder};
+  margin-top: 6px;
+  margin-right: 4px;
+  font-weight: 600;
+  padding: 4px 8px;
+  background: ${props => props.theme['gray-100']};
+  border-radius: 6px;
+  display: inline-block;
+  float: right;
+  
+  /* Muda de cor quando próximo do limite */
+  &[data-warning="true"] {
+    color: ${props => props.theme['yellow-600'] || '#d97706'};
+    background: ${props => props.theme['yellow-50'] || '#fef3c7'};
+  }
+  
+  &[data-limit="true"] {
+    color: ${props => props.theme['red-500'] || '#ef4444'};
+    background: ${props =>  '#fee2e2'};
+  }
+`;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/domain/Postcard/index.html b/frontend/coverage/src/components/domain/Postcard/index.html new file mode 100644 index 0000000..ed8f8a5 --- /dev/null +++ b/frontend/coverage/src/components/domain/Postcard/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/domain/Postcard + + + + + + + + + +
+
+

All files src/components/domain/Postcard

+
+ +
+ 69.23% + Statements + 72/104 +
+ + +
+ 58.9% + Branches + 43/73 +
+ + +
+ 64.28% + Functions + 18/28 +
+ + +
+ 72.16% + Lines + 70/97 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
69.23%72/10458.9%43/7364.28%18/2872.16%70/97
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/domain/Postcard/index.tsx.html b/frontend/coverage/src/components/domain/Postcard/index.tsx.html new file mode 100644 index 0000000..df2ed3a --- /dev/null +++ b/frontend/coverage/src/components/domain/Postcard/index.tsx.html @@ -0,0 +1,1132 @@ + + + + + + Code coverage report for src/components/domain/Postcard/index.tsx + + + + + + + + + +
+
+

All files / src/components/domain/Postcard index.tsx

+
+ +
+ 69.23% + Statements + 72/104 +
+ + +
+ 58.9% + Branches + 43/73 +
+ + +
+ 64.28% + Functions + 18/28 +
+ + +
+ 72.16% + Lines + 70/97 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +1x +21x +  +  +  +  +  +  +1x +12x +  +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +21x +21x +21x +21x +21x +  +  +21x +21x +21x +21x +21x +  +21x +  +21x +  +21x +10x +2x +  +  +  +  +2x +2x +2x +  +  +  +  +  +  +21x +  +  +  +  +  +13x +4x +  +13x +13x +  +  +  +21x +1x +  +1x +1x +  +  +  +  +  +21x +2x +2x +  +2x +  +2x +  +  +2x +1x +  +  +1x +1x +  +  +1x +  +  +  +21x +1x +  +1x +  +  +  +  +1x +  +1x +1x +1x +  +1x +1x +1x +  +  +  +  +  +  +1x +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +21x +  +12x +  +  +12x +  +  +12x +  +  +  +  +  +  +12x +  +  +  +  +  +  +  +  +21x +1x +  +  +  +  +  +21x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +2x +2x +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import React, { useState, useRef, useEffect } from 'react';
+import * as S from './styles';
+import * as D from '../../common/Dropdown/styles'; 
+import { useNavigate } from 'react-router-dom'; 
+import type { ProjectProps } from '../../../API/Project';
+import { DeleteProject } from '../../../API/Project';
+import Modal from '../../common/Modal';
+import type { NotificationState } from '../../common/Toast';
+import Toast from '../../common/Toast';
+import * as ModalS from '../../common/Modal/styles';
+import { CreateComment, GetComments, DeleteComment } from '../../../API/Comment';
+import type { CommentProps } from '../../../API/Comment';
+import { useAuth } from '../../../API/AuthContext';
+ 
+const TrashIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <polyline points="3 6 5 6 21 6"></polyline>
+    <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
+  </svg>
+);
+ 
+// Ícone de Comentário (Balão)
+const CommentIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/>
+  </svg>
+);
+ 
+ 
+// --- Ícone de Menu (Ellipsis) ---
+const EllipsisIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" />
+  </svg>
+);
+ 
+interface PostcardProps {
+  post: ProjectProps; 
+  showMenu: boolean;         // Verifica se o menu deve ser mostrado (se é dono do post)
+  onDelete?: (id: string) => Promise<void>; 
+  deleteLabel?: string;
+}
+ 
+// --- Componente Postcard ---
+export default function Postcard({ post, showMenu, onDelete, deleteLabel = 'Projeto' }: PostcardProps) {
+  const { currentUser } = useAuth();
+ 
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+  const menuRef = useRef<HTMLDivElement>(null);
+  const navigate = useNavigate(); // Inicialize o hook de navegação
+  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); // Estado para o modal de exclusão
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+  // Estados para o formulário de comentário
+  const [isCommentBoxOpen, setIsCommentBoxOpen] = useState(false);
+  const [commentText, setCommentText] = useState("");
+  const [isSubmittingComment, setIsSubmittingComment] = useState(false);
+  const MAX_COMMENT_CHARS = 500;
+  const [comments, setComments] = useState<CommentProps[]>([]);
+ 
+  const [commentToDelete, setCommentToDelete] = useState<string | null>(null);
+ 
+  const projectId = (post as any).id || (post as any).projectID;
+ 
+  useEffect(() => {
+    if (isCommentBoxOpen && projectId) {
+        loadComments();
+    }
+  }, [isCommentBoxOpen, projectId]);
+ 
+  async function loadComments() {
+      try {
+          const data = await GetComments(projectId);
+          setComments(data);
+      } catch (error) {
+          console.error("Erro ao carregar comentários", error);
+      }
+  }
+ 
+  // Lógica para fechar o menu ao clicar fora (sem alterações)
+  useEffect(() => {
+    function handleClickOutside(event: MouseEvent) {
+      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
+        setIsMenuOpen(false);
+      }
+    }
+    if (isMenuOpen) {
+      document.addEventListener('mousedown', handleClickOutside);
+    }
+    return () => {
+      document.removeEventListener('mousedown', handleClickOutside);
+    };
+  }, [isMenuOpen]);
+ 
+  const handleEditClick = () => {
+    const projectId = (post as any).id || (post as any).projectID;
+    
+    if (projectId) {
+        navigate(`/editProject/${projectId}`, { state: { projectToEdit: post } });
+    } else E{
+        console.error("Erro: ID do projeto não encontrado no objeto:", post);
+    }
+  };
+ 
+  const handleDeleteMainItem = async () => {
+    try {
+       const id = (post as any).id || (post as any).projectID || (post as any).commentID;
+       
+       Iif (!id) throw new Error("ID não encontrado.");
+ 
+       Iif (onDelete) {
+           await onDelete(id);
+       } else {
+           await DeleteProject(id);
+           setTimeout(() => navigate('/feed'), 1000);
+       }
+       
+       setNotification({ message: `${deleteLabel} excluído com sucesso!`, type: 'success' });
+       setIsDeleteModalOpen(false);
+ 
+    } catch (error) {
+      setNotification({ message: `Erro ao excluir ${deleteLabel?.toLowerCase()}.`, type: 'error' });
+    }
+  };
+ 
+  const handleCommentSubmit = async (e: React.FormEvent) => {
+    e.preventDefault();
+    
+    Iif (!projectId) {
+        setNotification({ message: 'Erro: Projeto sem ID.', type: 'error' });
+        return;
+    }
+ 
+    Iif (!commentText.trim()) return;
+ 
+    try {
+        setIsSubmittingComment(true);
+        await CreateComment(projectId, commentText);
+        
+        setNotification({ message: 'Comentário enviado!', type: 'success' });
+        setCommentText(""); // Limpa o campo
+        setIsCommentBoxOpen(false); 
+ 
+    } catch (error) {
+        if (error instanceof Error) {
+            setNotification({ message: error.message, type: 'error' });
+        }
+    } finally {
+        setIsSubmittingComment(false);
+    }
+  };
+ 
+  const handleConfirmDeleteInternalComment = async () => {
+    if (!commentToDelete) return;
+    try {
+        await DeleteComment(commentToDelete);
+        setNotification({ message: 'Comentário excluído.', type: 'success' });
+        setCommentToDelete(null); 
+        await loadComments(); 
+    } catch (error: any) {
+        setNotification({ message: error.message, type: 'error' });
+        setCommentToDelete(null);
+    }
+  };
+ 
+  const handleCardClick = (e: React.MouseEvent) => {
+    // Não navega se estiver na aba de comentários do perfil (deleteLabel 'Comentário')
+    Iif (deleteLabel !== 'Projeto') return;
+ 
+    // Não navega se o clique foi em um elemento interativo
+    const target = e.target as HTMLElement;
+    
+    // Verifica se clicou em botões, inputs, links ou no próprio menu
+    Eif (
+        target.closest('button') || 
+        target.closest('input') || 
+        target.closest('textarea') ||
+        target.closest('a') ||
+        target.closest(D.DropdownMenu as any) // Garante que itens do dropdown não disparem
+    ) {
+        return;
+    }
+ 
+    // Realiza a navegação
+    if (projectId) {
+        navigate(`/project/${projectId}`);
+    }
+  };
+ 
+  const formatDate = (dateString?: string) => {
+      Eif (!dateString) return "";
+      return new Date(dateString).toLocaleDateString('pt-BR', {
+          day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit'
+      });
+  };
+ 
+  return (
+    <S.PostCardWrapper onClick={handleCardClick}>
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+      
+      <S.PostHeader>
+        <img src={(post as any).avatarUrl || 'url_placeholder_avatar.png'} alt={post.title} /> 
+        <span>{post.title}</span> 
+        <small>• {(post as any).author?.title || 'Autor'}</small> 
+      </S.PostHeader>
+ 
+      <S.PostContent>
+        {showMenu && (
+          <S.MenuWrapper ref={menuRef}>
+            <S.MenuButton onClick={() => setIsMenuOpen(prev => !prev)}>
+              <EllipsisIcon />
+            </S.MenuButton>
+ 
+            {isMenuOpen && (
+              <D.DropdownMenu>
+                {deleteLabel === 'Projeto' && (
+                    <D.MenuItem onClick={handleEditClick}>Editar</D.MenuItem>
+                )}
+                <D.DangerMenuItem onClick={() => {
+                    setIsMenuOpen(false);
+                    setIsDeleteModalOpen(true);}}>
+                    Excluir
+                </D.DangerMenuItem>
+              </D.DropdownMenu>
+            )}
+          </S.MenuWrapper>
+        )}
+ 
+        <p>{post.description}</p>
+ 
+        <S.ActionRow>
+            <S.ActionButton onClick={() => setIsCommentBoxOpen(!isCommentBoxOpen)}>
+                <CommentIcon />
+                <span>Comentar</span>
+            </S.ActionButton>
+        </S.ActionRow>
+ 
+        {isCommentBoxOpen && (
+            <>
+                <S.CommentForm onSubmit={handleCommentSubmit}>
+                    <S.CommentTextArea 
+                        placeholder="Escreva seu comentário..."
+                        value={commentText}
+                        onChange={(e) => setCommentText(e.target.value)}
+                        maxLength={MAX_COMMENT_CHARS}
+                        disabled={isSubmittingComment}
+                    />
+                    <S.CommentFooter>
+                        <S.CharacterCount isLimit={commentText.length >= MAX_COMMENT_CHARS}>
+                            {commentText.length} / {MAX_COMMENT_CHARS}
+                        </S.CharacterCount>
+                        <S.SubmitCommentButton 
+                            type="submit" 
+                            disabled={isSubmittingComment || !commentText.trim()}
+                        >
+                            {isSubmittingComment ? 'Enviando...' : 'Enviar'}
+                        </S.SubmitCommentButton>
+                    </S.CommentFooter>
+                </S.CommentForm>
+ 
+                {/* LISTA DE COMENTÁRIOS */}
+                {comments.length > 0 && (
+                    <S.CommentsSection>
+                        {comments.map((comment) => {
+                            // Verifica se o usuário atual é o autor do comentário
+                            const isAuthor = currentUser?.id && String(currentUser.id) === String(comment.authorID);
+ 
+                            return (
+                                <S.CommentItem key={comment.commentID || Math.random()}>
+                                    <S.CommentAvatar /> 
+                                    <S.CommentBubble>
+                                        <S.CommentHeader>
+                                            <div style={{ display: 'flex', gap: '8px', alignItems: 'center' }}>
+                                                <strong>{comment.username || "Usuário"}</strong>
+                                                <span>{formatDate(comment.createdAt)}</span>
+                                            </div>
+                                            
+                                            {/* Botão de Deletar (Só aparece para o dono) */}
+                                            {isAuthor && (
+                                                <S.DeleteCommentButton 
+                                                    onClick={() => setCommentToDelete(comment.commentID!)}
+                                                    title="Excluir comentário"
+                                                >
+                                                    <TrashIcon />
+                                                </S.DeleteCommentButton>
+                                            )}
+                                        </S.CommentHeader>
+                                        <S.CommentText>{comment.content}</S.CommentText>
+                                    </S.CommentBubble>
+                                </S.CommentItem>
+                            );
+                        })}
+                    </S.CommentsSection>
+                )}
+            </>
+        )}
+ 
+      </S.PostContent>
+      <Modal 
+        isOpen={isDeleteModalOpen} 
+        onClose={() => setIsDeleteModalOpen(false)}
+        title={`Excluir ${deleteLabel}`}
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Tem certeza que deseja excluir este {deleteLabel?.toLowerCase()}?
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton onClick={() => setIsDeleteModalOpen(false)}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton onClick={handleDeleteMainItem} style={{ backgroundColor: '#e74c3c' }}>
+                    Excluir
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+ 
+      <Modal 
+        isOpen={!!commentToDelete} 
+        onClose={() => setCommentToDelete(null)}
+        title="Excluir Comentário"
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Deseja realmente apagar este comentário?
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton onClick={() => setCommentToDelete(null)}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton 
+                    onClick={handleConfirmDeleteInternalComment}
+                    style={{ backgroundColor: '#e74c3c' }}
+                >
+                    Excluir
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+ 
+    </S.PostCardWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/domain/Searchbar/index.html b/frontend/coverage/src/components/domain/Searchbar/index.html new file mode 100644 index 0000000..dcebc50 --- /dev/null +++ b/frontend/coverage/src/components/domain/Searchbar/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/domain/Searchbar + + + + + + + + + +
+
+

All files src/components/domain/Searchbar

+
+ +
+ 91.07% + Statements + 51/56 +
+ + +
+ 83.33% + Branches + 30/36 +
+ + +
+ 78.94% + Functions + 15/19 +
+ + +
+ 90.9% + Lines + 50/55 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
91.07%51/5683.33%30/3678.94%15/1990.9%50/55
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/domain/Searchbar/index.tsx.html b/frontend/coverage/src/components/domain/Searchbar/index.tsx.html new file mode 100644 index 0000000..6073314 --- /dev/null +++ b/frontend/coverage/src/components/domain/Searchbar/index.tsx.html @@ -0,0 +1,568 @@ + + + + + + Code coverage report for src/components/domain/Searchbar/index.tsx + + + + + + + + + +
+
+

All files / src/components/domain/Searchbar index.tsx

+
+ +
+ 91.07% + Statements + 51/56 +
+ + +
+ 83.33% + Branches + 30/36 +
+ + +
+ 78.94% + Functions + 15/19 +
+ + +
+ 90.9% + Lines + 50/55 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162  +  +  +  +  +  +  +  +  +  +  +47x +47x +  +47x +  +47x +47x +  +  +47x +47x +  +  +47x +47x +  +47x +6x +6x +6x +6x +  +6x +  +  +  +  +6x +6x +  +  +  +6x +  +  +  +  +  +47x +20x +8x +8x +8x +  +  +12x +  +  +12x +3x +  +  +  +  +  +12x +3x +  +  +  +12x +12x +  +  +  +  +47x +  +1x +1x +  +  +6x +6x +  +  +  +47x +1x +1x +1x +  +  +47x +1x +1x +1x +  +  +47x +  +47x +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import React, { useState, useEffect, useRef } from 'react';
+import { FiSearch } from 'react-icons/fi';
+import * as S from './styles';
+import { useNavigate } from 'react-router-dom';
+ 
+import { GetAllCommunities } from '../../../API/Community';
+import { GetFeedProjects } from '../../../API/Project';
+import type { CommunityProps } from '../../../API/Community';
+import type { ProjectProps } from '../../../API/Project';
+ 
+export default function Searchbar() {
+    const [query, setQuery] = useState('');
+    const navigate = useNavigate();
+ 
+    const wrapperRef = useRef<HTMLDivElement>(null);
+ 
+    const [isFocused, setIsFocused] = useState(false);
+    const [isLoading, setIsLoading] = useState(false);
+ 
+    // Dados brutos (cache local)
+    const [allCommunities, setAllCommunities] = useState<CommunityProps[]>([]);
+    const [allProjects, setAllProjects] = useState<ProjectProps[]>([]);
+ 
+    // Dados filtrados para exibição
+    const [filteredCommunities, setFilteredCommunities] = useState<CommunityProps[]>([]);
+    const [filteredProjects, setFilteredProjects] = useState<ProjectProps[]>([]);
+ 
+    const handleFocus = async () => {
+        setIsFocused(true);
+        Eif (allCommunities.length === 0 && allProjects.length === 0) {
+            setIsLoading(true);
+            try {
+                // Busca em paralelo
+                const [communitiesData, projectsData] = await Promise.all([
+                    GetAllCommunities().catch(() => []), // Se falhar, retorna array vazio
+                    GetFeedProjects().catch(() => [])
+                ]);
+                
+                setAllCommunities(communitiesData);
+                setAllProjects(projectsData);
+            } catch (error) {
+                console.error("Erro ao carregar dados para pesquisa", error);
+            } finally {
+                setIsLoading(false);
+            }
+        }
+    };
+ 
+    // Efeito para filtrar sempre que a query ou os dados mudarem
+    useEffect(() => {
+        if (!query.trim()) {
+            setFilteredCommunities([]);
+            setFilteredProjects([]);
+            return;
+        }
+ 
+        const lowerQuery = query.toLowerCase();
+ 
+        // Filtra Comunidades (pelo nome ou descrição ou tecnologias)
+        const filteredComms = allCommunities.filter(comm => 
+            comm.name.toLowerCase().includes(lowerQuery) ||
+            comm.description?.toLowerCase().includes(lowerQuery) ||
+            comm.technologies?.some(tech => tech.toLowerCase().includes(lowerQuery))
+        );
+ 
+        // Filtra Projetos (pelo título ou tecnologias)
+        const filteredProjs = allProjects.filter(proj => 
+            proj.title.toLowerCase().includes(lowerQuery) ||
+            proj.technologies?.some(tech => tech.toLowerCase().includes(lowerQuery))
+        );
+ 
+        setFilteredCommunities(filteredComms.slice(0, 5)); // Limita a 5 resultados
+        setFilteredProjects(filteredProjs.slice(0, 5));    // Limita a 5 resultados
+ 
+    }, [query, allCommunities, allProjects]);
+ 
+    // Fecha ao clicar fora
+    useEffect(() => {
+        function handleClickOutside(event: MouseEvent) {
+            Eif (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
+                setIsFocused(false);
+            }
+        }
+        document.addEventListener('mousedown', handleClickOutside);
+        return () => document.removeEventListener('mousedown', handleClickOutside);
+    }, []);
+ 
+    // Navegação
+    const handleNavigateToCommunity = (communityId: string) => {
+        navigate(`/r/${communityId}`);
+        setIsFocused(false);
+        setQuery('');
+    };
+ 
+    const handleNavigateToProject = (projectId: string) => {
+        navigate(`/project/${projectId}`); 
+        console.log("Navegar para projeto:", projectId);
+        setIsFocused(false);
+    };
+ 
+    const hasResults = filteredCommunities.length > 0 || filteredProjects.length > 0;
+ 
+    return (
+        <S.SearchWrapper ref={wrapperRef}>
+            <FiSearch size={20} />
+            <S.SearchInput
+                type="text"
+                placeholder="Busque comunidades e projetos..."
+                value={query}
+                onChange={(e) => setQuery(e.target.value)}
+                onFocus={handleFocus}
+            />
+ 
+            {/* Renderiza o dropdown apenas se estiver focado e houver texto */}
+            {isFocused && query.length > 0 && (
+                <S.ResultsDropdown>
+                    {isLoading ? (
+                        <S.NoResults>Carregando...</S.NoResults>
+                    ) : !hasResults ? (
+                        <S.NoResults>Nenhum resultado encontrado.</S.NoResults>
+                    ) : (
+                        <>
+                            {/* Seção de Comunidades */}
+                            {filteredCommunities.length > 0 && (
+                                <S.ResultSection>
+                                    <h4>Comunidades</h4>
+                                    {filteredCommunities.map(comm => (
+                                        <S.ResultItem 
+                                            key={comm.communityID} 
+                                            onClick={() => handleNavigateToCommunity(comm.communityID)}
+                                        >
+                                            <span>{comm.name}</span>
+                                            {/* Opcional: mostrar tecnologia principal */}
+                                            {comm.technologies?.[0] && <small>{comm.technologies[0]}</small>}
+                                        </S.ResultItem>
+                                    ))}
+                                </S.ResultSection>
+                            )}
+ 
+                            {/* Seção de Projetos */}
+                            {filteredProjects.length > 0 && (
+                                <S.ResultSection>
+                                    <h4>Projetos</h4>
+                                    {filteredProjects.map((proj: any) => (
+                                        <S.ResultItem 
+                                            key={proj.id || proj.projectID} 
+                                            onClick={() => handleNavigateToProject(proj.id || proj.projectID)}
+                                        >
+                                            <span>{proj.title}</span>
+                                            <small>por {proj.authorUsername || 'Usuário'}</small>
+                                        </S.ResultItem>
+                                    ))}
+                                </S.ResultSection>
+                            )}
+                        </>
+                    )}
+                </S.ResultsDropdown>
+            )}
+        </S.SearchWrapper>
+    );
+}
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/domain/TagInput/index.html b/frontend/coverage/src/components/domain/TagInput/index.html new file mode 100644 index 0000000..3464f16 --- /dev/null +++ b/frontend/coverage/src/components/domain/TagInput/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/domain/TagInput + + + + + + + + + +
+
+

All files src/components/domain/TagInput

+
+ +
+ 94.28% + Statements + 33/35 +
+ + +
+ 76.19% + Branches + 16/21 +
+ + +
+ 92.85% + Functions + 13/14 +
+ + +
+ 93.93% + Lines + 31/33 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
94.28%33/3576.19%16/2192.85%13/1493.93%31/33
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/domain/TagInput/index.tsx.html b/frontend/coverage/src/components/domain/TagInput/index.tsx.html new file mode 100644 index 0000000..6d4f16a --- /dev/null +++ b/frontend/coverage/src/components/domain/TagInput/index.tsx.html @@ -0,0 +1,418 @@ + + + + + + Code coverage report for src/components/domain/TagInput/index.tsx + + + + + + + + + +
+
+

All files / src/components/domain/TagInput index.tsx

+
+ +
+ 94.28% + Statements + 33/35 +
+ + +
+ 76.19% + Branches + 16/21 +
+ + +
+ 92.85% + Functions + 13/14 +
+ + +
+ 93.93% + Lines + 31/33 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +20x +20x +20x +20x +  +20x +9x +3x +11x +  +  +3x +  +6x +  +  +  +  +20x +  +  +  +  +  +5x +5x +5x +  +  +  +  +20x +  +2x +1x +1x +  +1x +1x +1x +1x +1x +  +  +  +  +20x +2x +1x +  +  +20x +  +  +  +  +18x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  + 
import React, { useState, useEffect, useRef } from 'react';
+import * as S from '../CreationForm/styles'; 
+import { Keyword, KeywordContainer } from '../../common/Keyword';
+ 
+interface TagInputProps {
+  value: string[];
+  onChange: (value: string[]) => void;
+  
+  searchList: string[]; 
+  limit: number;         
+  placeholder: string;   
+}
+ 
+ 
+export default function TagInput({ 
+  value: selectedTags = [], 
+  onChange, 
+  searchList, 
+  limit,      
+  placeholder 
+}: TagInputProps) {
+  
+  const [searchQuery, setSearchQuery] = useState('');
+  const [searchResults, setSearchResults] = useState<string[]>([]);
+  const [error, setError] = useState('');
+  const wrapperRef = useRef<HTMLDivElement>(null);
+ 
+  useEffect(() => {
+    if (searchQuery.length > 0) {
+      const filtered = searchList.filter(item =>
+        item.toLowerCase().includes(searchQuery.toLowerCase()) &&
+        !selectedTags.includes(item) // Não mostra o que já foi selecionado
+      );
+      setSearchResults(filtered);
+    } else {
+      setSearchResults([]);
+    }
+  }, [searchQuery, selectedTags, searchList]); 
+ 
+  // Lógica para fechar a lista de resultados ao clicar fora
+  useEffect(() => {
+    function handleClickOutside(event: MouseEvent) {
+      if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) {
+        setSearchResults([]); // Fecha a lista
+      }
+    }
+    document.addEventListener('mousedown', handleClickOutside);
+    return () => {
+      document.removeEventListener('mousedown', handleClickOutside);
+    };
+  }, [wrapperRef]);
+ 
+  // Adiciona uma tag
+  const handleAddTag = (tag: string) => {
+    // Usa o 'limit' da prop
+    if (selectedTags.length >= limit) {
+      setError(`Limite de ${limit} itens atingido.`);
+      return;
+    }
+    Eif (!selectedTags.includes(tag)) {
+      onChange([...selectedTags, tag]); // Atualiza o react-hook-form
+      setSearchQuery(''); 
+      setSearchResults([]);
+      setError(''); 
+    }
+  };
+ 
+  // Remove uma tag
+  const handleRemoveTag = (tagToRemove: string) => {
+    onChange(selectedTags.filter(tag => tag !== tagToRemove));
+    setError(''); 
+  };
+ 
+  return (
+    <S.SearchWrapper ref={wrapperRef}>
+      {selectedTags.length > 0 && (
+        <KeywordContainer>
+          {selectedTags.map(tag => (
+            <Keyword 
+              key={tag} 
+              onRemove={() => handleRemoveTag(tag)}
+            >
+              {tag}
+            </Keyword>
+          ))}
+        </KeywordContainer>
+      )}
+      
+      <div style={{ height: selectedTags.length > 0 ? '12px' : '0' }} />
+ 
+      <S.Input
+        type="text"
+        placeholder={placeholder} 
+        value={searchQuery}
+        onChange={(e) => setSearchQuery(e.target.value)}
+        disabled={selectedTags.length >= limit} 
+      />
+ 
+      {searchResults.length > 0 && (
+        <S.SearchResultsList>
+          {searchResults.map(tag => (
+            <S.SearchResultItem key={tag} onClick={() => handleAddTag(tag)}>
+              {tag}
+            </S.SearchResultItem>
+          ))}
+        </S.SearchResultsList>
+      )}
+ 
+      {error && <S.ErrorMessage>{error}</S.ErrorMessage>}
+    </S.SearchWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/layout/Header/index.html b/frontend/coverage/src/components/layout/Header/index.html new file mode 100644 index 0000000..3335e19 --- /dev/null +++ b/frontend/coverage/src/components/layout/Header/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/layout/Header + + + + + + + + + +
+
+

All files src/components/layout/Header

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/layout/Header/index.tsx.html b/frontend/coverage/src/components/layout/Header/index.tsx.html new file mode 100644 index 0000000..b4ea8dc --- /dev/null +++ b/frontend/coverage/src/components/layout/Header/index.tsx.html @@ -0,0 +1,166 @@ + + + + + + Code coverage report for src/components/layout/Header/index.tsx + + + + + + + + + +
+
+

All files / src/components/layout/Header index.tsx

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { FiPlus } from 'react-icons/fi';
+import Searchbar from '../../domain/Searchbar';
+import * as S from './styles';
+ 
+ 
+interface HeaderProps {
+    onCreateClick: () => void; 
+}
+ 
+export default function Header({ onCreateClick }: HeaderProps) {
+    return (
+        <S.HeaderContainer>
+            <S.SearchContainer>
+                <Searchbar />
+            </S.SearchContainer>
+ 
+            <S.ActionsContainer>
+                <S.CreateButton onClick={onCreateClick}> 
+                    <FiPlus size={20} />
+                    <span>Create</span>
+                </S.CreateButton>
+ 
+                <S.ProfileIcon to={`/profile`}> 
+                </S.ProfileIcon>
+            </S.ActionsContainer>
+        </S.HeaderContainer>
+    );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/layout/HeaderHome/index.html b/frontend/coverage/src/components/layout/HeaderHome/index.html new file mode 100644 index 0000000..700e628 --- /dev/null +++ b/frontend/coverage/src/components/layout/HeaderHome/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/layout/HeaderHome + + + + + + + + + +
+
+

All files src/components/layout/HeaderHome

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/layout/HeaderHome/index.tsx.html b/frontend/coverage/src/components/layout/HeaderHome/index.tsx.html new file mode 100644 index 0000000..086e35a --- /dev/null +++ b/frontend/coverage/src/components/layout/HeaderHome/index.tsx.html @@ -0,0 +1,136 @@ + + + + + + Code coverage report for src/components/layout/HeaderHome/index.tsx + + + + + + + + + +
+
+

All files / src/components/layout/HeaderHome index.tsx

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import * as S from './styles';
+ 
+export default function HeaderHome() {
+    return (
+        <S.HeaderContainer>
+ 
+            <S.ActionsContainer>
+                <S.Button to="/login"> 
+                    Login
+                </S.Button>
+ 
+                <S.Button to="/register"> 
+                    Register
+                </S.Button>
+            </S.ActionsContainer>
+        </S.HeaderContainer>
+    );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/layout/Sidebar/index.html b/frontend/coverage/src/components/layout/Sidebar/index.html new file mode 100644 index 0000000..5442f7a --- /dev/null +++ b/frontend/coverage/src/components/layout/Sidebar/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/components/layout/Sidebar + + + + + + + + + +
+
+

All files src/components/layout/Sidebar

+
+ +
+ 93.75% + Statements + 15/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 93.75% + Lines + 15/16 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
93.75%15/1675%3/4100%5/593.75%15/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/components/layout/Sidebar/index.tsx.html b/frontend/coverage/src/components/layout/Sidebar/index.tsx.html new file mode 100644 index 0000000..0b5d088 --- /dev/null +++ b/frontend/coverage/src/components/layout/Sidebar/index.tsx.html @@ -0,0 +1,298 @@ + + + + + + Code coverage report for src/components/layout/Sidebar/index.tsx + + + + + + + + + +
+
+

All files / src/components/layout/Sidebar index.tsx

+
+ +
+ 93.75% + Statements + 15/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 100% + Functions + 5/5 +
+ + +
+ 93.75% + Lines + 15/16 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +9x +9x +9x +  +9x +2x +  +  +9x +  +8x +8x +  +8x +8x +8x +  +  +  +  +  +  +8x +8x +  +  +9x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState } from 'react';
+import { FiHome, FiChevronDown } from 'react-icons/fi';
+import { GetUserCommunities } from '../../../API/Community';
+import * as S from './styles';
+import type { CommunityProps } from '../../../API/Community';
+import { useAuth } from '../../../API/AuthContext';
+import { useEffect } from 'react';
+ 
+export default function Sidebar() {
+    // Estado para controlar se a lista de comunidades está visível
+    const [isCommunitiesOpen, setIsCommunitiesOpen] = useState(true);
+    const { currentUser } = useAuth();
+    const [userCommunities, setUserCommunities] = useState<CommunityProps[]>([]);
+ 
+    const toggleCommunities = () => {
+        setIsCommunitiesOpen(!isCommunitiesOpen);
+    };
+ 
+      useEffect(() => {
+        // Função assíncrona para buscar todos os dados
+        const fetchCommunities = async () => {
+          try {;
+            
+            const apiUserCommunities = await GetUserCommunities();
+            console.log("Comunidades do usuário:", apiUserCommunities);
+            setUserCommunities(apiUserCommunities);
+    
+          } catch (error) {
+            console.error("Falha ao buscar comunidades:", error);
+          } 
+          
+        };
+        Eif(currentUser)
+          fetchCommunities();
+      }, [currentUser]); 
+ 
+    return (
+        <S.SidebarContainer>
+            <S.SidebarNav>
+                
+                <S.HomeLink to="/feed">
+                    <FiHome size={22} />
+                    <span>Home</span>
+                </S.HomeLink>
+ 
+                <S.CommunitiesHeader onClick={toggleCommunities} isOpen={isCommunitiesOpen}>
+                    <span>COMUNIDADES</span>
+                    <FiChevronDown size={20} />
+                </S.CommunitiesHeader>
+ 
+                {isCommunitiesOpen && (
+                    <S.CommunitiesList>
+                        {userCommunities.map((community) => (
+                            <S.CommunityLink
+                                to={`/r/${community.communityID}`}
+                                key={community.communityID}
+                            >
+                                <S.CommunityIcon
+                                    alt={`${community.name} icon`}
+                                />
+                                <span>{community.name}</span>
+                            </S.CommunityLink>
+                        ))}
+                    </S.CommunitiesList>
+                )}
+ 
+            </S.SidebarNav>
+        </S.SidebarContainer>
+    );
+}
+ 
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/index.html b/frontend/coverage/src/index.html new file mode 100644 index 0000000..5479737 --- /dev/null +++ b/frontend/coverage/src/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src + + + + + + + + + +
+
+

All files src

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
App.tsx +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/CommunityPage/index.html b/frontend/coverage/src/pages/CommunityPage/index.html new file mode 100644 index 0000000..280a055 --- /dev/null +++ b/frontend/coverage/src/pages/CommunityPage/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/pages/CommunityPage + + + + + + + + + +
+
+

All files src/pages/CommunityPage

+
+ +
+ 83.94% + Statements + 115/137 +
+ + +
+ 68.42% + Branches + 39/57 +
+ + +
+ 88.05% + Functions + 59/67 +
+ + +
+ 85.24% + Lines + 104/122 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
71.05%54/7658.13%25/4365.21%15/2373.13%49/67
styles.ts +
+
100%61/61100%14/14100%44/44100%55/55
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/CommunityPage/index.tsx.html b/frontend/coverage/src/pages/CommunityPage/index.tsx.html new file mode 100644 index 0000000..b21a8cb --- /dev/null +++ b/frontend/coverage/src/pages/CommunityPage/index.tsx.html @@ -0,0 +1,838 @@ + + + + + + Code coverage report for src/pages/CommunityPage/index.tsx + + + + + + + + + +
+
+

All files / src/pages/CommunityPage index.tsx

+
+ +
+ 71.05% + Statements + 54/76 +
+ + +
+ 58.13% + Branches + 25/43 +
+ + +
+ 65.21% + Functions + 15/23 +
+ + +
+ 73.13% + Lines + 49/67 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +14x +14x +  +14x +14x +14x +  +14x +14x +14x +  +14x +  +14x +  +4x +4x +4x +4x +4x +4x +  +  +  +  +4x +  +  +14x +  +  +  +  +  +6x +6x +  +  +14x +1x +  +1x +1x +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +14x +  +  +  +14x +1x +1x +1x +1x +1x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +14x +1x +  +1x +1x +  +  +1x +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +14x +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +1x +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useParams, useNavigate } from 'react-router-dom';
+import Sidebar from '../../components/layout/Sidebar';
+import Postcard from '../../components/domain/Postcard';
+import * as S from './styles';
+import { FiMoreHorizontal } from 'react-icons/fi'; 
+import { useEffect, useState, useRef } from 'react';
+import { GetCommunityById, JoinCommunity, DeleteCommunity, LeaveCommunity } from '../../API/Community';
+import type { NotificationState } from '../../components/common/Toast';
+import Toast from '../../components/common/Toast';
+import type { CommunityProps } from '../../API/Community';
+import * as D from '../../components/common/Dropdown/styles';
+import Modal from '../../components/common/Modal';
+import * as ModalS from '../../components/common/Modal/styles';
+ 
+export default function CommunityPage() {
+  const { communityID } = useParams<{ communityID: string }>();
+  const navigate = useNavigate();
+ 
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+  const [community, setCommunity] = useState<any>(null);
+  const [posts, setPosts] = useState<any[]>([]);
+ 
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+  const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
+  const menuRef = useRef<HTMLDivElement>(null);
+ 
+  const [isLeaveModalOpen, setIsLeaveModalOpen] = useState(false);
+ 
+  useEffect(() => {
+    async function loadData() {
+        console.log("Carregando dados da comunidade para ID:", communityID);
+        Iif (!communityID) return;
+        try {
+            const data = await GetCommunityById(communityID);
+            setCommunity(data.community);
+            setPosts(data.posts);
+        } catch (error) {
+            console.error(error);
+        } 
+    }
+    loadData();
+  }, [communityID]);
+ 
+  useEffect(() => {
+    function handleClickOutside(event: MouseEvent) {
+      if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
+        setIsMenuOpen(false);
+      }
+    }
+    if (isMenuOpen) document.addEventListener('mousedown', handleClickOutside);
+    return () => document.removeEventListener('mousedown', handleClickOutside);
+  }, [isMenuOpen]);
+ 
+  const handleJoin = async () => {
+    Iif (!community) return;
+ 
+    try {
+        await JoinCommunity(community.communityID);
+        
+        // Atualiza a interface após entrar na comunidade
+        setCommunity((prev: CommunityProps | null) => prev ? ({
+            ...prev,
+            isMember: true, // Esconde o botão
+            memberCount: (prev.memberCount || 0) + 1 // Atualiza o contador visualmente
+        }) : null);
+ 
+        setNotification({ message: 'Você entrou na comunidade!', type: 'success' });
+ 
+    } catch (error) {
+        if (error instanceof Error) {
+            setNotification({ message: error.message, type: 'error' });
+        }
+    }
+  };
+ 
+  const handleEdit = () => {
+    navigate('/editCommunity', { state: { communityToEdit: community } });
+  };
+ 
+  const handleDelete = async () => {
+    Iif (!community) return;
+    try {
+        await DeleteCommunity(community.communityID);
+        setNotification({ message: 'Comunidade excluída com sucesso.', type: 'success' });
+        setIsDeleteModalOpen(false);
+        
+        // Redireciona para home após excluir
+        setTimeout(() => {
+            navigate('/feed');
+        }, 1500);
+ 
+    } catch (error) {
+        if (error instanceof Error) {
+            setNotification({ message: error.message, type: 'error' });
+        }
+        setIsDeleteModalOpen(false);
+    }
+  };
+ 
+  const handleLeave = async () => {
+    Iif (!community) return;
+ 
+    try {
+        await LeaveCommunity(community.communityID);
+        
+        // Atualiza a interface otimisticamente
+        setCommunity((prev: CommunityProps | null) => prev ? ({
+            ...prev,
+            isMember: false, // O usuário não é mais membro
+            memberCount: Math.max((prev.memberCount || 0) - 1, 0) // Decrementa contador
+        }) : null);
+ 
+        setNotification({ message: 'Você saiu da comunidade.', type: 'success' });
+        setIsLeaveModalOpen(false); // Fecha o modal
+ 
+    } catch (error) {
+        if (error instanceof Error) {
+            setNotification({ message: error.message, type: 'error' });
+        }
+        setIsLeaveModalOpen(false);
+    }
+  };
+ 
+  if (!community) return <div>Comunidade não encontrada</div>;
+ 
+  return (
+    <S.PageWrapper>
+      <Sidebar />
+ 
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <S.MainContent>
+        <S.Banner />
+        
+        <S.HeaderContainer>
+          <S.Avatar /> 
+          <S.HeaderInfo>
+            <h1>{community.name}</h1>
+            <span>{community.memberCount} membros</span>
+          </S.HeaderInfo>
+ 
+          <S.HeaderActions>
+            {!community.isMember && (
+            <S.JoinButton onClick={handleJoin}>
+                Join
+            </S.JoinButton>
+            )}
+            {community.isMember && !community.isAdmin && (
+                <S.LeaveButton onClick={() => setIsLeaveModalOpen(true)}>
+                    Sair
+                </S.LeaveButton>
+            )}
+           {community.isAdmin && (
+                <S.MenuWrapper ref={menuRef}>
+                    <S.OptionsButton onClick={() => setIsMenuOpen(!isMenuOpen)}>
+                        <FiMoreHorizontal />
+                    </S.OptionsButton>
+ 
+                    {isMenuOpen && (
+                        <D.DropdownMenu>
+                            <D.MenuItem onClick={handleEdit}>
+                                Editar Comunidade
+                            </D.MenuItem>
+                            <D.Separator />
+                            <D.DangerMenuItem onClick={() => {
+                                setIsMenuOpen(false);
+                                setIsDeleteModalOpen(true);
+                            }}>
+                                Excluir Comunidade
+                            </D.DangerMenuItem>
+                        </D.DropdownMenu>
+                    )}
+                </S.MenuWrapper>
+            )}
+          </S.HeaderActions>
+        </S.HeaderContainer>
+ 
+        <S.ContentGrid>
+          <S.FeedColumn>
+            {posts.map(post => (
+              <S.FeedCardWrapper key={post.projectID || post.id}>
+                <Postcard post={post} showMenu={false} />
+              </S.FeedCardWrapper>
+            ))}
+          </S.FeedColumn>
+ 
+          <S.InfoSidebar>
+            <h3>DESCRIPTION</h3>
+            <p>{community.description}</p>
+ 
+            <h3>KEYWORDS</h3>
+            <S.KeywordsContainer>
+              {community.technologies?.map((keyword: string) => (
+                <S.KeywordTag key={keyword}>{keyword}</S.KeywordTag>
+              ))}
+            </S.KeywordsContainer>
+          </S.InfoSidebar>
+        </S.ContentGrid>
+      </S.MainContent>
+ 
+      <Modal 
+        isOpen={isDeleteModalOpen} 
+        onClose={() => setIsDeleteModalOpen(false)}
+        title="Excluir Comunidade"
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Tem certeza que deseja excluir a comunidade <strong>{community.name}</strong>?<br/>
+                Todos os posts e vínculos serão removidos.
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton onClick={() => setIsDeleteModalOpen(false)}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton onClick={handleDelete} style={{ backgroundColor: '#e74c3c' }}>
+                    Excluir
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+ 
+      <Modal 
+        isOpen={isLeaveModalOpen} 
+        onClose={() => setIsLeaveModalOpen(false)}
+        title="Sair da Comunidade"
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Tem certeza que deseja sair da comunidade <strong>{community.name}</strong>?
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton onClick={() => setIsLeaveModalOpen(false)}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton 
+                    onClick={handleLeave} 
+                    style={{ backgroundColor: '#e74c3c' }} // Botão vermelho
+                >
+                    Sair
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+    </S.PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/CommunityPage/styles.ts.html b/frontend/coverage/src/pages/CommunityPage/styles.ts.html new file mode 100644 index 0000000..e5861ef --- /dev/null +++ b/frontend/coverage/src/pages/CommunityPage/styles.ts.html @@ -0,0 +1,1426 @@ + + + + + + Code coverage report for src/pages/CommunityPage/styles.ts + + + + + + + + + +
+
+

All files / src/pages/CommunityPage styles.ts

+
+ +
+ 100% + Statements + 61/61 +
+ + +
+ 100% + Branches + 14/14 +
+ + +
+ 100% + Functions + 44/44 +
+ + +
+ 100% + Lines + 55/55 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448  +  +1x +  +  +10x +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +10x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +10x +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +3x +3x +3x +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +  +  +  +  +  +  +  +1x +  +  +3x +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +3x +3x +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +4x +4x +4x +  +  +  +  +  +  +  +  +  +4x +4x +  +4x +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +10x +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +1x +10x +10x +  +  +  +  +10x +  +  +  +  +10x +  +10x +  +  +  +1x +  +  +  +  + 
import styled from 'styled-components';
+ 
+export const PageWrapper = styled.div`
+  display: flex;
+  min-height: 100vh;
+  background: linear-gradient(135deg, ${props => props.theme.white} 0%, ${props => props.theme['gray-100'] || props.theme['gray-100']} 100%);
+`;
+ 
+export const MainContent = styled.main`
+  flex: 1;
+  margin-left: 250px;
+  display: flex;
+  flex-direction: column;
+  
+  animation: fadeIn 0.5s ease-out;
+  
+  @keyframes fadeIn {
+    from {
+      opacity: 0;
+    }
+    to {
+      opacity: 1;
+    }
+  }
+`;
+ 
+// --- Área do Topo (Banner + Avatar + Título) ---
+ 
+export const Banner = styled.div`
+  width: 100%;
+  height: 220px;
+  background: linear-gradient(135deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.placeholder} 100%);
+  position: relative;
+  overflow: hidden;
+  
+  /* Padrão decorativo com formas geométricas */
+  &::before {
+    content: '';
+    position: absolute;
+    top: -50%;
+    right: -10%;
+    width: 600px;
+    height: 600px;
+    background: radial-gradient(circle, rgba(255, 255, 255, 0.15) 0%, transparent 70%);
+    border-radius: 50%;
+  }
+  
+  &::after {
+    content: '';
+    position: absolute;
+    bottom: -30%;
+    left: -5%;
+    width: 400px;
+    height: 400px;
+    background: radial-gradient(circle, rgba(255, 255, 255, 0.1) 0%, transparent 70%);
+    border-radius: 50%;
+  }
+`;
+ 
+export const HeaderContainer = styled.div`
+  display: flex;
+  align-items: flex-end;
+  padding: 0 40px;
+  margin-top: -60px;
+  margin-bottom: 32px;
+  gap: 24px;
+  position: relative;
+  z-index: 2;
+  flex-wrap: wrap;
+  
+  animation: slideUp 0.6s ease-out;
+  
+  @keyframes slideUp {
+    from {
+      opacity: 0;
+      transform: translateY(30px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+`;
+ 
+export const Avatar = styled.div`
+  width: 130px;
+  height: 130px;
+  border-radius: 24px;
+  background: linear-gradient(135deg, ${props => props.theme.sidebar} 0%, ${props => props.theme.button} 100%);
+  border: 5px solid ${props => props.theme.white};
+  flex-shrink: 0;
+  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2),
+              0 4px 12px rgba(0, 0, 0, 0.15);
+  position: relative;
+  
+  /* Efeito de brilho */
+  &::after {
+    content: '';
+    position: absolute;
+    top: 15%;
+    left: 15%;
+    width: 35%;
+    height: 35%;
+    background: radial-gradient(circle, rgba(255, 255, 255, 0.4) 0%, transparent 70%);
+    border-radius: 50%;
+  }
+  
+  transition: transform 0.3s ease, box-shadow 0.3s ease;
+  
+  &:hover {
+    transform: scale(1.05) rotate(2deg);
+    box-shadow: 0 15px 40px rgba(0, 0, 0, 0.25),
+                0 6px 16px rgba(0, 0, 0, 0.2);
+  }
+`;
+ 
+export const HeaderInfo = styled.div`
+  display: flex;
+  flex-direction: column;
+  padding-bottom: 12px;
+  flex: 1;
+  gap: 14px;
+  min-width: 0;
+ 
+  h1 {
+    font-size: 2.8rem;
+    font-weight: 800;
+    color: ${props => props.theme.black};
+    margin: 0;
+    margin-bottom: 8px;
+    line-height: 1.1;
+    letter-spacing: -0.02em;
+    
+    background: linear-gradient(135deg, ${props => props.theme.white} 0%, ${props => props.theme.button} 100%);
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    background-clip: text;
+    
+    position: relative;
+    word-wrap: break-word;
+    overflow-wrap: break-word;
+    
+    /* Underline decorativo */
+    &::after {
+      content: '';
+      position: absolute;
+      bottom: -10px;
+      left: 0;
+      width: 80px;
+      height: 5px;
+      background: linear-gradient(90deg, ${props => props.theme.button} 0%, transparent 100%);
+      border-radius: 3px;
+    }
+  }
+ 
+  span {
+    color: ${props => props.theme['gray-600'] || props.theme['gray-500']};
+    font-size: 1rem;
+    font-weight: 600;
+    padding: 6px 14px;
+    background: ${props => props.theme['gray-100']};
+    border-radius: 20px;
+    width: fit-content;
+    display: flex;
+    align-items: center;
+    gap: 6px;
+    
+    /* Ícone decorativo */
+    &::before {
+      content: '👥';
+      font-size: 0.9em;
+    }
+  }
+`;
+ 
+export const HeaderActions = styled.div`
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  padding-bottom: 15px;
+`;
+ 
+export const JoinButton = styled.button`
+  padding: 12px 32px;
+  border-radius: 12px;
+  border: 2px solid ${props => props.theme.button};
+  background: ${props => props.theme.button};
+  color: ${props => props.theme.white};
+  font-weight: 700;
+  font-size: 1rem;
+  cursor: pointer;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  box-shadow: 0 4px 12px ${props => props.theme.button}40;
+  position: relative;
+  overflow: hidden;
+  
+  /* Efeito de brilho deslizante */
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -100%;
+    width: 100%;
+    height: 100%;
+    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
+    transition: left 0.5s;
+  }
+  
+  &:hover::before {
+    left: 100%;
+  }
+ 
+  &:hover {
+    transform: translateY(-3px);
+    box-shadow: 0 8px 20px ${props => props.theme.button}50;
+    background: ${props => props.theme['hover-button'] || props.theme.button};
+  }
+  
+  &:active {
+    transform: translateY(-1px);
+  }
+`;
+ 
+export const LeaveButton = styled.button`
+  padding: 12px 32px;
+  border-radius: 12px;
+  border: 2px solid ${props => props.theme['red-500']};
+  background: transparent;
+  color: ${props => props.theme['red-500']};
+  font-weight: 700;
+  font-size: 1rem;
+  cursor: pointer;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  position: relative;
+  overflow: hidden;
+ 
+  &::before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 0;
+    height: 0;
+    background: ${props => props.theme['red-500']};
+    border-radius: 50%;
+    transform: translate(-50%, -50%);
+    transition: width 0.4s, height 0.4s;
+    z-index: -1;
+  }
+ 
+  &:hover::before {
+    width: 300%;
+    height: 300%;
+  }
+ 
+  &:hover {
+    color: ${props => props.theme.white};
+    border-color: ${props => props.theme['red-500']};
+    box-shadow: 0 4px 16px ${props => props.theme['red-500']}40;
+    transform: translateY(-2px);
+  }
+  
+  &:active {
+    transform: translateY(0);
+  }
+  
+  > * {
+    position: relative;
+    z-index: 1;
+  }
+`;
+ 
+export const OptionsButton = styled.button`
+  width: 48px;
+  height: 48px;
+  border-radius: 12px;
+  border: 2px solid ${props => props.theme.button};
+  background: ${props => props.theme.white};
+  color: ${props => props.theme.button};
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  font-size: 1.3rem;
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+ 
+  &:hover {
+    background-color: ${props => props.theme.button};
+    color: ${props => props.theme.white};
+    transform: scale(1.1) rotate(90deg);
+    box-shadow: 0 4px 16px ${props => props.theme.button}30;
+  }
+  
+  &:active {
+    transform: scale(1.05) rotate(90deg);
+  }
+`;
+ 
+// --- Grid de Conteúdo (Feed + Info Lateral) ---
+ 
+export const ContentGrid = styled.div`
+  display: grid;
+  grid-template-columns: 1fr 340px;
+  gap: 28px;
+  padding: 0 40px 40px 40px;
+  max-width: 1400px;
+  width: 100%;
+  box-sizing: border-box;
+ 
+  @media (max-width: 900px) {
+    grid-template-columns: 1fr;
+  }
+`;
+ 
+export const FeedColumn = styled.div`
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  
+  animation: slideInLeft 0.5s ease-out;
+  
+  @keyframes slideInLeft {
+    from {
+      opacity: 0;
+      transform: translateX(-20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateX(0);
+    }
+  }
+`;
+ 
+export const FeedCardWrapper = styled.div`
+  background: linear-gradient(135deg, ${props => props.theme.background} 0%, ${props => props.theme['gray-100'] || props.theme.background} 100%);
+  border-radius: 18px;
+  padding: 10px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+  transition: all 0.3s ease;
+  
+  &:hover {
+    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
+    transform: translateY(-2px);
+  }
+`;
+ 
+// --- Sidebar de Informações (Direita) ---
+ 
+export const InfoSidebar = styled.aside`
+  background: ${props => props.theme.white};
+  border: 2px solid ${props => props.theme.button}25;
+  border-radius: 20px;
+  padding: 28px;
+  height: fit-content;
+  position: sticky;
+  top: 20px;
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
+  overflow-wrap: break-word;
+  word-wrap: break-word;
+  word-break: break-word;
+  
+  animation: slideInRight 0.5s ease-out;
+  
+  @keyframes slideInRight {
+    from {
+      opacity: 0;
+      transform: translateX(20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateX(0);
+    }
+  }
+  
+  h3 {
+    color: ${props => props.theme.title};
+    font-size: 0.85rem;
+    font-weight: 800;
+    letter-spacing: 1.5px;
+    text-transform: uppercase;
+    margin-bottom: 16px;
+    margin-top: 28px;
+    position: relative;
+    padding-left: 12px;
+    
+    /* Barra lateral decorativa */
+    &::before {
+      content: '';
+      position: absolute;
+      left: 0;
+      top: 50%;
+      transform: translateY(-50%);
+      width: 4px;
+      height: 18px;
+      background: linear-gradient(180deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.button} 100%);
+      border-radius: 2px;
+    }
+  }
+ 
+  h3:first-child {
+    margin-top: 0;
+  }
+ 
+  p {
+    color: ${props => props.theme['gray-700'] || props.theme.black};
+    font-size: 0.95rem;
+    line-height: 1.7;
+    margin-bottom: 16px;
+    padding-left: 12px;
+    word-wrap: break-word;
+    overflow-wrap: break-word;
+    word-break: break-word;
+    white-space: pre-wrap;
+  }
+`;
+ 
+export const KeywordsContainer = styled.div`
+  display: flex;
+  flex-wrap: wrap;
+  gap: 10px;
+  padding-left: 12px;
+`;
+ 
+export const KeywordTag = styled.span`
+  border: 2px solid ${props => props.theme.keyword};
+  color: ${props => props.theme.keyword};
+  border-radius: 10px;
+  padding: 8px 18px;
+  font-size: 0.85rem;
+  font-weight: 700;
+  background: ${props => props.theme.keyword}10;
+  transition: all 0.2s ease;
+  cursor: default;
+  
+  &:hover {
+    background: ${props => props.theme.keyword}20;
+    transform: translateY(-2px);
+    box-shadow: 0 4px 8px ${props => props.theme.keyword}20;
+  }
+`;
+ 
+export const MenuWrapper = styled.div`
+  position: relative;
+  display: flex;
+  align-items: center;
+  z-index: 10;
+`;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/CreateCommunity/index.html b/frontend/coverage/src/pages/CreateCommunity/index.html new file mode 100644 index 0000000..5d6afd4 --- /dev/null +++ b/frontend/coverage/src/pages/CreateCommunity/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/CreateCommunity + + + + + + + + + +
+
+

All files src/pages/CreateCommunity

+
+ +
+ 81.81% + Statements + 27/33 +
+ + +
+ 90.9% + Branches + 20/22 +
+ + +
+ 71.42% + Functions + 5/7 +
+ + +
+ 81.81% + Lines + 27/33 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
81.81%27/3390.9%20/2271.42%5/781.81%27/33
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/CreateCommunity/index.tsx.html b/frontend/coverage/src/pages/CreateCommunity/index.tsx.html new file mode 100644 index 0000000..1b46139 --- /dev/null +++ b/frontend/coverage/src/pages/CreateCommunity/index.tsx.html @@ -0,0 +1,502 @@ + + + + + + Code coverage report for src/pages/CreateCommunity/index.tsx + + + + + + + + + +
+
+

All files / src/pages/CreateCommunity index.tsx

+
+ +
+ 81.81% + Statements + 27/33 +
+ + +
+ 90.9% + Branches + 20/22 +
+ + +
+ 71.42% + Functions + 5/7 +
+ + +
+ 81.81% + Lines + 27/33 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140  +  +  +  +  +  +  +  +  +  +  +  +  +  +7x +7x +  +7x +7x +  +7x +  +  +  +  +  +  +  +  +  +7x +7x +7x +7x +7x +  +7x +  +2x +2x +2x +  +  +  +  +2x +  +  +7x +2x +2x +  +1x +1x +1x +  +  +1x +1x +1x +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {useState, useEffect} from 'react';
+import { useNavigate, useLocation } from 'react-router-dom';
+import { useForm, Controller } from 'react-hook-form';
+import Sidebar from '../../components/layout/Sidebar';
+import { PageWrapper, ContentWrapper } from '../Feed/styles'; 
+import * as S from '../../components/domain/CreationForm/styles'; 
+import TagInput from '../../components/domain/TagInput';
+import type { NotificationState } from '../../components/common/Toast';
+import { GetKeywords } from '../../API/Keywords';
+import  Toast  from '../../components/common/Toast';
+import type { CommunityProps } from '../../API/Community';
+import { NewCommunity, UpdateCommunity } from '../../API/Community';
+ 
+export default function CreateCommunity() {
+  const navigate = useNavigate();
+  const location = useLocation();
+ 
+  const communityToEdit = location.state?.communityToEdit as CommunityProps | undefined;
+  const isEditMode = !!communityToEdit;
+  
+  const { register, handleSubmit, control, watch } = useForm<CommunityProps>({
+    // Preenche os valores iniciais com os dados da comunidade se estiver editando
+    defaultValues: {
+      communityID: communityToEdit?.communityID || "",
+      name: communityToEdit?.name || "",
+      description: communityToEdit?.description || "",
+      technologies: communityToEdit?.technologies || []
+    }
+  });
+ 
+  const descriptionValue = watch('description');
+  const descriptionLength = descriptionValue ? descriptionValue.length : 0;
+  const MAX_CHARS = 500;
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+  const [keywords, setKeywords] = useState<string[]>([]); 
+ 
+  useEffect(() => {
+      async function loadTechs() {
+        try {
+          const techsFromDB = await GetKeywords();
+          setKeywords(techsFromDB);
+        } catch (error) {
+          console.error("Falha ao carregar tecnologias:", error);
+        }
+      }
+      loadTechs();
+    }, []);
+ 
+  const onSubmit = (data: CommunityProps) => {
+    try{
+      if (isEditMode && communityToEdit) {
+        // --- MODO EDIÇÃO ---
+        console.log("Atualizando Comunidade:", communityToEdit.communityID, data);
+        UpdateCommunity(communityToEdit.communityID, data);
+        setNotification({ message: 'Comunidade atualizada com sucesso!', type: 'success' });
+      } else {
+        // --- MODO CRIAÇÃO ---
+        console.log("Criando Comunidade:", data);
+        NewCommunity(data);
+        setNotification({ message: 'Comunidade criada com sucesso!', type: 'success' });
+      }
+ 
+      setTimeout(() => {
+          navigate('/feed'); 
+      }, 1000);
+ 
+    } catch (error) {
+      console.error('Erro ao criar comunidade:', error);
+      if (error instanceof Error){
+        setNotification({ message: error.message, type: 'error' });
+      }
+    }
+    
+  };
+ 
+  return (
+    <PageWrapper>
+      <Sidebar />
+ 
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <ContentWrapper>
+        <S.FormContainer onSubmit={handleSubmit(onSubmit)}>
+ 
+          <h2>{isEditMode ? 'Editar Comunidade' : 'Criar Comunidade'}</h2>
+          
+          <S.InputGroup>
+            <S.Label htmlFor="name">Nome da Comunidade</S.Label>
+            <S.Input id="name" {...register('name', { required: true })} />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="description">Descrição do Projeto</S.Label>
+              <S.TextArea 
+                id="description"
+                placeholder="Descreva sua comunidade..."
+                maxLength={MAX_CHARS}
+                {...register('description', {
+                  maxLength: {
+                  value: MAX_CHARS,
+                  message: `A descrição não pode exceder ${MAX_CHARS} caracteres`
+                }
+                })}
+                />
+                <S.CharacterCount>
+                {descriptionLength} / {MAX_CHARS}
+                </S.CharacterCount>
+          </S.InputGroup>
+          
+          <S.InputGroup>
+            <S.Label htmlFor="keywords">Palavras-chave</S.Label>
+            
+            <Controller
+              name="technologies"
+              control={control}
+              render={({ field }) => (
+                <TagInput 
+                  value={field.value}
+                  onChange={field.onChange}
+                  searchList={keywords}
+                  limit={10} 
+                  placeholder="Adicione até 10 palavras-chave..."
+                />
+              )}
+            />
+          </S.InputGroup>
+ 
+          <S.SubmitButton type="submit">{isEditMode ? 'Salvar Alterações' : 'Criar Comunidade'}</S.SubmitButton>
+ 
+        </S.FormContainer>
+      </ContentWrapper>
+    </PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/CreateProject/index.html b/frontend/coverage/src/pages/CreateProject/index.html new file mode 100644 index 0000000..42d0fc4 --- /dev/null +++ b/frontend/coverage/src/pages/CreateProject/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/CreateProject + + + + + + + + + +
+
+

All files src/pages/CreateProject

+
+ +
+ 84.44% + Statements + 38/45 +
+ + +
+ 87.09% + Branches + 27/31 +
+ + +
+ 80% + Functions + 8/10 +
+ + +
+ 86.04% + Lines + 37/43 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
84.44%38/4587.09%27/3180%8/1086.04%37/43
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/CreateProject/index.tsx.html b/frontend/coverage/src/pages/CreateProject/index.tsx.html new file mode 100644 index 0000000..e1bada3 --- /dev/null +++ b/frontend/coverage/src/pages/CreateProject/index.tsx.html @@ -0,0 +1,703 @@ + + + + + + Code coverage report for src/pages/CreateProject/index.tsx + + + + + + + + + +
+
+

All files / src/pages/CreateProject index.tsx

+
+ +
+ 84.44% + Statements + 38/45 +
+ + +
+ 87.09% + Branches + 27/31 +
+ + +
+ 80% + Functions + 8/10 +
+ + +
+ 86.04% + Lines + 37/43 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +13x +13x +13x +  +13x +  +  +13x +  +13x +  +13x +  +  +  +13x +13x +6x +  +6x +6x +  +  +13x +  +  +  +  +  +  +  +  +  +  +13x +13x +13x +13x +  +  +13x +  +4x +4x +4x +  +  +  +  +4x +  +  +  +13x +  +2x +  +  +  +  +2x +2x +  +1x +1x +1x +  +  +1x +1x +1x +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +13x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +15x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState, useEffect } from 'react';
+import { useForm, Controller } from 'react-hook-form';
+import Sidebar from '../../components/layout/Sidebar';
+import { PageWrapper, ContentWrapper } from '../Feed/styles'; 
+import * as S from '../../components/domain/CreationForm/styles'; 
+import TagInput from '../../components/domain/TagInput';
+import { IMaskInput } from 'react-imask';
+import { NewProject, UpdateProject } from '../../API/Project'; 
+import type { ProjectProps } from '../../API/Project';
+import  Toast  from '../../components/common/Toast';
+import { useNavigate, useLocation, useParams } from 'react-router-dom';
+import type { NotificationState } from '../../components/common/Toast';
+import { GetKeywords } from '../../API/Keywords';
+import { parseDate } from '../../API/Project';
+ 
+interface ProjectFormProps extends Omit<ProjectProps, 'startDate'> {
+  startDate: string; 
+}
+ 
+export default function CreateProject() {
+  const navigate = useNavigate();
+  const location = useLocation(); // Hook para ler o state
+  const [keywords, setKeywords] = useState<string[]>([]); 
+ 
+  const { projectId: paramId } = useParams<{ projectId?: string }>(); 
+ 
+  // Recupera o projeto do estado
+  const projectToEdit = location.state?.projectToEdit as (ProjectProps & { id?: string; projectID?: string }) | undefined;
+  // Define se é modo edição
+  const isEditMode = !!projectToEdit;
+ 
+  const validProjectId = projectToEdit?.id 
+                      || projectToEdit?.projectID 
+                      || (paramId !== 'undefined' ? paramId : undefined);
+ 
+  const formatDateToString = (date?: Date | string) => {
+    if (!date) return "";
+    const d = new Date(date);
+    // Verifica se é data válida
+    Iif (isNaN(d.getTime())) return "";
+    return d.toLocaleDateString('pt-BR'); // Retorna "20/11/2025"
+  };
+ 
+  const { register, handleSubmit, control, watch } = useForm<ProjectFormProps>({
+    // Preenche os valores padrão se estiver em modo de edição
+    defaultValues: {
+      title: projectToEdit?.title || "",
+      description: projectToEdit?.description || "",
+      technologies: projectToEdit?.technologies || [], 
+      status: projectToEdit?.status || "",
+      startDate: formatDateToString(projectToEdit?.startDate)
+    }
+  });
+ 
+  const descriptionValue = watch('description');
+  const descriptionLength = descriptionValue ? descriptionValue.length : 0;
+  const MAX_CHARS = 2500;
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+  // Carrega as tecnologias disponíveis do backend
+  useEffect(() => {
+    async function loadTechs() {
+      try {
+        const techsFromDB = await GetKeywords();
+        setKeywords(techsFromDB);
+      } catch (error) {
+        console.error("Falha ao carregar tecnologias:", error);
+      }
+    }
+    loadTechs();
+  }, []);
+ 
+  // Lida com CRIAR ou ATUALIZAR
+  const onSubmit = (data: ProjectFormProps) => {
+ 
+    const finalData: ProjectProps = {
+        ...data,
+        startDate: parseDate(data.startDate) 
+    };
+ 
+    try {
+      if (isEditMode && validProjectId) {
+        // MODO DE EDIÇÃO
+        console.log("Atualizando Projeto:", validProjectId, finalData);
+        UpdateProject(validProjectId, finalData); 
+        setNotification({ message: 'Projeto atualizado com sucesso!', type: 'success' });
+      } else {
+        // MODO DE CRIAÇÃO
+        console.log("Criando Projeto:", finalData);
+        NewProject(finalData); 
+        setNotification({ message: 'Projeto criado com sucesso!', type: 'success' });
+      }
+      
+      // Redireciona após o sucesso
+      setTimeout(() => {
+          navigate('/feed'); 
+      }, 1000);
+ 
+    } catch(error) {
+      console.error('Erro ao salvar projeto:', error);
+      if (error instanceof Error){
+        setNotification({ message: error.message, type: 'error' });
+      }
+    }
+  };
+ 
+  return (
+    <PageWrapper>
+      <Sidebar />
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <ContentWrapper>
+        <S.FormContainer onSubmit={handleSubmit(onSubmit)}>
+          
+          <h2>{isEditMode ? 'Editar Projeto' : 'Criar Projeto'}</h2>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="title">Nome do Projeto</S.Label>
+            <S.Input id="title" {...register('title', { required: true })} />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="description">Descrição do Projeto</S.Label>
+            <S.TextArea 
+              id="description"
+              placeholder="Descreva seu projeto..."
+              maxLength={MAX_CHARS}
+              {...register('description', {
+                maxLength: {
+                  value: MAX_CHARS,
+                  message: `A descrição não pode exceder ${MAX_CHARS} caracteres`
+                }
+              })}
+            />
+            <S.CharacterCount>
+              {descriptionLength} / {MAX_CHARS}
+            </S.CharacterCount>
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="startDate">Data de Início</S.Label>
+            <Controller
+              name="startDate"
+              control={control}
+              render={({ field: { onChange, value } }) => (
+                <S.Input
+                  as={IMaskInput}
+                  mask="00/00/0000"
+                  id="startDate"
+                  placeholder="DD/MM/AAAA"
+                  value={value} 
+                  onAccept={(value: string) => onChange(value)}
+                  disabled={isEditMode} 
+                />
+              )} 
+            />
+          </S.InputGroup>
+          
+          <S.InputGroup>
+            <S.Label htmlFor="technologies">Tecnologias (Palavras-chave)</S.Label>
+            <Controller
+              name="technologies"
+              control={control}
+              render={({ field }) => (
+                <TagInput 
+                  value={field.value}
+                  onChange={field.onChange}
+                  searchList={keywords}
+                  limit={6}
+                  placeholder="Adicione até 6 tecnologias..."
+                />
+              )}
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="status">Status</S.Label>
+            <S.SelectWrapper>
+              <S.Select 
+                id="status" 
+                {...register('status', { required: true })}
+                required 
+              >
+                <option value="" disabled>Selecione um status...</option>
+                <option value="em-andamento">Em andamento</option>
+                <option value="pausado">Pausado</option>
+                <option value="finalizado">Finalizado</option>
+              </S.Select>
+            </S.SelectWrapper>
+          </S.InputGroup>
+ 
+          {/* 10. Botão de submit dinâmico */}
+          <S.SubmitButton type="submit">
+            {isEditMode ? 'Atualizar Projeto' : 'Criar Projeto'}
+          </S.SubmitButton>
+ 
+        </S.FormContainer>
+      </ContentWrapper>
+    </PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/EditProfile/index.html b/frontend/coverage/src/pages/EditProfile/index.html new file mode 100644 index 0000000..63d764c --- /dev/null +++ b/frontend/coverage/src/pages/EditProfile/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/EditProfile + + + + + + + + + +
+
+

All files src/pages/EditProfile

+
+ +
+ 87.09% + Statements + 27/31 +
+ + +
+ 55.55% + Branches + 10/18 +
+ + +
+ 66.66% + Functions + 4/6 +
+ + +
+ 93.1% + Lines + 27/29 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
87.09%27/3155.55%10/1866.66%4/693.1%27/29
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/EditProfile/index.tsx.html b/frontend/coverage/src/pages/EditProfile/index.tsx.html new file mode 100644 index 0000000..caf88b4 --- /dev/null +++ b/frontend/coverage/src/pages/EditProfile/index.tsx.html @@ -0,0 +1,460 @@ + + + + + + Code coverage report for src/pages/EditProfile/index.tsx + + + + + + + + + +
+
+

All files / src/pages/EditProfile index.tsx

+
+ +
+ 87.09% + Statements + 27/31 +
+ + +
+ 55.55% + Branches + 10/18 +
+ + +
+ 66.66% + Functions + 4/6 +
+ + +
+ 93.1% + Lines + 27/29 +
+ + +
+

+ 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 +123 +124 +125 +126  +  +  +  +  +  +  +  +  +  +  +  +  +8x +8x +8x +  +  +8x +3x +3x +3x +3x +  +  +8x +  +  +8x +3x +3x +3x +3x +3x +3x +  +  +  +8x +2x +2x +2x +  +1x +  +1x +  +  +1x +  +  +  +  +1x +1x +1x +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState, useEffect } from 'react';
+import { useForm } from 'react-hook-form';
+import { useNavigate } from 'react-router-dom';
+import Sidebar from '../../components/layout/Sidebar';
+import { PageWrapper, ContentWrapper } from '../Feed/styles';
+import * as S from '../../components/domain/CreationForm/styles'; 
+import Toast from '../../components/common/Toast';
+import type { NotificationState } from '../../components/common/Toast';
+import { useAuth } from '../../API/AuthContext';
+import { UpdateProfile } from '../../API/User';
+import type { UserProfileData } from '../../API/User';
+ 
+export default function EditProfile() {
+  const { currentUser, updateUser } = useAuth(); 
+  const navigate = useNavigate();
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+  // Formata a data para o input (YYYY-MM-DD) 
+const formatDateForInput = (dateString?: string) => {
+  Iif (!dateString) return "";
+  const date = new Date(dateString);
+  Iif (isNaN(date.getTime())) return "";
+  return date.toISOString().split('T')[0];
+};
+ 
+  const { register, handleSubmit, setValue } = useForm<UserProfileData>();
+ 
+  // Preenche o formulário com os dados atuais
+  useEffect(() => {
+    Eif (currentUser) {
+      setValue('nomeCompleto', currentUser.nomeCompleto || '');
+      setValue('username', currentUser.username || '');
+      setValue('email', currentUser.email || '');
+      setValue('telefone', (currentUser as any).phone || ''); 
+      setValue('dataNascimento', formatDateForInput((currentUser as any).birthDate)); 
+    }
+  }, [currentUser, setValue]);
+ 
+  const onSubmit = async (data: UserProfileData) => {
+    try {
+      console.log("Atualizando perfil:", data);
+      await UpdateProfile(data);
+      
+      setNotification({ message: 'Perfil atualizado com sucesso!', type: 'success' });
+      
+      updateUser(data);
+ 
+      // Redireciona
+      setTimeout(() => {
+          navigate('/profile');
+      }, 1000);
+ 
+    } catch (error) {
+      console.error(error);
+      Eif (error instanceof Error) {
+        setNotification({ message: error.message, type: 'error' });
+      }
+    }
+  };
+ 
+  return (
+    <PageWrapper>
+      <Sidebar />
+      {notification && (
+        <Toast 
+            message={notification.message} 
+            type={notification.type} 
+            onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <ContentWrapper>
+        <S.FormContainer onSubmit={handleSubmit(onSubmit)}>
+          <h2>Editar Perfil</h2>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="nomeCompleto">Nome Completo</S.Label>
+            <S.Input 
+                id="nomeCompleto" 
+                {...register('nomeCompleto', { required: true })} 
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="username">Nome de Usuário</S.Label>
+            <S.Input 
+                id="username" 
+                {...register('username', { required: true })} 
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="email">Email</S.Label>
+            <S.Input 
+                id="email" 
+                type="email"
+                {...register('email', { required: true })} 
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="telefone">Telefone</S.Label>
+            <S.Input 
+                id="telefone" 
+                {...register('telefone')} 
+            />
+          </S.InputGroup>
+ 
+          <S.InputGroup>
+            <S.Label htmlFor="dataNascimento">Data de Nascimento</S.Label>
+            <S.Input 
+                id="dataNascimento" 
+                type="date"
+                {...register('dataNascimento')} 
+            />
+          </S.InputGroup>
+ 
+          <S.SubmitButton type="submit">
+            Salvar Alterações
+          </S.SubmitButton>
+ 
+        </S.FormContainer>
+      </ContentWrapper>
+    </PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Feed/index.html b/frontend/coverage/src/pages/Feed/index.html new file mode 100644 index 0000000..c09471f --- /dev/null +++ b/frontend/coverage/src/pages/Feed/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/pages/Feed + + + + + + + + + +
+
+

All files src/pages/Feed

+
+ +
+ 86.27% + Statements + 44/51 +
+ + +
+ 69.23% + Branches + 9/13 +
+ + +
+ 74.07% + Functions + 20/27 +
+ + +
+ 87.75% + Lines + 43/49 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
92.3%24/2669.23%9/1377.77%7/992.3%24/26
styles.ts +
+
80%20/25100%0/072.22%13/1882.6%19/23
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Feed/index.tsx.html b/frontend/coverage/src/pages/Feed/index.tsx.html new file mode 100644 index 0000000..70d7f62 --- /dev/null +++ b/frontend/coverage/src/pages/Feed/index.tsx.html @@ -0,0 +1,436 @@ + + + + + + Code coverage report for src/pages/Feed/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Feed index.tsx

+
+ +
+ 92.3% + Statements + 24/26 +
+ + +
+ 69.23% + Branches + 9/13 +
+ + +
+ 77.77% + Functions + 7/9 +
+ + +
+ 92.3% + Lines + 24/26 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +18x +18x +18x +18x +18x +  +18x +  +6x +6x +6x +5x +  +1x +1x +1x +  +  +6x +  +  +6x +  +  +18x +1x +1x +  +  +18x +1x +1x +  +  +18x +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState, useEffect } from 'react';
+import { useNavigate } from 'react-router-dom';
+import Modal from '../../components/common/Modal';
+import Postcard from '../../components/domain/Postcard';
+import Header from '../../components/layout/Header';
+import Sidebar from '../../components/layout/Sidebar';
+import * as S from './styles';
+import * as ModalS from '../../components/common/Modal/styles';
+import { GetFeedProjects } from '../../API/Project';
+import type { ProjectProps } from '../../API/Project';
+import Toast from '../../components/common/Toast'; 
+import type { NotificationState } from '../../components/common/Toast';
+ 
+export default function Feed() {
+    const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
+    const [isLoading, setIsLoading] = useState(true);
+    const navigate = useNavigate();
+    const [posts, setPosts] = useState<ProjectProps[]>([]);
+    const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+    useEffect(() => {
+        async function loadFeed() {
+            setIsLoading(true);
+            try {
+                const feedData = await GetFeedProjects();
+                setPosts(feedData || []);
+            } catch (error) {
+                console.error("Erro ao carregar feed:", error);
+                Eif (error instanceof Error) {
+                    setNotification({ message: "Não foi possível carregar o feed.", type: 'error' });
+                }
+            } finally {
+                setIsLoading(false);
+            }
+        }
+        loadFeed();
+    }, []);
+ 
+    const handleCreateProject = () => {
+        setIsCreateModalOpen(false);
+        navigate('/createProject');
+    };
+ 
+    const handleCreateCommunity = () => {
+        setIsCreateModalOpen(false);
+        navigate('/createCommunity');
+    };
+ 
+    return (
+        <S.PageWrapper>
+            {notification && (
+                <Toast 
+                    message={notification.message} 
+                    type={notification.type} 
+                    onClose={() => setNotification(null)} 
+                />
+            )}
+            
+            <Header onCreateClick={() => setIsCreateModalOpen(true)}/>
+            <Sidebar />
+ 
+            <S.ContentWrapper>
+                <S.FeedContainer>
+                    <S.PostList>
+                        {isLoading ? (
+                            <S.LoadingContainer>
+                                <div className="spinner"></div>
+                                <p>Carregando feed...</p>
+                            </S.LoadingContainer>
+                        ) : posts.length > 0 ? (
+                            posts.map((post, index) => (
+                                <Postcard 
+                                    key={(post as unknown as ProjectProps).id || (post as any).projectID || index} 
+                                    post={post} 
+                                    showMenu={false} 
+                                />
+                            ))
+                        ) : (
+                            <S.EmptyFeedMessage>
+                                <svg 
+                                    viewBox="0 0 24 24" 
+                                    fill="none" 
+                                    stroke="currentColor" 
+                                    strokeWidth="2"
+                                    strokeLinecap="round" 
+                                    strokeLinejoin="round"
+                                >
+                                    <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
+                                    <line x1="9" y1="9" x2="15" y2="15"/>
+                                    <line x1="15" y1="9" x2="9" y2="15"/>
+                                </svg>
+                                <h3>Nenhum post encontrado</h3>
+                                <p style={{ color: '#ccc', textAlign: 'center', marginTop: '20px' }}>
+                                    Nenhum post encontrado. Entre em comunidades para ver atualizações!
+                                </p>
+                            </S.EmptyFeedMessage>
+                        )}
+                    </S.PostList>
+                </S.FeedContainer>
+            </S.ContentWrapper>
+ 
+            <Modal 
+                isOpen={isCreateModalOpen} 
+                onClose={() => setIsCreateModalOpen(false)}
+                title="O que você deseja criar?"
+            >
+                <ModalS.ModalActions>
+                    <ModalS.ChoiceButton onClick={handleCreateProject}>
+                        Criar Projeto
+                    </ModalS.ChoiceButton>
+                    <ModalS.ChoiceButton onClick={handleCreateCommunity}>
+                        Criar Comunidade
+                    </ModalS.ChoiceButton>
+                </ModalS.ModalActions>
+            </Modal>
+        </S.PageWrapper>
+    );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Feed/styles.ts.html b/frontend/coverage/src/pages/Feed/styles.ts.html new file mode 100644 index 0000000..8f9df32 --- /dev/null +++ b/frontend/coverage/src/pages/Feed/styles.ts.html @@ -0,0 +1,709 @@ + + + + + + Code coverage report for src/pages/Feed/styles.ts + + + + + + + + + +
+
+

All files / src/pages/Feed styles.ts

+
+ +
+ 80% + Statements + 20/25 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 72.22% + Functions + 13/18 +
+ + +
+ 82.6% + Lines + 19/23 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209  +  +  +4x +44x +  +  +  +  +  +  +  +  +  +  +44x +44x +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +16x +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +16x +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +5x +  +  +  +  +  +  +  +  +  +  +  +  +  +5x +  +  +  +  +  +  +5x +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +  +  +  +  +  +  +10x +10x +  +  +  +  +  +  +  +  +  +10x +  +  + 
import styled from 'styled-components';
+ 
+// Wrapper para a página inteira
+export const PageWrapper = styled.div`
+    background: linear-gradient(135deg, ${props => props.theme['gray-100']} 0%, ${props => props.theme['gray-100']}f0 100%);
+    min-height: 100vh;
+    position: relative;
+    
+    &::before {
+        content: '';
+        position: fixed;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        background: radial-gradient(circle at 20% 50%, ${props => props.theme.keyword}08 0%, transparent 50%),
+                    radial-gradient(circle at 80% 80%, ${props => props.theme.button}08 0%, transparent 50%);
+        pointer-events: none;
+        z-index: 0;
+    }
+`;
+ 
+// Wrapper para o conteúdo principal
+export const ContentWrapper = styled.main`
+    margin-left: 250px; 
+    margin-top: 60px;  
+    padding: 32px 24px;
+    box-sizing: border-box;
+    position: relative;
+    z-index: 1;
+    animation: fadeIn 0.5s ease-out;
+ 
+    @keyframes fadeIn {
+        from {
+            opacity: 0;
+            transform: translateY(10px);
+        }
+        to {
+            opacity: 1;
+            transform: translateY(0);
+        }
+    }
+ 
+    @media (max-width: 768px) {
+        margin-left: 0;
+        padding: 20px 16px;
+    }
+`;
+ 
+// Container principal do feed com posts
+export const FeedContainer = styled.main`
+    width: 100%;
+    max-width: 800px; 
+    margin: 0 auto; 
+    background: ${props => props.theme.background};
+    backdrop-filter: blur(10px);
+    border-radius: 20px;
+    padding: 28px;
+    box-sizing: border-box;
+    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12),
+                0 2px 8px rgba(0, 0, 0, 0.08),
+                0 0 0 1px ${props => props.theme.placeholder}15;
+    position: relative;
+    transition: all 0.3s ease;
+ 
+    &::before {
+        content: '';
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        height: 3px;
+ 
+        background-size: 200% 100%;
+        border-radius: 20px 20px 0 0;
+        animation: gradientShift 3s ease infinite;
+    }
+ 
+    @keyframes gradientShift {
+        0%, 100% { background-position: 0% 50%; }
+        50% { background-position: 100% 50%; }
+    }
+ 
+    &:hover {
+        box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15),
+                    0 4px 12px rgba(0, 0, 0, 0.1),
+                    0 0 0 1px ${props => props.theme.placeholder}25;
+    }
+ 
+    @media (max-width: 768px) {
+        padding: 20px;
+        border-radius: 16px;
+    }
+`;
+ 
+// Lista que agrupa os posts
+export const PostList = styled.div`
+    display: flex;
+    flex-direction: column;
+    gap: 20px;
+    position: relative;
+ 
+    /* Animação de entrada para cada post */
+    & > * {
+        animation: slideInUp 0.4s ease-out backwards;
+    }
+ 
+    & > *:nth-child(1) { animation-delay: 0.05s; }
+    & > *:nth-child(2) { animation-delay: 0.1s; }
+    & > *:nth-child(3) { animation-delay: 0.15s; }
+    & > *:nth-child(4) { animation-delay: 0.2s; }
+    & > *:nth-child(5) { animation-delay: 0.25s; }
+    
+    @keyframes slideInUp {
+        from {
+            opacity: 0;
+            transform: translateY(20px);
+        }
+        to {
+            opacity: 1;
+            transform: translateY(0);
+        }
+    }
+`;
+ 
+// Mensagem de feed vazio
+export const EmptyFeedMessage = styled.div`
+    text-align: center;
+    padding: 60px 24px;
+    color: ${props => props.theme.placeholder};
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 16px;
+ 
+    svg {
+        width: 80px;
+        height: 80px;
+        opacity: 0.5;
+        margin-bottom: 8px;
+    }
+ 
+    h3 {
+        color: ${props => props.theme.subtitle};
+        font-size: 1.3rem;
+        font-weight: 600;
+        margin: 0 0 8px 0;
+    }
+ 
+    p {
+        color: ${props => props.theme.placeholder};
+        font-size: 0.95rem;
+        line-height: 1.5;
+        max-width: 400px;
+        margin: 0;
+    }
+`;
+ 
+// Header do feed 
+export const FeedHeader = styled.div`
+    margin-bottom: 24px;
+    padding-bottom: 20px;
+    border-bottom: 1px solid ${props => props.theme.placeholder}20;
+ 
+    h1 {
+        color: ${props => props.theme.white};
+        font-size: 1.8rem;
+        font-weight: 700;
+        margin: 0 0 8px 0;
+        background: linear-gradient(135deg, ${props => props.theme.white}, ${props => props.theme.subtitle});
+        -webkit-background-clip: text;
+        -webkit-text-fill-color: transparent;
+        background-clip: text;
+    }
+ 
+    p {
+        color: ${props => props.theme.placeholder};
+        font-size: 0.9rem;
+        margin: 0;
+    }
+`;
+ 
+// Container para loading state
+export const LoadingContainer = styled.div`
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 60px 24px;
+    gap: 16px;
+ 
+    .spinner {
+        width: 40px;
+        height: 40px;
+        border: 3px solid ${props => props.theme.placeholder}30;
+        border-top-color: ${props => props.theme.keyword};
+        border-radius: 50%;
+        animation: spin 0.8s linear infinite;
+    }
+ 
+    @keyframes spin {
+        to { transform: rotate(360deg); }
+    }
+ 
+    p {
+        color: ${props => props.theme.placeholder};
+        font-size: 0.9rem;
+    }
+`;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Home/index.html b/frontend/coverage/src/pages/Home/index.html new file mode 100644 index 0000000..e655fe0 --- /dev/null +++ b/frontend/coverage/src/pages/Home/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/Home + + + + + + + + + +
+
+

All files src/pages/Home

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
100%1/1100%0/0100%1/1100%1/1
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Home/index.tsx.html b/frontend/coverage/src/pages/Home/index.tsx.html new file mode 100644 index 0000000..494171f --- /dev/null +++ b/frontend/coverage/src/pages/Home/index.tsx.html @@ -0,0 +1,124 @@ + + + + + + Code coverage report for src/pages/Home/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Home index.tsx

+
+ +
+ 100% + Statements + 1/1 +
+ + +
+ 100% + Branches + 0/0 +
+ + +
+ 100% + Functions + 1/1 +
+ + +
+ 100% + Lines + 1/1 +
+ + +
+

+ 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  +  +  +  +1x +  +  +  +  +  +  +  +  + 
import HeaderHome from '../../components/layout/HeaderHome';
+import * as S from './styles';
+ 
+export default function Home() {
+    return (
+        <S.HomePageContainer>
+            <HeaderHome />
+            <S.ContentWrapper>
+                <S.SiteTitle>CTable</S.SiteTitle>
+                <S.Tagline>Descubra, compartilhe, aprenda, converse: um novo mundo se abre para os amantes de computação.</S.Tagline>
+            </S.ContentWrapper>
+    </S.HomePageContainer>
+    );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Login/index.html b/frontend/coverage/src/pages/Login/index.html new file mode 100644 index 0000000..a6fa6eb --- /dev/null +++ b/frontend/coverage/src/pages/Login/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/Login + + + + + + + + + +
+
+

All files src/pages/Login

+
+ +
+ 87.5% + Statements + 14/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 50% + Functions + 2/4 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
87.5%14/1675%3/450%2/487.5%14/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Login/index.tsx.html b/frontend/coverage/src/pages/Login/index.tsx.html new file mode 100644 index 0000000..b7ef58e --- /dev/null +++ b/frontend/coverage/src/pages/Login/index.tsx.html @@ -0,0 +1,340 @@ + + + + + + Code coverage report for src/pages/Login/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Login index.tsx

+
+ +
+ 87.5% + Statements + 14/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 50% + Functions + 2/4 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +10x +  +10x +10x +  +  +2x +2x +2x +  +1x +  +  +1x +  +1x +  +  +  +  +1x +  +  +1x +1x +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import {useState} from 'react';
+import {
+  FormPageContainer,
+  FormWrapper,
+  FormTitle,
+  StyledForm,
+  StyledInput,
+  SubmitButton,
+  RedirectLink
+} from '../../components/domain/Form/styles';
+import { useForm} from 'react-hook-form';
+import  Toast  from '../../components/common/Toast';
+import { useNavigate } from 'react-router-dom';
+import type { LoginProps } from '../../API/Auth';
+import { useAuth } from '../../API/AuthContext';
+import type { NotificationState } from '../../components/common/Toast';
+ 
+export default function LoginPage() {
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+  const { login } = useAuth();
+    
+  const { register, handleSubmit, formState: {isSubmitting} } = useForm<LoginProps>();
+  const navigate = useNavigate();
+  
+    async function onSubmit(data: LoginProps) {
+      console.log(data);
+      try{
+        await login(data);
+        
+        console.log('Usuário registrado com sucesso');
+        
+        // Define estado para mostrar notificação de sucesso
+        setNotification({ message: 'Usuário registrado com sucesso!', type: 'success' });
+    
+        setTimeout(() => {
+        navigate('/feed'); // Navega para a página de feed
+        }, 1000);
+        
+      } catch (error) { 
+        console.error('Erro ao registrar usuário:', error);
+        
+        // Define estado para mostrar notificação de erro
+        Eif (error instanceof Error){
+        setNotification({ message: error.message, type: 'error' });
+        }
+      } 
+  }
+ 
+  return (
+    <FormPageContainer>
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+      <FormWrapper>
+        <FormTitle>Login</FormTitle>
+        
+        <StyledForm onSubmit={handleSubmit(onSubmit)}>
+          <StyledInput 
+            type="text" 
+            placeholder="Email ou usuário" 
+            required 
+            {...register('username')}
+          />
+          <StyledInput 
+            type="password" 
+            placeholder="Senha" 
+            required 
+            {...register('senha')}
+          />
+          
+          <SubmitButton disabled = {isSubmitting} type="submit">Entrar</SubmitButton>
+        </StyledForm>
+ 
+        <RedirectLink>
+          Não tem uma conta? <a href="/register">Cadastre-se</a>
+        </RedirectLink>
+      </FormWrapper>
+    </FormPageContainer>
+  );
+}
+ 
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Profile/index.html b/frontend/coverage/src/pages/Profile/index.html new file mode 100644 index 0000000..a932326 --- /dev/null +++ b/frontend/coverage/src/pages/Profile/index.html @@ -0,0 +1,131 @@ + + + + + + Code coverage report for src/pages/Profile + + + + + + + + + +
+
+

All files src/pages/Profile

+
+ +
+ 92.43% + Statements + 110/119 +
+ + +
+ 82.25% + Branches + 51/62 +
+ + +
+ 89.58% + Functions + 43/48 +
+ + +
+ 94.54% + Lines + 104/110 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
89.88%80/8971.05%27/3882.75%24/2992.85%78/84
styles.ts +
+
100%30/30100%24/24100%19/19100%26/26
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Profile/index.tsx.html b/frontend/coverage/src/pages/Profile/index.tsx.html new file mode 100644 index 0000000..80973d5 --- /dev/null +++ b/frontend/coverage/src/pages/Profile/index.tsx.html @@ -0,0 +1,931 @@ + + + + + + Code coverage report for src/pages/Profile/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Profile index.tsx

+
+ +
+ 89.88% + Statements + 80/89 +
+ + +
+ 71.05% + Branches + 27/38 +
+ + +
+ 82.75% + Functions + 24/29 +
+ + +
+ 92.85% + Lines + 78/84 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +40x +  +  +  +  +1x +40x +  +  +  +1x +40x +  +  +  +  +  +  +  +  +42x +42x +42x +42x +  +42x +  +  +42x +42x +  +42x +42x +42x +  +42x +  +40x +40x +40x +  +40x +40x +  +39x +  +39x +39x +  +  +1x +  +  +  +40x +40x +  +  +  +42x +  +1x +1x +  +  +25x +7x +  +25x +25x +  +  +  +42x +1x +1x +  +  +42x +1x +  +  +1x +1x +  +  +  +42x +1x +1x +  +  +42x +  +3x +3x +  +3x +3x +1x +  +1x +  +1x +  +  +  +  +  +2x +2x +1x +1x +1x +  +1x +  +1x +  +3x +3x +  +  +  +  +42x +42x +37x +35x +  +  +2x +2x +  +  +  +  +  +5x +  +5x +2x +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +42x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +4x +4x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState, useRef, useEffect } from 'react';
+import Sidebar from '../../components/layout/Sidebar'; 
+import Postcard from '../../components/domain/Postcard'; 
+import * as S from './styles'; 
+import * as D from '../../components/common/Dropdown/styles';
+import type { ProjectProps } from '../../API/Project';
+import type { CommentProps } from '../../API/Comment';
+import { GetUserProjects } from '../../API/Project';
+import { GetUserComments, DeleteComment } from '../../API/Comment';
+import { useAuth } from '../../API/AuthContext';
+import { useNavigate } from 'react-router-dom';
+import { DeleteProfile } from '../../API/User';
+import Toast from '../../components/common/Toast';
+import Modal from '../../components/common/Modal';
+import * as ModalS from '../../components/common/Modal/styles';
+ 
+// --- ÍCONES ---
+const PostsIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
+    <polyline points="14 2 14 8 20 8" /><line x1="16" y1="13" x2="8" y2="13" /><line x1="16" y1="17" x2="8" y2="17" /><line x1="10" y1="9" x2="8" y2="9" />
+  </svg>
+);
+const CommentsIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
+  </svg>
+);
+const SettingsIcon = () => (
+  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
+    <circle cx="12" cy="12" r="1" /><circle cx="19" cy="12" r="1" /><circle cx="5" cy="12" r="1" />
+  </svg>
+);
+// -----------------------
+ 
+type ViewState = 'posts' | 'comments';
+ 
+export default function Profile() {
+  const { currentUser, logout } = useAuth();
+  const [view, setView] = useState<ViewState>('posts');
+  const [isMenuOpen, setIsMenuOpen] = useState(false);
+  const menuRef = useRef<HTMLDivElement>(null);
+ 
+  const navigate = useNavigate();
+ 
+  // Estados para os dados da API
+  const [userPosts, setUserPosts] = useState<ProjectProps[]>([]);
+  const [userComments, setUserComments] = useState<CommentProps[]>([]);
+ 
+  const [isDeleting, setIsDeleting] = useState(false);
+  const [isDeleteProfileModalOpen, setIsDeleteProfileModalOpen] = useState(false);
+  const [notification, setNotification] = useState<{message: string, type: 'success' | 'error'} | null>(null);
+ 
+  useEffect(() => {
+    // Função assíncrona para buscar todos os dados
+    console.log("Efeito de busca de dados do perfil disparado.");
+    const fetchProfileData = async () => {
+      try {;
+        
+        console.log("Usuário atual no Profile:", currentUser);
+        const apiUserPosts = await GetUserProjects();
+        
+        const apiUserComments: CommentProps[] = await GetUserComments();
+        
+        setUserPosts(apiUserPosts);
+        setUserComments(apiUserComments);
+ 
+      } catch (error) {
+        console.error("Falha ao buscar dados do perfil:", error);
+      } 
+      
+    };
+    Eif(currentUser)
+      fetchProfileData();
+  }, [currentUser]); 
+ 
+  // Lógica para fechar o menu ao clicar fora 
+  useEffect(() => {
+    function handleClickOutside(event: MouseEvent) {
+      Eif (menuRef.current && !menuRef.current.contains(event.target as Node)) {
+        setIsMenuOpen(false);
+      }
+    }
+    if (isMenuOpen) {
+      document.addEventListener('mousedown', handleClickOutside);
+    }
+    return () => {
+      document.removeEventListener('mousedown', handleClickOutside);
+    };
+  }, [isMenuOpen]);
+ 
+  const handleLogout = () => {
+    logout(); // Limpa o estado e o localStorage
+    navigate('/login'); // Redireciona para a tela de login
+  };
+ 
+  const handleDeleteComment = async (commentId: string) => {
+      await DeleteComment(commentId);
+      
+      // Remove o comentário deletado do estado local para sumir da tela instantaneamente
+      setUserComments((prevComments) => 
+          prevComments.filter(comment => comment.commentID !== commentId)
+      );
+  };
+ 
+  const handleEditProfile = () => {
+      setIsMenuOpen(false);
+      navigate('/editProfile');
+  };
+ 
+  const handleDeleteProfile = async () => {
+    
+    Iif (isDeleting) return;
+    setIsDeleting(true);
+ 
+      try {
+          await DeleteProfile();
+          setNotification({ message: "Perfil excluído com sucesso. Até logo!", type: 'success' });
+ 
+          setIsDeleteProfileModalOpen(false);
+          
+          setTimeout(() => {
+              logout(); // Desloga o usuário e limpa o storage
+              navigate('/login'); // Manda para login
+          }, 2000);
+ 
+      } catch (error) {
+          Eif (error instanceof Error) {
+              if (error.message.includes("não encontrado") || error.message.includes("not found")) {
+                  setNotification({ message: "Conta já encerrada. Redirecionando...", type: 'success' });
+                  setTimeout(() => { logout(); navigate('/login'); }, 2000);
+                  return;
+              }
+              setNotification({ message: error.message, type: 'error' });
+          }
+          setIsDeleteProfileModalOpen(false);
+      } finally {
+          setIsDeleting(false);
+          setIsDeleteProfileModalOpen(false);
+      }
+  };
+ 
+  // Função para renderizar o feed (posts ou comentários)
+  const renderFeed = () => {
+    if (view === 'posts') {
+      if (userPosts.length === 0) {
+        return <p style={{ color: '#fff', padding: '20px' }}>Nenhum projeto encontrado.</p>;
+      }
+ 
+     return userPosts.map((post, index) => (
+        <S.PostContainer key={index}>
+          <Postcard post={post} showMenu={true} />
+        </S.PostContainer>
+      ));
+    }
+ 
+    Eif (view === 'comments') {
+      // Mapeia 'userComments' 
+      return userComments.map(comment => (
+        <S.PostContainer key={comment.commentID || Math.random()}>
+          <Postcard 
+            post={{
+              id: comment.commentID,
+              title: `Comentou em: ${comment.projectTitle || 'Projeto'}`, 
+              description: comment.content, 
+              technologies: [],
+              status: '',
+              startDate: comment.createdAt,
+              // Passa o usuário atual como autor para o cabeçalho do card
+              author: { title: currentUser?.username || 'Você' } 
+            } as unknown as ProjectProps} 
+            showMenu={true} 
+            deleteLabel="Comentário"
+            onDelete={() => handleDeleteComment(comment.commentID!)}
+          />
+        </S.PostContainer>
+      ));
+    }
+ 
+    return null;
+  };
+ 
+  return (
+    <S.PageWrapper>
+      <Sidebar />
+ 
+      {notification && (
+        <Toast 
+            message={notification.message} 
+            type={notification.type} 
+            onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <S.ContentWrapper>
+ 
+        <S.ProfileHeader>
+            <S.ActionsWrapper ref={menuRef}>
+                <S.ProfileActions>
+                    <S.IconButton
+                        title="Ver publicações"
+                        $active={view === 'posts'}
+                        onClick={() => setView('posts')}
+                        >
+                        <PostsIcon />
+                    </S.IconButton>
+                    <S.IconButton
+                        title="Ver comentários"
+                        $active={view === 'comments'}
+                        onClick={() => setView('comments')}
+                        >
+                        <CommentsIcon />
+                    </S.IconButton>
+                    <S.IconButton
+                        title="Configurações"
+                        onClick={() => setIsMenuOpen(prev => !prev)}
+                        >
+                        <SettingsIcon />
+                    </S.IconButton>
+                </S.ProfileActions>
+ 
+                {isMenuOpen && (
+                <D.DropdownMenu>
+                    <D.MenuItem onClick={handleEditProfile}>Editar Perfil</D.MenuItem>
+                    <D.MenuItem onClick={handleLogout}>Sair</D.MenuItem>
+                    <D.Separator />
+                    <D.DangerMenuItem onClick={() => {
+                        setIsMenuOpen(false);
+                        setIsDeleteProfileModalOpen(true);
+                    }}>
+                        Excluir Perfil
+                    </D.DangerMenuItem>
+                </D.DropdownMenu>
+                )}
+ 
+            </S.ActionsWrapper>                
+        </S.ProfileHeader>
+        
+        <S.ProfileInfo>
+            <S.ProfileAvatar 
+              style={{ 
+                backgroundImage: undefined 
+              }} 
+            />
+            <S.Username>{currentUser?.username || 'Carregando...'}</S.Username>
+        </S.ProfileInfo>
+ 
+        <S.PostList>
+          {renderFeed()}
+        </S.PostList>
+        
+      </S.ContentWrapper>
+ 
+      <Modal 
+        isOpen={isDeleteProfileModalOpen} 
+        onClose={() => !isDeleting && setIsDeleteProfileModalOpen(false)}
+        title="Excluir Conta"
+      >
+        <div style={{ textAlign: 'center' }}>
+            <p style={{ marginBottom: '24px', color: '#555' }}>
+                Tem certeza que deseja excluir sua conta? <br/>
+                <strong>Todos os seus projetos, comunidades e comentários serão apagados permanentemente.</strong>
+            </p>
+            <ModalS.ModalActions>
+                <ModalS.ChoiceButton 
+                  onClick={() => setIsDeleteProfileModalOpen(false)}
+                  disabled={isDeleting}>
+                    Cancelar
+                </ModalS.ChoiceButton>
+                <ModalS.ChoiceButton 
+                    onClick={handleDeleteProfile} 
+                    style={{ backgroundColor: '#e74c3c' }}
+                    disabled={isDeleting}
+                >
+                    {isDeleting ? 'Excluindo...' : 'Excluir Conta'}
+                </ModalS.ChoiceButton>
+            </ModalS.ModalActions>
+        </div>
+      </Modal>
+ 
+    </S.PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Profile/styles.ts.html b/frontend/coverage/src/pages/Profile/styles.ts.html new file mode 100644 index 0000000..10d88f0 --- /dev/null +++ b/frontend/coverage/src/pages/Profile/styles.ts.html @@ -0,0 +1,922 @@ + + + + + + Code coverage report for src/pages/Profile/styles.ts + + + + + + + + + +
+
+

All files / src/pages/Profile styles.ts

+
+ +
+ 100% + Statements + 30/30 +
+ + +
+ 100% + Branches + 24/24 +
+ + +
+ 100% + Functions + 19/19 +
+ + +
+ 100% + Lines + 26/26 +
+ + +
+

+ 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 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280  +  +  +1x +40x +  +  +  +  +1x +  +  +  +  +  +  +1x +  +  +  +  +3x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +40x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +40x +40x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +40x +  +  +40x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +40x +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +1x +  +  +  +  +  +  +  +  +  +  +  +120x +  +  +120x +  +  +  +120x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +120x +  +  +  +  +  +  +  +  +  +  +  +  +  +120x +  +  +120x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +120x +  +  +  +  +1x +  +  + 
import styled from 'styled-components';
+ 
+// Wrapper para a página inteira
+export const PageWrapper = styled.div`
+  background: linear-gradient(135deg, ${props => props.theme['gray-100']} 0%, ${props => props.theme['gray-100'] || props.theme['gray-100']} 100%);
+  min-height: 100vh;
+`;
+ 
+// Wrapper para o conteúdo principal
+export const ContentWrapper = styled.main`
+  margin-left: 250px; 
+  box-sizing: border-box;
+  padding-bottom: 60px;
+`;
+ 
+// Container principal com posts
+export const PostContainer = styled.main`
+    width: 100%;
+    max-width: 800px; 
+    margin: 0 auto; 
+    
+    background-color: ${props => props.theme.background};
+    border-radius: 16px;
+    padding: 24px;
+    box-sizing: border-box;
+    
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04),
+                0 1px 2px rgba(0, 0, 0, 0.06);
+    
+    transition: all 0.3s ease;
+    
+    &:hover {
+        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08),
+                    0 2px 4px rgba(0, 0, 0, 0.06);
+        transform: translateY(-2px);
+    }
+`;
+ 
+// Lista que agrupa os posts do perfil
+export const PostList = styled.div`
+  display: flex;
+  flex-direction: column;
+  gap: 20px;
+  padding: 32px 24px;
+  
+  animation: fadeIn 0.4s ease-out;
+  
+  @keyframes fadeIn {
+    from {
+      opacity: 0;
+      transform: translateY(10px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+`;
+ 
+// Cabeçalho do perfil
+export const ProfileHeader = styled.header`
+  background: linear-gradient(135deg, ${props => props.theme.button} 0%, ${props => props.theme['hover-button'] || props.theme.button} 100%);
+  height: 160px;
+  position: relative;
+  z-index: 0;
+  
+  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
+  
+  /* Padrão decorativo sutil */
+  &::before {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background-image: 
+      radial-gradient(circle at 20% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
+      radial-gradient(circle at 80% 80%, rgba(255, 255, 255, 0.1) 0%, transparent 50%);
+    pointer-events: none;
+  }
+  
+  /* Posiciona os botões de ação */
+  display: flex;
+  justify-content: flex-end; 
+  align-items: flex-end; 
+  padding: 20px 32px; 
+`;
+ 
+// Container da foto + nome
+export const ProfileInfo = styled.div`
+  display: flex;
+  align-items: flex-end; 
+  gap: 20px;
+  
+  margin-top: -70px; 
+  margin-left: 32px; 
+  padding-bottom: 24px;
+  position: relative; 
+  z-index: 1; 
+  pointer-events: none; 
+  
+  animation: slideUp 0.5s ease-out;
+  
+  @keyframes slideUp {
+    from {
+      opacity: 0;
+      transform: translateY(20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0);
+    }
+  }
+  
+  /* Reativa pointer-events apenas nos elementos internos */
+  > * {
+    pointer-events: auto;
+  }
+`;
+ 
+// A foto de perfil circular
+export const ProfileAvatar = styled.div`
+  width: 120px; 
+  height: 120px;
+  border-radius: 50%;
+  background: linear-gradient(135deg, ${props => props.theme.sidebar} 0%, ${props => props.theme.button} 100%);
+  border: 5px solid ${props => props.theme.background}; 
+  background-size: cover;
+  background-position: center;
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15),
+              0 2px 8px rgba(0, 0, 0, 0.1);
+  
+  position: relative;
+  flex-shrink: 0;
+  
+  /* Efeito de brilho sutil */
+  &::after {
+    content: '';
+    position: absolute;
+    top: 10%;
+    left: 10%;
+    width: 40%;
+    height: 40%;
+    background: radial-gradient(circle, rgba(255, 255, 255, 0.3) 0%, transparent 70%);
+    border-radius: 50%;
+  }
+  
+  transition: transform 0.3s ease, box-shadow 0.3s ease;
+  
+  &:hover {
+    transform: scale(1.05);
+    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.2),
+                0 4px 12px rgba(0, 0, 0, 0.15);
+  }
+`;
+ 
+// O nome do usuário
+export const Username = styled.h1`
+  font-size: 2.5em;
+  font-weight: 700;
+  color: ${props => props.theme.title}; 
+  margin: 0 0 10px 0; /* Margem inferior para alinhar com a base do avatar */
+  
+  background: linear-gradient(135deg, ${props => props.theme.title} 0%, ${props => props.theme.subtitle} 100%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+  
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  
+  position: relative;
+  
+  &::after {
+    content: '';
+    position: absolute;
+    bottom: -8px;
+    left: 0;
+    width: 60px;
+    height: 4px;
+    background: linear-gradient(90deg, ${props => props.theme.button} 0%, transparent 100%);
+    border-radius: 2px;
+  }
+`;
+ 
+// Container dos 3 botões de ação (dentro do banner)
+export const ProfileActions = styled.div`
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  position: relative;
+  z-index: 3;
+  
+  /* Backdrop blur para destacar os botões */
+  background: rgba(255, 255, 255, 0.1);
+  backdrop-filter: blur(10px);
+  padding: 8px;
+  border-radius: 50px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+`;
+ 
+// Botão de ícone
+export const IconButton = styled.button<{ $active?: boolean }>`
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  border: none;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  
+  background-color: ${props => props.$active 
+    ? props.theme['hover-button'] || props.theme.button
+    : props.theme.background};
+  color: ${props => props.$active 
+    ? '#FFFFFF'
+    : props.theme.button}; 
+ 
+  box-shadow: ${props => props.$active
+    ? '0 4px 12px rgba(0, 0, 0, 0.15), inset 0 1px 2px rgba(255, 255, 255, 0.1)'
+    : '0 2px 8px rgba(0, 0, 0, 0.08)'};
+  
+  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ 
+  /* Efeito ripple */
+  &::before {
+    content: '';
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    width: 0;
+    height: 0;
+    border-radius: 50%;
+    background: ${props => props.$active 
+      ? 'rgba(255, 255, 255, 0.3)'
+      : 'rgba(0, 0, 0, 0.1)'};
+    transform: translate(-50%, -50%);
+    transition: width 0.6s, height 0.6s;
+  }
+ 
+  &:hover::before {
+    width: 100%;
+    height: 100%;
+  }
+ 
+  &:hover {
+    transform: translateY(-3px) scale(1.05);
+    box-shadow: ${props => props.$active
+      ? '0 6px 20px rgba(0, 0, 0, 0.2)'
+      : '0 4px 16px rgba(0, 0, 0, 0.12)'};
+    background-color: ${props => props.$active 
+      ? props.theme['hover-button'] || props.theme.button
+      : props.theme['gray-500'] || props.theme.background};
+  }
+ 
+  &:active {
+    transform: translateY(-1px) scale(1.02);
+  }
+ 
+  svg {
+    width: 22px;
+    height: 22px;
+    position: relative;
+    z-index: 1;
+    transition: transform 0.2s ease;
+  }
+ 
+  &:hover svg {
+    transform: ${props => props.$active ? 'rotate(5deg)' : 'scale(1.1)'};
+  }
+`;
+ 
+// Menus de ações flutuantes
+export const ActionsWrapper = styled.div`
+  position: relative; 
+  z-index: 5; /* Aumentado para ficar acima de tudo */
+`;
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/ProjectPage/index.html b/frontend/coverage/src/pages/ProjectPage/index.html new file mode 100644 index 0000000..9b718ab --- /dev/null +++ b/frontend/coverage/src/pages/ProjectPage/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/ProjectPage + + + + + + + + + +
+
+

All files src/pages/ProjectPage

+
+ +
+ 90% + Statements + 18/20 +
+ + +
+ 75% + Branches + 6/8 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 94.11% + Lines + 16/17 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
90%18/2075%6/8100%4/494.11%16/17
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/ProjectPage/index.tsx.html b/frontend/coverage/src/pages/ProjectPage/index.tsx.html new file mode 100644 index 0000000..09585d8 --- /dev/null +++ b/frontend/coverage/src/pages/ProjectPage/index.tsx.html @@ -0,0 +1,367 @@ + + + + + + Code coverage report for src/pages/ProjectPage/index.tsx + + + + + + + + + +
+
+

All files / src/pages/ProjectPage index.tsx

+
+ +
+ 90% + Statements + 18/20 +
+ + +
+ 75% + Branches + 6/8 +
+ + +
+ 100% + Functions + 4/4 +
+ + +
+ 94.11% + Lines + 16/17 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +4x +4x +4x +  +4x +  +2x +2x +2x +2x +2x +  +  +  +2x +  +  +2x +  +  +4x +2x +  +  +1x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +2x +  +  +  +  +  +  +  +  +  +  + 
import { useEffect, useState } from 'react';
+import { useParams } from 'react-router-dom';
+import Sidebar from '../../components/layout/Sidebar';
+import * as S from './styles';
+import { GetProjectById } from '../../API/Project';
+import type { ProjectProps } from '../../API/Project';
+import { FiCalendar, FiUser } from 'react-icons/fi';
+ 
+export default function ProjectPage() {
+  const { projectId } = useParams<{ projectId: string }>();
+  const [project, setProject] = useState<ProjectProps | null>(null);
+  const [loading, setLoading] = useState(true);
+ 
+  useEffect(() => {
+    async function loadData() {
+        Iif (!projectId) return;
+        try {
+            setLoading(true);
+            const data = await GetProjectById(projectId);
+            setProject(data);
+        } catch (error) {
+            console.error("Erro ao carregar projeto:", error);
+        } finally {
+            setLoading(false);
+        }
+    }
+    loadData();
+  }, [projectId]);
+ 
+  if (loading) return <div>Carregando...</div>;
+  if (!project) return <div>Projeto não encontrado</div>;
+ 
+  // Formata data
+  const startDate = new Date(project.startDate).toLocaleDateString('pt-BR');
+ 
+  return (
+    <S.PageWrapper>
+      <Sidebar />
+      
+      <S.MainContent>
+        <S.Banner />
+        
+        <S.HeaderContainer>
+          {/* Ícone com a inicial do projeto */}
+          <S.ProjectIcon>
+            {project.title.charAt(0).toUpperCase()}
+          </S.ProjectIcon>
+          
+          <S.HeaderInfo>
+            <h1>{project.title}</h1>
+            <span>
+                <FiUser style={{ marginRight: 5, verticalAlign: 'middle' }}/>
+                Criado por <strong>{project.authorUsername || project.authorName}</strong>
+            </span>
+          </S.HeaderInfo>
+        </S.HeaderContainer>
+ 
+        <S.ContentGrid>
+          
+          {/* Coluna Principal: Descrição */}
+          <S.MainColumn>
+            <h2>Sobre o Projeto</h2>
+            <S.DescriptionBox>
+                {project.description}
+            </S.DescriptionBox>
+ 
+          </S.MainColumn>
+ 
+          <S.InfoSidebar>
+            <h3>Status</h3>
+            <S.StatusBadge status={project.status}>
+                {project.status.replace('-', ' ')}
+            </S.StatusBadge>
+ 
+            <h3>Início</h3>
+            <div style={{ display: 'flex', alignItems: 'center', gap: '8px', color: '#555' }}>
+                <FiCalendar />
+                <span>{startDate}</span>
+            </div>
+ 
+            <h3>Tecnologias</h3>
+            <S.KeywordsContainer>
+              {project.technologies?.map((tech) => (
+                <S.KeywordTag key={tech}>
+                  {tech}
+                </S.KeywordTag>
+              ))}
+            </S.KeywordsContainer>
+          </S.InfoSidebar>
+ 
+        </S.ContentGrid>
+      </S.MainContent>
+    </S.PageWrapper>
+  );
+}
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Register/index.html b/frontend/coverage/src/pages/Register/index.html new file mode 100644 index 0000000..bbaf4b5 --- /dev/null +++ b/frontend/coverage/src/pages/Register/index.html @@ -0,0 +1,116 @@ + + + + + + Code coverage report for src/pages/Register + + + + + + + + + +
+
+

All files src/pages/Register

+
+ +
+ 87.5% + Statements + 14/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 60% + Functions + 3/5 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

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

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.tsx +
+
87.5%14/1675%3/460%3/587.5%14/16
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/coverage/src/pages/Register/index.tsx.html b/frontend/coverage/src/pages/Register/index.tsx.html new file mode 100644 index 0000000..78deec1 --- /dev/null +++ b/frontend/coverage/src/pages/Register/index.tsx.html @@ -0,0 +1,421 @@ + + + + + + Code coverage report for src/pages/Register/index.tsx + + + + + + + + + +
+
+

All files / src/pages/Register index.tsx

+
+ +
+ 87.5% + Statements + 14/16 +
+ + +
+ 75% + Branches + 3/4 +
+ + +
+ 60% + Functions + 3/5 +
+ + +
+ 87.5% + Lines + 14/16 +
+ + +
+

+ 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  +  +  +  +  +  +  +  +  +  +  +  +8x +  +  +8x +8x +  +  +2x +2x +2x +  +1x +  +  +1x +1x +  +  +  +  +1x +  +  +1x +1x +  +  +  +  +8x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +10x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  + 
import { useState } from 'react';
+import { FormPageContainer, FormWrapper, FormTitle, StyledForm, StyledInput, SubmitButton, RedirectLink } from '../../components/domain/Form/styles';
+import { useForm, Controller} from 'react-hook-form';
+import { IMaskInput } from 'react-imask';
+import  Toast  from '../../components/common/Toast';
+import { useNavigate } from 'react-router-dom';
+import {Register as RegisterAPI} from '../../API/Auth'
+import type { RegisterProps } from '../../API/Auth';
+import type { NotificationState } from '../../components/common/Toast';
+ 
+export default function Register() {
+  // Estado para a notificação - usado no Toast
+  const [notification, setNotification] = useState<NotificationState | null>(null);
+ 
+  
+  const { register, handleSubmit, formState: {isSubmitting}, control } = useForm<RegisterProps>();
+  const navigate = useNavigate();
+ 
+  async function onSubmit(data: RegisterProps) {
+    console.log(data);
+    try{
+      await RegisterAPI(data);
+      
+      console.log('Usuário registrado com sucesso:');
+      
+      // Define estado para mostrar notificação de sucesso
+      setNotification({ message: 'Usuário registrado com sucesso!', type: 'success' });
+      setTimeout(() => {
+        navigate('/feed'); // Navega para a página de feed
+      }, 1000);
+      
+    } catch (error) { 
+      console.error('Erro ao registrar usuário:', error);
+      
+      // Define estado para mostrar notificação de erro
+      Eif (error instanceof Error){
+        setNotification({ message: error.message, type: 'error' });
+      }
+    }
+  }
+ 
+  return (
+    <FormPageContainer>
+      
+      {notification && (
+        <Toast
+          message={notification.message}
+          type={notification.type}
+          onClose={() => setNotification(null)} 
+        />
+      )}
+ 
+      <FormWrapper>
+        <FormTitle>Criar conta</FormTitle>
+        
+        <StyledForm onSubmit={handleSubmit(onSubmit)}>
+          <StyledInput 
+            type="text" 
+            placeholder="Nome completo" 
+            required 
+            {...register('nomeCompleto')}
+          />
+          <StyledInput 
+            type="text" 
+            placeholder="Nome de usuário (user)" 
+            required 
+            {...register('username')}
+          />
+          <StyledInput 
+            type="email" 
+            placeholder="Email" 
+            required 
+            {...register('email')}
+          />
+          <StyledInput 
+            type="password" 
+            placeholder="Senha" 
+            required 
+            {...register('senha')}
+          />
+          <StyledInput 
+            type="tel" 
+            placeholder="Telefone" 
+            required 
+            {...register('telefone')}
+          />
+          <Controller
+            name="dataNascimento"
+            control={control}
+            rules={{ required: true }} 
+            render={({ field }) => (
+              <StyledInput
+                {...field}
+                as={IMaskInput} 
+                mask="00/00/0000"
+                placeholder="Data de nascimento"
+                required
+              />
+            )}
+          />
+          
+          <SubmitButton disabled = {isSubmitting} type="submit">Cadastrar</SubmitButton>
+        </StyledForm>
+ 
+        <RedirectLink>
+          Já tem uma conta? <a href="/login">Faça login</a>
+        </RedirectLink>
+      </FormWrapper>
+    </FormPageContainer>
+  );
+}
+ 
+ 
+ +
+
+ + + + + + + + \ No newline at end of file diff --git a/frontend/src/API/Auth.ts b/frontend/src/API/Auth.ts index 93b9429..a33016a 100644 --- a/frontend/src/API/Auth.ts +++ b/frontend/src/API/Auth.ts @@ -1,4 +1,4 @@ -import api from './api'; // Importa a instância que criamos no Passo 2 +import api from './api'; import { isAxiosError } from 'axios'; export interface LoginProps { diff --git a/frontend/src/API/AuthContext.tsx b/frontend/src/API/AuthContext.tsx index e02d596..791ade2 100644 --- a/frontend/src/API/AuthContext.tsx +++ b/frontend/src/API/AuthContext.tsx @@ -46,7 +46,7 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => // Função de login que atualiza o estado E o localStorage const login = async (data: LoginProps) => { - const { user, token } = await api.Login(data); // Chama sua API + const { user, token } = await api.Login(data); localStorage.setItem('token', token); localStorage.setItem('user', JSON.stringify(user)); setCurrentUser(user); diff --git a/frontend/src/API/Comment.ts b/frontend/src/API/Comment.ts index 7bbffdb..4a153f9 100644 --- a/frontend/src/API/Comment.ts +++ b/frontend/src/API/Comment.ts @@ -1,5 +1,6 @@ import api from './api'; import { isAxiosError } from 'axios'; + export interface CommentProps { projectTitle?: string; commentID?: string; diff --git a/frontend/src/API/Project.ts b/frontend/src/API/Project.ts index c59f70d..bff8c5e 100644 --- a/frontend/src/API/Project.ts +++ b/frontend/src/API/Project.ts @@ -14,10 +14,8 @@ export interface ProjectProps { } export function parseDate(dataString: string): Date { - // Divide a string "20/11/2025" em partes const [dia, mes, ano] = dataString.split('/'); - // Cria a data: new Date(ano, mês - 1, dia) return new Date(Number(ano), Number(mes) - 1, Number(dia)); } diff --git a/frontend/src/App.spec.tsx b/frontend/src/App.spec.tsx index 4dc6aeb..2c0fe9b 100644 --- a/frontend/src/App.spec.tsx +++ b/frontend/src/App.spec.tsx @@ -2,7 +2,6 @@ import { render, screen } from '@testing-library/react'; import { describe, it, expect, vi } from 'vitest'; import App from './App'; -// --- Mocks --- vi.mock('./Router', () => ({ Router: () =>
Router Content
})); diff --git a/frontend/src/components/common/Keyword/index.tsx b/frontend/src/components/common/Keyword/index.tsx index f3eff70..a41eb7d 100644 --- a/frontend/src/components/common/Keyword/index.tsx +++ b/frontend/src/components/common/Keyword/index.tsx @@ -1,7 +1,6 @@ import React from 'react'; import * as S from './styles'; -// Props que o componente Keyword aceita interface KeywordProps { children: React.ReactNode; onRemove: () => void; diff --git a/frontend/src/components/common/Modal/Modal.spec.tsx b/frontend/src/components/common/Modal/Modal.spec.tsx index 812a068..ba96bcf 100644 --- a/frontend/src/components/common/Modal/Modal.spec.tsx +++ b/frontend/src/components/common/Modal/Modal.spec.tsx @@ -82,10 +82,8 @@ describe('Componente Modal', () => { ); - // Clica no cartão do modal (conteúdo) fireEvent.click(screen.getByTestId('content')); - // A função de fechar NÃO deve ser chamada expect(handleClose).not.toHaveBeenCalled(); }); }); \ No newline at end of file diff --git a/frontend/src/components/common/Toast/Toast.spec.tsx b/frontend/src/components/common/Toast/Toast.spec.tsx index 1e94ba4..e551945 100644 --- a/frontend/src/components/common/Toast/Toast.spec.tsx +++ b/frontend/src/components/common/Toast/Toast.spec.tsx @@ -50,12 +50,11 @@ describe('Componente Toast', () => { // Verifica que ainda não foi chamado expect(handleClose).not.toHaveBeenCalled(); - // Avança o tempo em 5000ms (5 segundos) + // Avança o tempo em 5000ms act(() => { vi.advanceTimersByTime(5000); }); - // Agora deve ter sido chamado expect(handleClose).toHaveBeenCalledTimes(1); }); diff --git a/frontend/src/components/common/Toast/index.tsx b/frontend/src/components/common/Toast/index.tsx index e9a2235..48189b2 100644 --- a/frontend/src/components/common/Toast/index.tsx +++ b/frontend/src/components/common/Toast/index.tsx @@ -4,7 +4,7 @@ import { ToastContainer, ToastMessage, CloseButton } from './styles'; interface ToastProps { message: string; type: 'success' | 'error'; - onClose: () => void; // Função para fechar o toast + onClose: () => void; } export interface NotificationState { diff --git a/frontend/src/components/domain/Postcard/Postcard.spec.tsx b/frontend/src/components/domain/Postcard/Postcard.spec.tsx index 116a5a7..7e843b1 100644 --- a/frontend/src/components/domain/Postcard/Postcard.spec.tsx +++ b/frontend/src/components/domain/Postcard/Postcard.spec.tsx @@ -5,7 +5,6 @@ import { BrowserRouter } from 'react-router-dom'; import * as ProjectAPI from '../../../API/Project'; import * as CommentAPI from '../../../API/Comment'; -// --- Mocks --- // Mock do hook useAuth vi.mock('../../../API/AuthContext', () => ({ @@ -102,7 +101,6 @@ describe('Componente Postcard', () => { it('NÃO deve navegar se clicar em um botão interativo dentro do card', () => { render(); - // Clica no botão de menu (que está dentro do wrapper) fireEvent.click(screen.getByTestId('menu-btn')); // O menu deve abrir, mas a navegação NÃO deve ocorrer @@ -126,7 +124,6 @@ describe('Componente Postcard', () => { fireEvent.click(screen.getByTestId('menu-btn')); fireEvent.click(screen.getByTestId('delete-post-btn')); - // Botão de confirmação no modal (segundo botão "Excluir" na tela) const modalButtons = screen.getAllByText('Excluir'); fireEvent.click(modalButtons[modalButtons.length - 1]); @@ -158,7 +155,6 @@ describe('Componente Postcard', () => { fireEvent.click(screen.getByTestId('delete-post-btn')); - // Confirmação no Modal (o último botão "Excluir" está no modal) const buttons = screen.getAllByText('Excluir'); const confirmDeleteBtn = buttons[buttons.length - 1]; fireEvent.click(confirmDeleteBtn); diff --git a/frontend/src/components/domain/Postcard/index.tsx b/frontend/src/components/domain/Postcard/index.tsx index 9dee11c..7c0f3ca 100644 --- a/frontend/src/components/domain/Postcard/index.tsx +++ b/frontend/src/components/domain/Postcard/index.tsx @@ -27,7 +27,7 @@ const CommentIcon = () => ( ); -// --- Ícone de Menu (Ellipsis) --- +// Ícone de Menu (Ellipsis) const EllipsisIcon = () => ( @@ -41,7 +41,6 @@ interface PostcardProps { deleteLabel?: string; } -// --- Componente Postcard --- export default function Postcard({ post, showMenu, onDelete, deleteLabel = 'Projeto' }: PostcardProps) { const { currentUser } = useAuth(); @@ -77,7 +76,7 @@ export default function Postcard({ post, showMenu, onDelete, deleteLabel = 'Proj } } - // Lógica para fechar o menu ao clicar fora (sem alterações) + // Lógica para fechar o menu ao clicar fora useEffect(() => { function handleClickOutside(event: MouseEvent) { if (menuRef.current && !menuRef.current.contains(event.target as Node)) { @@ -164,7 +163,7 @@ export default function Postcard({ post, showMenu, onDelete, deleteLabel = 'Proj }; const handleCardClick = (e: React.MouseEvent) => { - // Não navega se estiver na aba de comentários do perfil (deleteLabel 'Comentário') + // Não navega se estiver na aba de comentários do perfil if (deleteLabel !== 'Projeto') return; // Não navega se o clique foi em um elemento interativo diff --git a/frontend/src/components/domain/Searchbar/Searchbar.spec.tsx b/frontend/src/components/domain/Searchbar/Searchbar.spec.tsx index 2426639..9d4844e 100644 --- a/frontend/src/components/domain/Searchbar/Searchbar.spec.tsx +++ b/frontend/src/components/domain/Searchbar/Searchbar.spec.tsx @@ -107,14 +107,12 @@ describe('Componente Searchbar', () => { // Focar no input deve disparar o carregamento fireEvent.focus(input); - // Digitar algo fireEvent.change(input, { target: { value: 'Vitest' } }); - // Aguarda o dropdown aparecer e os resultados serem filtrados const projectItem = await screen.findByText('Projeto Vitest'); expect(projectItem).toBeInTheDocument(); - // Deve mostrar o Projeto, mas não a Comunidade (pois 'React Devs' não bate com 'Vitest') + // Deve mostrar o Projeto, mas não a Comunidade expect(screen.getByText('Projeto Vitest')).toBeInTheDocument(); expect(screen.queryByText('React Devs')).not.toBeInTheDocument(); }); diff --git a/frontend/src/components/domain/Searchbar/index.tsx b/frontend/src/components/domain/Searchbar/index.tsx index 0070209..f73bf7f 100644 --- a/frontend/src/components/domain/Searchbar/index.tsx +++ b/frontend/src/components/domain/Searchbar/index.tsx @@ -2,7 +2,6 @@ import React, { useState, useEffect, useRef } from 'react'; import { FiSearch } from 'react-icons/fi'; import * as S from './styles'; import { useNavigate } from 'react-router-dom'; - import { GetAllCommunities } from '../../../API/Community'; import { GetFeedProjects } from '../../../API/Project'; import type { CommunityProps } from '../../../API/Community'; @@ -70,7 +69,7 @@ export default function Searchbar() { ); setFilteredCommunities(filteredComms.slice(0, 5)); // Limita a 5 resultados - setFilteredProjects(filteredProjs.slice(0, 5)); // Limita a 5 resultados + setFilteredProjects(filteredProjs.slice(0, 5)); }, [query, allCommunities, allProjects]); @@ -130,7 +129,6 @@ export default function Searchbar() { onClick={() => handleNavigateToCommunity(comm.communityID)} > {comm.name} - {/* Opcional: mostrar tecnologia principal */} {comm.technologies?.[0] && {comm.technologies[0]}} ))} diff --git a/frontend/src/components/domain/TagInput/TagInput.spec.tsx b/frontend/src/components/domain/TagInput/TagInput.spec.tsx index 04ef8c1..73ec61e 100644 --- a/frontend/src/components/domain/TagInput/TagInput.spec.tsx +++ b/frontend/src/components/domain/TagInput/TagInput.spec.tsx @@ -2,7 +2,7 @@ import { render, screen, fireEvent } from '@testing-library/react'; import { describe, it, expect, vi, beforeEach } from 'vitest'; import TagInput from './'; -// Mock dos estilos para evitar erros de ThemeProvider +// Mock dos estilos vi.mock('../CreationForm/styles', () => ({ SearchWrapper: ({ children, ref }: { children: React.ReactNode; ref: React.Ref }) =>
{children}
, Input: (props: React.InputHTMLAttributes) => , @@ -11,7 +11,7 @@ vi.mock('../CreationForm/styles', () => ({ ErrorMessage: ({ children }: { children: React.ReactNode }) => {children}, })); -// Mock do componente Keyword (visualização da tag) +// Mock do componente Keyword vi.mock('../../common/Keyword', () => ({ KeywordContainer: ({ children }: { children: React.ReactNode }) =>
{children}
, Keyword: ({ children, onRemove }: { children: React.ReactNode; onRemove: () => void }) => ( @@ -98,7 +98,7 @@ describe('Componente TagInput', () => { const removeBtn = screen.getByTestId('remove-React'); fireEvent.click(removeBtn); - // Deve chamar onChange com a lista filtrada (sem 'React') + // Deve chamar onChange com a lista filtrada expect(mockOnChange).toHaveBeenCalledWith(['Vitest']); }); diff --git a/frontend/src/components/domain/TagInput/index.tsx b/frontend/src/components/domain/TagInput/index.tsx index ccdd7ea..7e0ed10 100644 --- a/frontend/src/components/domain/TagInput/index.tsx +++ b/frontend/src/components/domain/TagInput/index.tsx @@ -52,7 +52,6 @@ export default function TagInput({ // Adiciona uma tag const handleAddTag = (tag: string) => { - // Usa o 'limit' da prop if (selectedTags.length >= limit) { setError(`Limite de ${limit} itens atingido.`); return; @@ -65,7 +64,6 @@ export default function TagInput({ } }; - // Remove uma tag const handleRemoveTag = (tagToRemove: string) => { onChange(selectedTags.filter(tag => tag !== tagToRemove)); setError(''); diff --git a/frontend/src/components/layout/HeaderHome/HeaderHome.spec.tsx b/frontend/src/components/layout/HeaderHome/HeaderHome.spec.tsx index d13df6f..131c69f 100644 --- a/frontend/src/components/layout/HeaderHome/HeaderHome.spec.tsx +++ b/frontend/src/components/layout/HeaderHome/HeaderHome.spec.tsx @@ -7,7 +7,6 @@ import { BrowserRouter } from 'react-router-dom'; vi.mock('./styles', () => ({ HeaderContainer: ({ children }: { children: React.ReactNode }) =>
{children}
, ActionsContainer: ({ children }: { children: React.ReactNode }) =>
{children}
, - // Simulando o componente Button (que é um Link) Button: ({ children, to }: { children: React.ReactNode; to: string }) => {children}, })); diff --git a/frontend/src/components/layout/HeaderHome/styles.ts b/frontend/src/components/layout/HeaderHome/styles.ts index b8c7ac0..c040713 100644 --- a/frontend/src/components/layout/HeaderHome/styles.ts +++ b/frontend/src/components/layout/HeaderHome/styles.ts @@ -65,7 +65,7 @@ export const ActionsContainer = styled.div` z-index: 1; `; -// Botão melhorado +// Botão export const Button = styled(Link)` display: flex; align-items: center; @@ -161,24 +161,3 @@ export const Button = styled(Link)` } } `; - -// Logo/Brand (opcional, caso queira adicionar) -export const Logo = styled.div` - font-size: 1.4rem; - font-weight: 700; - color: ${props => props.theme.white}; - background: linear-gradient(135deg, - ${props => props.theme.keyword}, - ${props => props.theme.button} - ); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - letter-spacing: -0.5px; - cursor: pointer; - transition: transform 0.2s ease; - - &:hover { - transform: scale(1.05); - } -`; \ No newline at end of file diff --git a/frontend/src/components/layout/Sidebar/Sidebar.spec.tsx b/frontend/src/components/layout/Sidebar/Sidebar.spec.tsx index 161b1e0..b242287 100644 --- a/frontend/src/components/layout/Sidebar/Sidebar.spec.tsx +++ b/frontend/src/components/layout/Sidebar/Sidebar.spec.tsx @@ -3,9 +3,6 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import Sidebar from './index'; import { BrowserRouter } from 'react-router-dom'; import * as CommunityAPI from '../../../API/Community'; -import * as AuthContext from '../../../API/AuthContext'; - -// --- Mocks --- // Mock do contexto de autenticação vi.mock('../../../API/AuthContext', () => ({ diff --git a/frontend/src/pages/CommunityPage/CommunityPage.spec.tsx b/frontend/src/pages/CommunityPage/CommunityPage.spec.tsx index 35cd3fd..a1b4476 100644 --- a/frontend/src/pages/CommunityPage/CommunityPage.spec.tsx +++ b/frontend/src/pages/CommunityPage/CommunityPage.spec.tsx @@ -4,7 +4,6 @@ import CommunityPage from './index'; import { BrowserRouter } from 'react-router-dom'; import * as CommunityAPI from '../../API/Community'; -// --- Mocks --- const navigateMock = vi.fn(); const mockParams = { communityID: '100' }; @@ -17,7 +16,6 @@ vi.mock('react-router-dom', async () => { }; }); -// Mock das APIs vi.mock('../../API/Community', () => ({ GetCommunityById: vi.fn(), JoinCommunity: vi.fn(), @@ -25,7 +23,6 @@ vi.mock('../../API/Community', () => ({ DeleteCommunity: vi.fn(), })); -// Mocks Visuais vi.mock('../../components/layout/Sidebar', () => ({ default: () =>
})); vi.mock('../../components/domain/Postcard', () => ({ default: ({ post }: { post: { title: string } }) =>
{post.title}
@@ -34,7 +31,6 @@ vi.mock('../../components/common/Toast', () => ({ default: ({ message }: { message: string }) =>
{message}
})); -// Mock Modal (renderiza se aberto) interface ModalMockProps { isOpen: boolean; children: React.ReactNode; @@ -55,7 +51,6 @@ vi.mock('../../components/common/Modal/styles', () => ({ ChoiceButton: ({ children, onClick }: { children: React.ReactNode; onClick: React.MouseEventHandler }) => , })); -// Mock Dropdown vi.mock('../../components/common/Dropdown/styles', () => { const DropdownMenu = ({ children }: { children: React.ReactNode }) => ; DropdownMenu.toString = () => '#dropdown-menu-mock'; @@ -145,7 +140,7 @@ describe('Página CommunityPage', () => { expect(screen.getByTestId('modal')).toBeInTheDocument(); expect(screen.getByText('Sair da Comunidade')).toBeInTheDocument(); - // onfirma no modal + // Confirma no modal const buttons = screen.getAllByText('Sair'); fireEvent.click(buttons[buttons.length - 1]); diff --git a/frontend/src/pages/CommunityPage/index.tsx b/frontend/src/pages/CommunityPage/index.tsx index 9cc1989..aa59f03 100644 --- a/frontend/src/pages/CommunityPage/index.tsx +++ b/frontend/src/pages/CommunityPage/index.tsx @@ -113,7 +113,7 @@ export default function CommunityPage() { try { await LeaveCommunity(community.communityID); - // Atualiza a interface otimisticamente + // Atualiza a interface setCommunity((prev: CommunityProps | null) => prev ? ({ ...prev, isMember: false, // O usuário não é mais membro diff --git a/frontend/src/pages/CreateProject/CreateProject.spec.tsx b/frontend/src/pages/CreateProject/CreateProject.spec.tsx index c9459b2..107464c 100644 --- a/frontend/src/pages/CreateProject/CreateProject.spec.tsx +++ b/frontend/src/pages/CreateProject/CreateProject.spec.tsx @@ -5,7 +5,6 @@ import { BrowserRouter } from 'react-router-dom'; import * as ProjectAPI from '../../API/Project'; import * as KeywordsAPI from '../../API/Keywords'; -// --- Mocks --- const navigateMock = vi.fn(); let mockLocationState: unknown = null; @@ -20,7 +19,6 @@ vi.mock('react-router-dom', async () => { }; }); -// Mock da API vi.mock('../../API/Project', async () => { const actual = await vi.importActual('../../API/Project'); return { @@ -34,11 +32,9 @@ vi.mock('../../API/Keywords', () => ({ GetKeywords: vi.fn(), })); -// Mocks Visuais vi.mock('../../components/layout/Sidebar', () => ({ default: () =>
})); vi.mock('../../components/common/Toast', () => ({ default: ({ message }: { message: string }) =>
{message}
})); -// Mock do TagInput vi.mock('../../components/domain/TagInput', () => ({ default: ({ onChange, value }: { onChange: (val: string[]) => void; value: string[] }) => ( ({ @@ -195,7 +195,6 @@ export default function CreateProject() { - {/* 10. Botão de submit dinâmico */} {isEditMode ? 'Atualizar Projeto' : 'Criar Projeto'} diff --git a/frontend/src/pages/EditProfile/EditProfile.spec.tsx b/frontend/src/pages/EditProfile/EditProfile.spec.tsx index 82cec98..1d85b8b 100644 --- a/frontend/src/pages/EditProfile/EditProfile.spec.tsx +++ b/frontend/src/pages/EditProfile/EditProfile.spec.tsx @@ -4,11 +4,9 @@ import EditProfile from './index'; import { BrowserRouter } from 'react-router-dom'; import * as UserAPI from '../../API/User'; -// --- Mocks --- const navigateMock = vi.fn(); const updateUserMock = vi.fn(); -// Mock do usuário atual logado const mockCurrentUser = { nomeCompleto: 'João Silva', username: 'joaosilva', @@ -33,11 +31,9 @@ vi.mock('../../API/AuthContext', () => ({ }) })); -// Mocks Visuais vi.mock('../../components/layout/Sidebar', () => ({ default: () =>
})); vi.mock('../../components/common/Toast', () => ({ default: ({ message }: { message: string }) =>
{message}
})); -// Mock dos estilos de formulário interface FormStyleProps { children?: React.ReactNode; onSubmit?: React.FormEventHandler; @@ -68,7 +64,6 @@ describe('Página EditProfile', () => { expect(screen.getByLabelText('Nome Completo')).toHaveValue('João Silva'); expect(screen.getByLabelText('Nome de Usuário')).toHaveValue('joaosilva'); expect(screen.getByLabelText('Email')).toHaveValue('joao@email.com'); - // A data é formatada para YYYY-MM-DD no componente expect(screen.getByLabelText('Data de Nascimento')).toHaveValue('1990-01-01'); }); diff --git a/frontend/src/pages/Feed/Feed.spec.tsx b/frontend/src/pages/Feed/Feed.spec.tsx index 783411c..8bdd3a7 100644 --- a/frontend/src/pages/Feed/Feed.spec.tsx +++ b/frontend/src/pages/Feed/Feed.spec.tsx @@ -4,8 +4,6 @@ import Feed from './'; import { BrowserRouter } from 'react-router-dom'; import * as ProjectAPI from '../../API/Project'; -// 1. Mocks de Componentes Filhos -// Mockamos os componentes visuais para focar na lógica da página Feed vi.mock('../../components/layout/Header', () => ({ default: ({ onCreateClick }: { onCreateClick: () => void }) => (