diff --git a/et --hard HEAD@{2} b/et --hard HEAD@{2} new file mode 100644 index 0000000000000000000000000000000000000000..080506ee11eb7b72adccd7694b14aa7fc112bc78 --- /dev/null +++ b/et --hard HEAD@{2} @@ -0,0 +1,485 @@ +[33m6234e68[m[33m ([m[1;36mHEAD -> [m[1;32missue/271.1-create-new-backend-routes-connection[m[33m)[m HEAD@{0}: rebase (continue) (finish): returning to refs/heads/issue/271.1-create-new-backend-routes-connection +[33m6234e68[m[33m ([m[1;36mHEAD -> [m[1;32missue/271.1-create-new-backend-routes-connection[m[33m)[m HEAD@{1}: rebase (continue): rebase +[33m347541c[m HEAD@{2}: rebase (continue): rebase +[33m97779d6[m HEAD@{3}: rebase (continue): ok +[33m05dace3[m HEAD@{4}: rebase (continue) (pick): ok +[33me3b8b31[m HEAD@{5}: rebase (continue) (pick): Issue #287: UPDATE mecred statistics on about page +[33m5e83680[m HEAD@{6}: rebase (continue): Issue #289: ADD Icons on profile page (verified) +[33mcda5c94[m HEAD@{7}: rebase (continue) (pick): Issue #290: FIX Style of the share profile button +[33md893a7a[m HEAD@{8}: rebase (continue) (pick): Issue #291: User card: update information +[33m8d8c38b[m HEAD@{9}: rebase (continue): Issue #288: UPDATE change order icons sidebar +[33m82b17e3[m HEAD@{10}: rebase (pick): Issue #280: FIX remove profile icon offline +[33md70485c[m HEAD@{11}: rebase (pick): FIX Correction of the random color vector and other details, plus removal of statistics +[33mc48bb0a[m HEAD@{12}: rebase (pick): Issue #282: FIX profile edition on HC +[33m0685262[m[33m ([m[1;31morigin/issue/271.gus[m[33m, [m[1;32missue/271.gus[m[33m)[m HEAD@{13}: rebase (start): checkout issue/271.gus +[33mae8f559[m HEAD@{14}: checkout: moving from issue/271.gus to issue/271.1-create-new-backend-routes-connection +[33m0685262[m[33m ([m[1;31morigin/issue/271.gus[m[33m, [m[1;32missue/271.gus[m[33m)[m HEAD@{15}: checkout: moving from issue/271.1-create-new-backend-routes-connection to issue/271.gus +[33mae8f559[m HEAD@{16}: rebase (finish): returning to refs/heads/issue/271.1-create-new-backend-routes-connection +[33mae8f559[m HEAD@{17}: rebase (pick): rebase +[33mc09911e[m HEAD@{18}: rebase (pick): rebase +[33m6a29086[m HEAD@{19}: rebase (pick): ok +[33m9535dd5[m HEAD@{20}: rebase (pick): ok +[33mc2308b4[m HEAD@{21}: rebase (pick): Issue #287: UPDATE mecred statistics on about page +[33mb624b7b[m HEAD@{22}: rebase (pick): Issue #289: ADD Icons on profile page (verified) +[33m22ea969[m HEAD@{23}: rebase (pick): Issue #290: FIX Style of the share profile button +[33m87445ec[m HEAD@{24}: rebase (pick): Issue #291: User card: update information +[33mf9c42e9[m HEAD@{25}: rebase (pick): Issue #288: UPDATE change order icons sidebar +[33m5d6caf1[m HEAD@{26}: rebase (pick): Issue #280: FIX remove profile icon offline +[33mfa46ddd[m HEAD@{27}: rebase (pick): FIX Correction of the random color vector and other details, plus removal of statistics +[33me5f98f1[m HEAD@{28}: rebase (pick): Issue #282: FIX profile edition on HC +[33m9d10585[m[33m ([m[1;31morigin/issue/271.3-update-routes-new-backend[m[33m, [m[1;32missue/271.3-update-routes-new-backend[m[33m)[m HEAD@{29}: rebase (start): checkout issue/271.3-update-routes-new-backend +[33m1f909f1[m[33m ([m[1;31morigin/issue/271.1-create-new-backend-routes-connection[m[33m)[m HEAD@{30}: checkout: moving from issue/271.3-update-routes-new-backend to issue/271.1-create-new-backend-routes-connection +[33m9d10585[m[33m ([m[1;31morigin/issue/271.3-update-routes-new-backend[m[33m, [m[1;32missue/271.3-update-routes-new-backend[m[33m)[m HEAD@{31}: checkout: moving from issue/271.1-create-new-backend-routes-connection to issue/271.3-update-routes-new-backend +[33m1f909f1[m[33m ([m[1;31morigin/issue/271.1-create-new-backend-routes-connection[m[33m)[m HEAD@{32}: rebase (continue) (finish): returning to refs/heads/issue/271.1-create-new-backend-routes-connection +[33m1f909f1[m[33m ([m[1;31morigin/issue/271.1-create-new-backend-routes-connection[m[33m)[m HEAD@{33}: rebase (continue): rebase +[33mf8f0b33[m HEAD@{34}: rebase (continue) (pick): ADD persistent login +[33ma5ec1e3[m HEAD@{35}: rebase (continue): rebase +[33m4d8dd6c[m HEAD@{36}: rebase (pick): ok +[33mfca864c[m HEAD@{37}: rebase (pick): ADD zustand and new backend login +[33mb4f38f6[m[33m ([m[1;32mdevelop[m[33m)[m HEAD@{38}: rebase (start): checkout develop +[33m70c1272[m HEAD@{39}: checkout: moving from develop to issue/271.1-create-new-backend-routes-connection +[33mb4f38f6[m[33m ([m[1;32mdevelop[m[33m)[m HEAD@{40}: pull (finish): returning to refs/heads/develop +[33mb4f38f6[m[33m ([m[1;32mdevelop[m[33m)[m HEAD@{41}: pull (pick): ok +[33mf2ca3ec[m HEAD@{42}: pull (start): checkout f2ca3ec0437aca4415077207441905f7ad0ea0ff +[33m1e76287[m HEAD@{43}: checkout: moving from issue/271.1-create-new-backend-routes-connection to develop +[33m70c1272[m HEAD@{44}: pull (finish): returning to refs/heads/issue/271.1-create-new-backend-routes-connection +[33m70c1272[m HEAD@{45}: pull (pick): rebase +[33m13fde09[m HEAD@{46}: pull (pick): ADD persistent login +[33m47b021e[m HEAD@{47}: pull (start): checkout 47b021ee3e0538d8f8015c7b7a05ebfb761396ae +[33m8b6eff8[m HEAD@{48}: commit: rebase +[33mea6b9e7[m HEAD@{49}: rebase (finish): returning to refs/heads/issue/271.1-create-new-backend-routes-connection +[33mea6b9e7[m HEAD@{50}: rebase (pick): rebase +[33m021900e[m HEAD@{51}: rebase (pick): ok +[33m9d10585[m[33m ([m[1;31morigin/issue/271.3-update-routes-new-backend[m[33m, [m[1;32missue/271.3-update-routes-new-backend[m[33m)[m HEAD@{52}: rebase (start): checkout issue/271.3-update-routes-new-backend +[33m47b021e[m HEAD@{53}: checkout: moving from issue/271.3-update-routes-new-backend to issue/271.1-create-new-backend-routes-connection +[33m9d10585[m[33m ([m[1;31morigin/issue/271.3-update-routes-new-backend[m[33m, [m[1;32missue/271.3-update-routes-new-backend[m[33m)[m HEAD@{54}: pull: Fast-forward +[33md6ffb7b[m HEAD@{55}: checkout: moving from issue/271.1-create-new-backend-routes-connection to issue/271.3-update-routes-new-backend +[33m47b021e[m HEAD@{56}: commit: rebase +[33mc682d43[m HEAD@{57}: rebase (finish): returning to refs/heads/issue/271.1-create-new-backend-routes-connection +[33mc682d43[m HEAD@{58}: rebase (fixup): ok +[33m826a265[m HEAD@{59}: rebase (fixup): # This is a combination of 2 commits. +[33m411e37c[m HEAD@{60}: rebase (pick): ok +[33md6ffb7b[m HEAD@{61}: rebase (start): checkout issue/271.3-update-routes-new-backend +[33m05a1946[m HEAD@{62}: checkout: moving from issue/271.3-update-routes-new-backend to issue/271.1-create-new-backend-routes-connection +[33md6ffb7b[m HEAD@{63}: checkout: moving from issue/271.1-create-new-backend-routes-connection to issue/271.3-update-routes-new-backend +[33m05a1946[m HEAD@{64}: commit: ok +[33mdcfed71[m HEAD@{65}: rebase (finish): returning to refs/heads/issue/271.1-create-new-backend-routes-connection +[33mdcfed71[m HEAD@{66}: rebase (pick): routes-created-and-fixed +[33m1e76287[m HEAD@{67}: rebase (start): checkout develop +[33mb7fc31a[m HEAD@{68}: checkout: moving from develop to issue/271.1-create-new-backend-routes-connection +[33m1e76287[m HEAD@{69}: pull (finish): returning to refs/heads/develop +[33m1e76287[m HEAD@{70}: pull (pick): ok +[33m8823613[m HEAD@{71}: pull (start): checkout 882361329901314da9a514860097eec5c34fdcc7 +[33m4a496bd[m HEAD@{72}: checkout: moving from issue/271.1-create-new-backend-routes-connection to develop +[33mb7fc31a[m HEAD@{73}: commit: routes-created-and-fixed +[33m4a496bd[m HEAD@{74}: Branch: renamed refs/heads/issue/271.1-create-new-backend-routes-conection to refs/heads/issue/271.1-create-new-backend-routes-connection +[33m4a496bd[m HEAD@{76}: Branch: renamed refs/heads/issue/271.1-create-new-backend-routes-coneciton to refs/heads/issue/271.1-create-new-backend-routes-conection +[33m4a496bd[m HEAD@{78}: Branch: renamed refs/heads/issue/271.1-update-collection-routes to refs/heads/issue/271.1-create-new-backend-routes-coneciton +[33m4a496bd[m HEAD@{80}: Branch: renamed refs/heads/Issue/271.1 to refs/heads/issue/271.1-update-collection-routes +[33m4a496bd[m HEAD@{82}: checkout: moving from develop to Issue/271.1 +[33m4a496bd[m HEAD@{83}: rebase (continue) (finish): returning to refs/heads/develop +[33m4a496bd[m HEAD@{84}: rebase (continue): ok +[33mffa3940[m HEAD@{85}: pull (start): checkout ffa39400246a243d9f43f8d9071e4037b75e48af +[33m7d9f13f[m HEAD@{86}: rebase (continue) (finish): returning to refs/heads/develop +[33m7d9f13f[m HEAD@{87}: rebase (continue) (finish): refs/heads/develop onto ffa39400246a243d9f43f8d9071e4037b75e48af +[33m7d9f13f[m HEAD@{88}: checkout: moving from ffa39400246a243d9f43f8d9071e4037b75e48af to develop +[33mffa3940[m HEAD@{89}: pull (start): checkout ffa39400246a243d9f43f8d9071e4037b75e48af +[33m7d9f13f[m HEAD@{90}: checkout: moving from develop to develop +[33m7d9f13f[m HEAD@{91}: checkout: moving from arrumar to develop +[33meec953e[m[33m ([m[1;31morigin/arrumar[m[33m, [m[1;32marrumar[m[33m)[m HEAD@{92}: rebase (finish): returning to refs/heads/arrumar +[33meec953e[m[33m ([m[1;31morigin/arrumar[m[33m, [m[1;32marrumar[m[33m)[m HEAD@{93}: rebase (reword): Alteração feita +[33m591a2f3[m HEAD@{94}: rebase: fast-forward +[33m7d9f13f[m HEAD@{95}: rebase (start): checkout develop +[33m591a2f3[m HEAD@{96}: checkout: moving from develop to arrumar +[33m7d9f13f[m HEAD@{97}: checkout: moving from arrumar to develop +[33m591a2f3[m HEAD@{98}: commit: ok +[33m7d9f13f[m HEAD@{99}: checkout: moving from develop to arrumar +[33m7d9f13f[m HEAD@{100}: commit: ok +[33mb2ca474[m HEAD@{101}: pull: Fast-forward +[33mba98771[m HEAD@{102}: checkout: moving from issue/250-change-about-page to develop +[33m5c1abb3[m[33m ([m[1;31morigin/issue/250-change-about-page[m[33m, [m[1;32missue/250-change-about-page[m[33m)[m HEAD@{103}: rebase (finish): returning to refs/heads/issue/250-change-about-page +[33m5c1abb3[m[33m ([m[1;31morigin/issue/250-change-about-page[m[33m, [m[1;32missue/250-change-about-page[m[33m)[m HEAD@{104}: rebase (fixup): Issue #250/FIX-About-page +[33m0a72404[m HEAD@{105}: rebase (fixup): # This is a combination of 4 commits. +[33m51f2869[m HEAD@{106}: rebase (fixup): # This is a combination of 3 commits. +[33m09f1e1e[m HEAD@{107}: rebase (fixup): # This is a combination of 2 commits. +[33mbca4771[m HEAD@{108}: rebase (reword): Issue #250/FIX-About-page +[33mbc34395[m HEAD@{109}: rebase (reword): Issue #245/Credits-screen +[33mba98771[m HEAD@{110}: rebase (start): checkout develop +[33macaa2cf[m HEAD@{111}: checkout: moving from develop to issue/250-change-about-page +[33mba98771[m HEAD@{112}: checkout: moving from issue/250-change-about-page to develop +[33macaa2cf[m HEAD@{113}: commit: Done +[33m21d386b[m HEAD@{114}: checkout: moving from develop to issue/250-change-about-page +[33mba98771[m HEAD@{115}: checkout: moving from issue-247/update-header-text to develop +[33m9a5c0bd[m[33m ([m[1;31morigin/issue-247/update-header-text[m[33m, [m[1;32missue-247/update-header-text[m[33m)[m HEAD@{116}: rebase (finish): returning to refs/heads/issue-247/update-header-text +[33m9a5c0bd[m[33m ([m[1;31morigin/issue-247/update-header-text[m[33m, [m[1;32missue-247/update-header-text[m[33m)[m HEAD@{117}: rebase (pick): Issue #247: CHANGED header in mobile version +[33m5dfb808[m HEAD@{118}: rebase (pick): Issue #248: ADD Stats gamification +[33m7469b4e[m HEAD@{119}: rebase (pick): Issue #245/Credits-screen +[33mba98771[m HEAD@{120}: rebase (start): checkout develop +[33m2d4a62a[m HEAD@{121}: checkout: moving from develop to issue-247/update-header-text +[33mba98771[m HEAD@{122}: checkout: moving from fix to develop +[33m61220db[m[33m ([m[1;31morigin/fix[m[33m, [m[1;32mfix[m[33m)[m HEAD@{123}: rebase (finish): returning to refs/heads/fix +[33m61220db[m[33m ([m[1;31morigin/fix[m[33m, [m[1;32mfix[m[33m)[m HEAD@{124}: rebase (fixup): Issue #245/Credits-screen +[33m2091574[m HEAD@{125}: rebase (fixup): # This is a combination of 3 commits. +[33m2cc544c[m HEAD@{126}: rebase (fixup): # This is a combination of 2 commits. +[33m6837f38[m HEAD@{127}: rebase (pick): Issue #245/Credits-screen +[33mba98771[m HEAD@{128}: rebase (start): checkout develop +[33mf0702ca[m HEAD@{129}: rebase (abort): updating HEAD +[33m16d357c[m HEAD@{130}: rebase (pick): Issue #247: CHANGED header in mobile version +[33mc33ddee[m HEAD@{131}: rebase (pick): Issue #248: ADD Stats gamification +[33m500f180[m HEAD@{132}: rebase (pick): Issue #245/Credits-screen +[33mba98771[m HEAD@{133}: rebase (start): checkout develop +[33mf0702ca[m HEAD@{134}: checkout: moving from develop to fix +[33mba98771[m HEAD@{135}: pull (finish): returning to refs/heads/develop +[33mba98771[m HEAD@{136}: pull (start): checkout ba98771b62ede2cef14224f8bfb5a63f4d01d88b +[33m5d4bb5c[m HEAD@{137}: checkout: moving from fix to develop +[33mf0702ca[m HEAD@{138}: commit: HOTFIX: Commit history on dev + api ref +[33m5d4bb5c[m HEAD@{139}: checkout: moving from develop to fix +[33m5d4bb5c[m HEAD@{140}: checkout: moving from issue/250-change-about-page to develop +[33m21d386b[m HEAD@{141}: checkout: moving from develop to issue/250-change-about-page +[33m5d4bb5c[m HEAD@{142}: checkout: moving from issue/250-change-about-page to develop +[33m21d386b[m HEAD@{143}: commit: Issue #250: FIX About page +[33m5d4bb5c[m HEAD@{144}: checkout: moving from develop to issue/250-change-about-page +[33m5d4bb5c[m HEAD@{145}: checkout: moving from issue/250-change-about-page to develop +[33m5d4bb5c[m HEAD@{146}: checkout: moving from develop to issue/250-change-about-page +[33m5d4bb5c[m HEAD@{147}: pull: Fast-forward +[33mcfb4aab[m HEAD@{148}: checkout: moving from issue-247/update-header-text to develop +[33m2d4a62a[m HEAD@{149}: rebase (finish): returning to refs/heads/issue-247/update-header-text +[33m2d4a62a[m HEAD@{150}: rebase (fixup): Issue #247: CHANGED header in mobile version +[33m6391f47[m HEAD@{151}: rebase (pick): Issue #247: CHANGED header in mobile version +[33mcfb4aab[m HEAD@{152}: rebase (start): checkout develop +[33m1085e0e[m HEAD@{153}: checkout: moving from develop to issue-247/update-header-text +[33mcfb4aab[m HEAD@{154}: pull: Fast-forward +[33m131951b[m HEAD@{155}: checkout: moving from issue-247/update-header-text to develop +[33m1085e0e[m HEAD@{156}: commit: done +[33mb2d65e7[m HEAD@{157}: rebase (continue) (finish): returning to refs/heads/issue-247/update-header-text +[33mb2d65e7[m HEAD@{158}: rebase (continue) (fixup): Issue #247: CHANGED header in mobile version +[33me284390[m HEAD@{159}: rebase (continue): Issue #247: CHANGED header in mobile version +[33m131951b[m HEAD@{160}: rebase (start): checkout develop +[33m37fd1d3[m HEAD@{161}: checkout: moving from develop to issue-247/update-header-text +[33m131951b[m HEAD@{162}: pull: Fast-forward +[33m9170068[m HEAD@{163}: checkout: moving from issue-247/update-header-text to develop +[33m37fd1d3[m HEAD@{164}: checkout: moving from develop to issue-247/update-header-text +[33m9170068[m HEAD@{165}: checkout: moving from issue/245-credits-screen to develop +[33m427ebc3[m[33m ([m[1;31morigin/issue/245-credits-screen[m[33m, [m[1;32missue/245-credits-screen[m[33m)[m HEAD@{166}: rebase (finish): returning to refs/heads/issue/245-credits-screen +[33m427ebc3[m[33m ([m[1;31morigin/issue/245-credits-screen[m[33m, [m[1;32missue/245-credits-screen[m[33m)[m HEAD@{167}: rebase (fixup): Issue #245/Credits-screen +[33m3a5125b[m HEAD@{168}: rebase (fixup): # This is a combination of 2 commits. +[33m3610a07[m HEAD@{169}: rebase (reword): Issue #245/Credits-screen +[33m6b5d22e[m HEAD@{170}: rebase (reword): para nao perder +[33m9170068[m HEAD@{171}: rebase (start): checkout develop +[33m0e2d735[m HEAD@{172}: checkout: moving from develop to issue/245-credits-screen +[33m9170068[m HEAD@{173}: pull: Fast-forward +[33mb204e06[m HEAD@{174}: checkout: moving from issue/245-credits-screen to develop +[33m0e2d735[m HEAD@{175}: commit: done +[33m6eb0220[m HEAD@{176}: commit: responsive ok +[33m41c0687[m HEAD@{177}: commit: para nao perder +[33mb204e06[m HEAD@{178}: checkout: moving from develop to issue/245-credits-screen +[33mb204e06[m HEAD@{179}: pull: Fast-forward +[33m176ac2d[m HEAD@{180}: checkout: moving from issue/239-cards-divorce to develop +[33m96f81ab[m[33m ([m[1;31morigin/issue/239-cards-divorce[m[33m, [m[1;32missue/239-cards-divorce[m[33m)[m HEAD@{181}: rebase (finish): returning to refs/heads/issue/239-cards-divorce +[33m96f81ab[m[33m ([m[1;31morigin/issue/239-cards-divorce[m[33m, [m[1;32missue/239-cards-divorce[m[33m)[m HEAD@{182}: rebase (fixup): preciso rebasear +[33m5505157[m HEAD@{183}: rebase (start): checkout develop +[33mcf0671f[m HEAD@{184}: checkout: moving from develop to issue/239-cards-divorce +[33m176ac2d[m HEAD@{185}: checkout: moving from issue/239-cards-divorce to develop +[33mcf0671f[m HEAD@{186}: rebase (continue) (finish): returning to refs/heads/issue/239-cards-divorce +[33mcf0671f[m HEAD@{187}: rebase (continue): rebase +[33m5505157[m HEAD@{188}: rebase (continue): preciso rebasear +[33m176ac2d[m HEAD@{189}: rebase (start): checkout develop +[33meb4aee5[m HEAD@{190}: checkout: moving from develop to issue/239-cards-divorce +[33m176ac2d[m HEAD@{191}: pull: Fast-forward +[33m3b90816[m HEAD@{192}: checkout: moving from issue/239-cards-divorce to develop +[33meb4aee5[m HEAD@{193}: reset: moving to HEAD +[33meb4aee5[m HEAD@{194}: rebase (finish): returning to refs/heads/issue/239-cards-divorce +[33meb4aee5[m HEAD@{195}: rebase (start): checkout develop +[33meb4aee5[m HEAD@{196}: checkout: moving from develop to issue/239-cards-divorce +[33m3b90816[m HEAD@{197}: checkout: moving from issue/239-cards-divorce to develop +[33meb4aee5[m HEAD@{198}: commit: rebase +[33m464536b[m HEAD@{199}: rebase (continue) (finish): returning to refs/heads/issue/239-cards-divorce +[33m464536b[m HEAD@{200}: rebase (continue): preciso rebasear +[33m3b90816[m HEAD@{201}: rebase (start): checkout develop +[33m92b94ba[m HEAD@{202}: checkout: moving from develop to issue/239-cards-divorce +[33m3b90816[m HEAD@{203}: pull: Fast-forward +[33mc7dcecf[m HEAD@{204}: checkout: moving from issue/239-cards-divorce to develop +[33m92b94ba[m HEAD@{205}: commit: preciso rebasear +[33mc7dcecf[m HEAD@{206}: checkout: moving from develop to issue/239-cards-divorce +[33mc7dcecf[m HEAD@{207}: checkout: moving from issue/239-cards-divorce to develop +[33mc7dcecf[m HEAD@{208}: checkout: moving from develop to issue/239-cards-divorce +[33mc7dcecf[m HEAD@{209}: pull: Fast-forward +[33m1704eb1[m HEAD@{210}: checkout: moving from issue/225-aligment to develop +[33m7d799a2[m[33m ([m[1;31morigin/issue/225-aligment[m[33m, [m[1;32missue/225-aligment[m[33m)[m HEAD@{211}: rebase (finish): returning to refs/heads/issue/225-aligment +[33m7d799a2[m[33m ([m[1;31morigin/issue/225-aligment[m[33m, [m[1;32missue/225-aligment[m[33m)[m HEAD@{212}: rebase (reword): Issue #225/aligment +[33m2001295[m HEAD@{213}: rebase (reword): ok +[33m1704eb1[m HEAD@{214}: rebase (start): checkout develop +[33me61f0b8[m HEAD@{215}: checkout: moving from develop to issue/225-aligment +[33m1704eb1[m HEAD@{216}: pull: Fast-forward +[33m334adae[m HEAD@{217}: checkout: moving from issue/225-aligment to develop +[33me61f0b8[m HEAD@{218}: commit: ok +[33m334adae[m HEAD@{219}: checkout: moving from develop to issue/225-aligment +[33m334adae[m HEAD@{220}: checkout: moving from issue/225-alignment to develop +[33mbb96091[m[33m ([m[1;31morigin/issue/225-alignment[m[33m, [m[1;32missue/225-alignment[m[33m)[m HEAD@{221}: checkout: moving from develop to issue/225-alignment +[33m334adae[m HEAD@{222}: pull: Fast-forward +[33m02a4569[m HEAD@{223}: checkout: moving from issue/225-alignment to develop +[33mbb96091[m[33m ([m[1;31morigin/issue/225-alignment[m[33m, [m[1;32missue/225-alignment[m[33m)[m HEAD@{224}: rebase (finish): returning to refs/heads/issue/225-alignment +[33mbb96091[m[33m ([m[1;31morigin/issue/225-alignment[m[33m, [m[1;32missue/225-alignment[m[33m)[m HEAD@{225}: rebase (reword): Issue #225/Aligment +[33m6731cdc[m HEAD@{226}: rebase (reword): Feito +[33m02a4569[m HEAD@{227}: rebase (start): checkout develop +[33m988d099[m HEAD@{228}: checkout: moving from develop to issue/225-alignment +[33m02a4569[m HEAD@{229}: pull: Fast-forward +[33m26949de[m HEAD@{230}: checkout: moving from issue/225-alignment to develop +[33m988d099[m HEAD@{231}: commit: Feito +[33m1f3ba1c[m HEAD@{232}: rebase (finish): returning to refs/heads/issue/225-alignment +[33m1f3ba1c[m HEAD@{233}: rebase (fixup): Issue #225-Aligment +[33mbd0ce61[m HEAD@{234}: rebase (fixup): # This is a combination of 3 commits. +[33m54f9fcc[m HEAD@{235}: rebase (fixup): # This is a combination of 2 commits. +[33m9406554[m HEAD@{236}: rebase (reword): Issue #225-Aligment +[33m94bbc4d[m HEAD@{237}: rebase (reword): Mesclando +[33m26949de[m HEAD@{238}: rebase (start): checkout develop +[33meaeb503[m HEAD@{239}: checkout: moving from develop to issue/225-alignment +[33m26949de[m HEAD@{240}: checkout: moving from issue/225-alignment to develop +[33meaeb503[m HEAD@{241}: commit: finished +[33ma330880[m HEAD@{242}: pull (finish): returning to refs/heads/issue/225-alignment +[33ma330880[m HEAD@{243}: pull (start): checkout a330880eb58b3458db220419dd56cff7060e3c19 +[33mf75d033[m HEAD@{244}: checkout: moving from develop to issue/225-alignment +[33m26949de[m HEAD@{245}: pull: Fast-forward +[33m499d26b[m[33m ([m[1;32missue/224-hotfix-resources[m[33m)[m HEAD@{246}: reset: moving to HEAD +[33m499d26b[m[33m ([m[1;32missue/224-hotfix-resources[m[33m)[m HEAD@{247}: checkout: moving from issue/224-hotfix-resources to develop +[33m499d26b[m[33m ([m[1;32missue/224-hotfix-resources[m[33m)[m HEAD@{248}: checkout: moving from develop to issue/224-hotfix-resources +[33m499d26b[m[33m ([m[1;32missue/224-hotfix-resources[m[33m)[m HEAD@{249}: checkout: moving from HOTFIX-button to develop +[33m7a641e9[m[33m ([m[1;31morigin/HOTFIX-button[m[33m, [m[1;32mHOTFIX-button[m[33m)[m HEAD@{250}: rebase (finish): returning to refs/heads/HOTFIX-button +[33m7a641e9[m[33m ([m[1;31morigin/HOTFIX-button[m[33m, [m[1;32mHOTFIX-button[m[33m)[m HEAD@{251}: rebase (reword): Issue #223/ HOTFIX-button +[33m0f9a5c3[m HEAD@{252}: rebase: fast-forward +[33m499d26b[m[33m ([m[1;32missue/224-hotfix-resources[m[33m)[m HEAD@{253}: rebase (start): checkout develop +[33m0f9a5c3[m HEAD@{254}: checkout: moving from develop to HOTFIX-button +[33m499d26b[m[33m ([m[1;32missue/224-hotfix-resources[m[33m)[m HEAD@{255}: checkout: moving from HOTFIX-button to develop +[33m0f9a5c3[m HEAD@{256}: commit: button-fixed +[33m499d26b[m[33m ([m[1;32missue/224-hotfix-resources[m[33m)[m HEAD@{257}: checkout: moving from develop to HOTFIX-button +[33m499d26b[m[33m ([m[1;32missue/224-hotfix-resources[m[33m)[m HEAD@{258}: pull: Fast-forward +[33m62ba0a5[m HEAD@{259}: checkout: moving from issue/225-alignment to develop +[33mf75d033[m HEAD@{260}: commit: ajuda +[33mcd4b0cb[m HEAD@{261}: commit: contato-page +[33m4447d1c[m HEAD@{262}: commit: publicar-page +[33mb983ba5[m HEAD@{263}: commit: sobre-page +[33md0f1447[m HEAD@{264}: checkout: moving from develop to issue/225-alignment +[33m62ba0a5[m HEAD@{265}: pull: Fast-forward +[33m90a6865[m HEAD@{266}: checkout: moving from issue/207-HOTFIX-complaint-tag to develop +[33m6edfdd7[m[33m ([m[1;31morigin/issue/207-HOTFIX-complaint-tag[m[33m, [m[1;32missue/207-HOTFIX-complaint-tag[m[33m)[m HEAD@{267}: rebase (finish): returning to refs/heads/issue/207-HOTFIX-complaint-tag +[33m6edfdd7[m[33m ([m[1;31morigin/issue/207-HOTFIX-complaint-tag[m[33m, [m[1;32missue/207-HOTFIX-complaint-tag[m[33m)[m HEAD@{268}: rebase (fixup): Issue #207/Complaints-homologation-page +[33m1bad2b0[m HEAD@{269}: rebase (fixup): # This is a combination of 2 commits. +[33mac0310b[m HEAD@{270}: rebase (start): checkout develop +[33m74e8f57[m HEAD@{271}: commit: done +[33m7880bde[m HEAD@{272}: checkout: moving from develop to issue/207-HOTFIX-complaint-tag +[33m90a6865[m HEAD@{273}: checkout: moving from issue/207-HOTFIX-complaint-tag to develop +[33m7880bde[m HEAD@{274}: commit: ok +[33mac0310b[m HEAD@{275}: rebase (continue) (finish): returning to refs/heads/issue/207-HOTFIX-complaint-tag +[33mac0310b[m HEAD@{276}: rebase (continue): Issue #207/Complaints-homologation-page +[33m90a6865[m HEAD@{277}: rebase (start): checkout develop +[33m2ec770c[m HEAD@{278}: checkout: moving from develop to issue/207-HOTFIX-complaint-tag +[33m90a6865[m HEAD@{279}: pull: Fast-forward +[33m82504e2[m HEAD@{280}: checkout: moving from issue/207-HOTFIX-complaint-tag to develop +[33m2ec770c[m HEAD@{281}: commit: ok +[33m82504e2[m HEAD@{282}: checkout: moving from develop to issue/207-HOTFIX-complaint-tag +[33m82504e2[m HEAD@{283}: pull: Fast-forward +[33m8171780[m HEAD@{284}: checkout: moving from issue/176-HOTFIX-resource-tag to develop +[33m1a29408[m[33m ([m[1;31morigin/issue/176-HOTFIX-resource-tag[m[33m, [m[1;32missue/176-HOTFIX-resource-tag[m[33m)[m HEAD@{285}: rebase (continue) (finish): returning to refs/heads/issue/176-HOTFIX-resource-tag +[33m1a29408[m[33m ([m[1;31morigin/issue/176-HOTFIX-resource-tag[m[33m, [m[1;32missue/176-HOTFIX-resource-tag[m[33m)[m HEAD@{286}: rebase (continue): ai +[33m8171780[m HEAD@{287}: rebase (start): checkout develop +[33m6bcba4e[m HEAD@{288}: checkout: moving from develop to issue/176-HOTFIX-resource-tag +[33m8171780[m HEAD@{289}: pull: Fast-forward +[33m5c37def[m HEAD@{290}: checkout: moving from issue/176-HOTFIX-resource-tag to develop +[33m6bcba4e[m HEAD@{291}: commit: ai +[33m5c37def[m HEAD@{292}: checkout: moving from develop to issue/176-HOTFIX-resource-tag +[33m5c37def[m HEAD@{293}: checkout: moving from issue/175-HOTFIX to develop +[33m34cf5fb[m[33m ([m[1;31morigin/issue/175-HOTFIX[m[33m, [m[1;32missue/175-HOTFIX[m[33m)[m HEAD@{294}: rebase (finish): returning to refs/heads/issue/175-HOTFIX +[33m34cf5fb[m[33m ([m[1;31morigin/issue/175-HOTFIX[m[33m, [m[1;32missue/175-HOTFIX[m[33m)[m HEAD@{295}: rebase (reword): Issue #175/HOTFIX +[33mcda84b7[m HEAD@{296}: rebase (reword): done +[33m5c37def[m HEAD@{297}: rebase (start): checkout develop +[33m456859e[m HEAD@{298}: checkout: moving from develop to issue/175-HOTFIX +[33m5c37def[m HEAD@{299}: pull: Fast-forward +[33m3a58570[m HEAD@{300}: checkout: moving from issue/175-HOTFIX to develop +[33m456859e[m HEAD@{301}: commit: done +[33m3a58570[m HEAD@{302}: checkout: moving from develop to issue/175-HOTFIX +[33m3a58570[m HEAD@{303}: checkout: moving from issues/200/190-HOTFIX to develop +[33m61d06b0[m[33m ([m[1;31morigin/issues/200/190-HOTFIX[m[33m, [m[1;32missues/200/190-HOTFIX[m[33m)[m HEAD@{304}: rebase (finish): returning to refs/heads/issues/200/190-HOTFIX +[33m61d06b0[m[33m ([m[1;31morigin/issues/200/190-HOTFIX[m[33m, [m[1;32missues/200/190-HOTFIX[m[33m)[m HEAD@{305}: rebase (pick): Issue #190/#200-HOTFIX +[33m3a58570[m HEAD@{306}: rebase (start): checkout develop +[33m7499204[m HEAD@{307}: checkout: moving from develop to issues/200/190-HOTFIX +[33m3a58570[m HEAD@{308}: pull: Fast-forward +[33m2136eb2[m HEAD@{309}: checkout: moving from issues/200/190-HOTFIX to develop +[33m7499204[m HEAD@{310}: rebase (finish): returning to refs/heads/issues/200/190-HOTFIX +[33m7499204[m HEAD@{311}: rebase (reword): Issue #190/#200-HOTFIX +[33m14073c5[m HEAD@{312}: rebase (reword): done +[33m2136eb2[m HEAD@{313}: rebase (start): checkout develop +[33mbef8e1e[m HEAD@{314}: checkout: moving from develop to issues/200/190-HOTFIX +[33m2136eb2[m HEAD@{315}: pull: Fast-forward +[33m4fa1ef5[m HEAD@{316}: checkout: moving from issues/200/190-HOTFIX to develop +[33mbef8e1e[m HEAD@{317}: commit: done +[33m4fa1ef5[m HEAD@{318}: rebase (finish): returning to refs/heads/issues/200/190-HOTFIX +[33m4fa1ef5[m HEAD@{319}: rebase (start): checkout develop +[33md63b0d0[m HEAD@{320}: reset: moving to HEAD +[33md63b0d0[m HEAD@{321}: checkout: moving from develop to issues/200/190-HOTFIX +[33m4fa1ef5[m HEAD@{322}: pull: Fast-forward +[33md63b0d0[m HEAD@{323}: checkout: moving from issues/200/190-HOTFIX to develop +[33md63b0d0[m HEAD@{324}: checkout: moving from develop to issues/200/190-HOTFIX +[33md63b0d0[m HEAD@{325}: checkout: moving from issue/193/194-HOTFIX to develop +[33md7dbfc0[m[33m ([m[1;31morigin/issue/193/194-HOTFIX[m[33m, [m[1;32missue/193/194-HOTFIX[m[33m)[m HEAD@{326}: rebase (finish): returning to refs/heads/issue/193/194-HOTFIX +[33md7dbfc0[m[33m ([m[1;31morigin/issue/193/194-HOTFIX[m[33m, [m[1;32missue/193/194-HOTFIX[m[33m)[m HEAD@{327}: rebase (reword): Issue #193#104-HOTFIX +[33m335aeac[m HEAD@{328}: rebase (reword): done +[33md63b0d0[m HEAD@{329}: rebase (start): checkout develop +[33m9d04c2d[m HEAD@{330}: checkout: moving from develop to issue/193/194-HOTFIX +[33md63b0d0[m HEAD@{331}: pull: Fast-forward +[33m32299fc[m HEAD@{332}: checkout: moving from issue/193/194-HOTFIX to develop +[33m9d04c2d[m HEAD@{333}: commit: done +[33mf8e4018[m[33m ([m[1;31morigin/issue/203/198/HOTFIX[m[33m, [m[1;32missue/203/198/HOTFIX[m[33m)[m HEAD@{334}: checkout: moving from issue/203/198/HOTFIX to issue/193/194-HOTFIX +[33mf8e4018[m[33m ([m[1;31morigin/issue/203/198/HOTFIX[m[33m, [m[1;32missue/203/198/HOTFIX[m[33m)[m HEAD@{335}: rebase (finish): returning to refs/heads/issue/203/198/HOTFIX +[33mf8e4018[m[33m ([m[1;31morigin/issue/203/198/HOTFIX[m[33m, [m[1;32missue/203/198/HOTFIX[m[33m)[m HEAD@{336}: rebase (reword): Issue #198#203/HOTFIX +[33md9a1b37[m HEAD@{337}: rebase (reword): done +[33m32299fc[m HEAD@{338}: rebase (start): checkout develop +[33ma166174[m HEAD@{339}: checkout: moving from develop to issue/203/198/HOTFIX +[33m32299fc[m HEAD@{340}: pull: Fast-forward +[33m61308b7[m HEAD@{341}: checkout: moving from issue/203/198/HOTFIX to develop +[33ma166174[m HEAD@{342}: commit: done +[33m61308b7[m HEAD@{343}: checkout: moving from develop to issue/203/198/HOTFIX +[33m61308b7[m HEAD@{344}: pull: Fast-forward +[33mae927a6[m HEAD@{345}: checkout: moving from issue/196-HOTFIX-collection-modal to develop +[33m63abe42[m[33m ([m[1;31morigin/issue/196-HOTFIX-collection-modal[m[33m, [m[1;32missue/196-HOTFIX-collection-modal[m[33m)[m HEAD@{346}: rebase (finish): returning to refs/heads/issue/196-HOTFIX-collection-modal +[33m63abe42[m[33m ([m[1;31morigin/issue/196-HOTFIX-collection-modal[m[33m, [m[1;32missue/196-HOTFIX-collection-modal[m[33m)[m HEAD@{347}: rebase (fixup): Issue #196#198/HOTFIX +[33m86affb9[m HEAD@{348}: rebase (start): checkout develop +[33m1b2ecb6[m HEAD@{349}: commit: done1 +[33m86affb9[m HEAD@{350}: rebase (finish): returning to refs/heads/issue/196-HOTFIX-collection-modal +[33m86affb9[m HEAD@{351}: rebase (fixup): Issue #196#198/HOTFIX +[33m0eb8e89[m HEAD@{352}: rebase (reword): Issue #196#198/HOTFIX +[33m76ba4e1[m HEAD@{353}: rebase (reword): done +[33mae927a6[m HEAD@{354}: rebase (start): checkout develop +[33mbbb59ff[m HEAD@{355}: checkout: moving from develop to issue/196-HOTFIX-collection-modal +[33mae927a6[m HEAD@{356}: pull: Fast-forward +[33m919173f[m HEAD@{357}: checkout: moving from issue/196-HOTFIX-collection-modal to develop +[33mbbb59ff[m HEAD@{358}: commit: done +[33mb2fa5c7[m HEAD@{359}: commit: done +[33m919173f[m HEAD@{360}: checkout: moving from develop to issue/196-HOTFIX-collection-modal +[33m919173f[m HEAD@{361}: checkout: moving from issue/183-HOTFIX-carousel to develop +[33me326144[m[33m ([m[1;31morigin/issue/183-HOTFIX-carousel[m[33m, [m[1;32missue/183-HOTFIX-carousel[m[33m)[m HEAD@{362}: rebase (finish): returning to refs/heads/issue/183-HOTFIX-carousel +[33me326144[m[33m ([m[1;31morigin/issue/183-HOTFIX-carousel[m[33m, [m[1;32missue/183-HOTFIX-carousel[m[33m)[m HEAD@{363}: rebase (pick): Issue #183/HOTFIX-about-page +[33m919173f[m HEAD@{364}: rebase (start): checkout develop +[33m7a91ab3[m HEAD@{365}: checkout: moving from develop to issue/183-HOTFIX-carousel +[33m919173f[m HEAD@{366}: pull: Fast-forward +[33mb27a638[m HEAD@{367}: checkout: moving from issue/183-HOTFIX-carousel to develop +[33m7a91ab3[m HEAD@{368}: rebase (finish): returning to refs/heads/issue/183-HOTFIX-carousel +[33m7a91ab3[m HEAD@{369}: rebase (fixup): Issue #183/HOTFIX-about-page +[33m65ff23c[m HEAD@{370}: rebase (fixup): # This is a combination of 2 commits. +[33m0464120[m HEAD@{371}: rebase (reword): Issue #183/HOTFIX-about-page +[33mbe9c3ad[m HEAD@{372}: rebase: fast-forward +[33mb27a638[m HEAD@{373}: rebase (start): checkout develop +[33mfbb4811[m HEAD@{374}: checkout: moving from develop to issue/183-HOTFIX-carousel +[33mb27a638[m HEAD@{375}: checkout: moving from issue/183-HOTFIX-carousel to develop +[33mfbb4811[m HEAD@{376}: commit: done +[33m59c4800[m HEAD@{377}: commit: done +[33mbe9c3ad[m HEAD@{378}: rebase (finish): returning to refs/heads/issue/183-HOTFIX-carousel +[33mbe9c3ad[m HEAD@{379}: rebase (reword): Issue #183/HOTFIX-carousel +[33m5e246a6[m HEAD@{380}: rebase: fast-forward +[33mb27a638[m HEAD@{381}: rebase (start): checkout develop +[33m5e246a6[m HEAD@{382}: checkout: moving from develop to issue/183-HOTFIX-carousel +[33mb27a638[m HEAD@{383}: checkout: moving from issue/183-HOTFIX-carousel to develop +[33m5e246a6[m HEAD@{384}: commit: done +[33mb27a638[m HEAD@{385}: checkout: moving from develop to issue/183-HOTFIX-carousel +[33mb27a638[m HEAD@{386}: pull: Fast-forward +[33mbb20958[m[33m ([m[1;32missue/169-HOTFIX-mobile-perfil[m[33m)[m HEAD@{387}: checkout: moving from issue/171-HOTFIX-collections-mobile to develop +[33m5da9975[m[33m ([m[1;31morigin/issue/171-HOTFIX-collections-mobile[m[33m, [m[1;32missue/171-HOTFIX-collections-mobile[m[33m)[m HEAD@{388}: commit: done +[33mbb20958[m[33m ([m[1;32missue/169-HOTFIX-mobile-perfil[m[33m)[m HEAD@{389}: checkout: moving from develop to issue/171-HOTFIX-collections-mobile +[33mbb20958[m[33m ([m[1;32missue/169-HOTFIX-mobile-perfil[m[33m)[m HEAD@{390}: checkout: moving from issue/169-HOTFIX-mobile-perfil to develop +[33mbb20958[m[33m ([m[1;32missue/169-HOTFIX-mobile-perfil[m[33m)[m HEAD@{391}: checkout: moving from develop to issue/169-HOTFIX-mobile-perfil +[33mbb20958[m[33m ([m[1;32missue/169-HOTFIX-mobile-perfil[m[33m)[m HEAD@{392}: pull: Fast-forward +[33m8c1d35a[m HEAD@{393}: checkout: moving from issue/166-HOTFIX-delete-collection to develop +[33mb7c531d[m[33m ([m[1;31morigin/issue/166-HOTFIX-delete-collection[m[33m, [m[1;32missue/166-HOTFIX-delete-collection[m[33m)[m HEAD@{394}: rebase (finish): returning to refs/heads/issue/166-HOTFIX-delete-collection +[33mb7c531d[m[33m ([m[1;31morigin/issue/166-HOTFIX-delete-collection[m[33m, [m[1;32missue/166-HOTFIX-delete-collection[m[33m)[m HEAD@{395}: rebase (reword): Issue #166:HOTFIX delete collection +[33m974e9c7[m HEAD@{396}: rebase: fast-forward +[33m8c1d35a[m HEAD@{397}: rebase (start): checkout develop +[33m974e9c7[m HEAD@{398}: checkout: moving from develop to issue/166-HOTFIX-delete-collection +[33m8c1d35a[m HEAD@{399}: checkout: moving from issue/166-HOTFIX-delete-collection to develop +[33m974e9c7[m HEAD@{400}: commit: done +[33m8c1d35a[m HEAD@{401}: rebase (finish): returning to refs/heads/issue/166-HOTFIX-delete-collection +[33m8c1d35a[m HEAD@{402}: rebase (start): checkout develop +[33m711b35d[m[33m ([m[1;31morigin/issue/162-HOTFIX-recurso[m[33m, [m[1;32missue/162-HOTFIX-recurso[m[33m)[m HEAD@{403}: reset: moving to HEAD +[33m711b35d[m[33m ([m[1;31morigin/issue/162-HOTFIX-recurso[m[33m, [m[1;32missue/162-HOTFIX-recurso[m[33m)[m HEAD@{404}: checkout: moving from develop to issue/166-HOTFIX-delete-collection +[33m8c1d35a[m HEAD@{405}: pull: Fast-forward +[33m711482c[m HEAD@{406}: checkout: moving from issue/166-HOTFIX-delete-collection to develop +[33m711b35d[m[33m ([m[1;31morigin/issue/162-HOTFIX-recurso[m[33m, [m[1;32missue/162-HOTFIX-recurso[m[33m)[m HEAD@{407}: checkout: moving from issue/162-HOTFIX-recurso to issue/166-HOTFIX-delete-collection +[33m711b35d[m[33m ([m[1;31morigin/issue/162-HOTFIX-recurso[m[33m, [m[1;32missue/162-HOTFIX-recurso[m[33m)[m HEAD@{408}: rebase (finish): returning to refs/heads/issue/162-HOTFIX-recurso +[33m711b35d[m[33m ([m[1;31morigin/issue/162-HOTFIX-recurso[m[33m, [m[1;32missue/162-HOTFIX-recurso[m[33m)[m HEAD@{409}: rebase (pick): Issue #162: HOTFIX resource +[33m711482c[m HEAD@{410}: rebase (start): checkout develop +[33mb856b1f[m HEAD@{411}: checkout: moving from develop to issue/162-HOTFIX-recurso +[33m711482c[m HEAD@{412}: checkout: moving from issue/162-HOTFIX-recurso to develop +[33mb856b1f[m HEAD@{413}: checkout: moving from develop to issue/162-HOTFIX-recurso +[33m711482c[m HEAD@{414}: pull: Fast-forward +[33m2c17be0[m HEAD@{415}: checkout: moving from develop to develop +[33m2c17be0[m HEAD@{416}: checkout: moving from issue/162-HOTFIX-recurso to develop +[33mb856b1f[m HEAD@{417}: rebase (finish): returning to refs/heads/issue/162-HOTFIX-recurso +[33mb856b1f[m HEAD@{418}: rebase (reword): Issue #162: HOTFIX resource +[33m4ad386b[m HEAD@{419}: rebase (reword): done +[33m2c17be0[m HEAD@{420}: rebase (start): checkout develop +[33m9898a07[m HEAD@{421}: checkout: moving from develop to issue/162-HOTFIX-recurso +[33m2c17be0[m HEAD@{422}: pull: Fast-forward +[33mf4c435e[m HEAD@{423}: checkout: moving from issue/162-HOTFIX-recurso to develop +[33m9898a07[m HEAD@{424}: commit: done +[33mf4c435e[m HEAD@{425}: checkout: moving from develop to issue/162-HOTFIX-recurso +[33mf4c435e[m HEAD@{426}: checkout: moving from issue/165-HOTFIX-home to develop +[33mb327101[m[33m ([m[1;31morigin/issue/165-HOTFIX-home[m[33m, [m[1;32missue/165-HOTFIX-home[m[33m)[m HEAD@{427}: rebase (finish): returning to refs/heads/issue/165-HOTFIX-home +[33mb327101[m[33m ([m[1;31morigin/issue/165-HOTFIX-home[m[33m, [m[1;32missue/165-HOTFIX-home[m[33m)[m HEAD@{428}: rebase (reword): Issue #165:HOTFIX home +[33m0e77362[m HEAD@{429}: rebase (reword): done +[33mf4c435e[m HEAD@{430}: rebase (start): checkout develop +[33m07645b3[m HEAD@{431}: checkout: moving from develop to issue/165-HOTFIX-home +[33mf4c435e[m HEAD@{432}: pull: Fast-forward +[33m58cf2a7[m HEAD@{433}: checkout: moving from issue/165-HOTFIX-home to develop +[33m07645b3[m HEAD@{434}: commit: done +[33m58cf2a7[m HEAD@{435}: checkout: moving from issue-164/Hotfix-colecao to issue/165-HOTFIX-home +[33m2c5f58a[m[33m ([m[1;31morigin/issue-164/Hotfix-colecao[m[33m, [m[1;32missue-164/Hotfix-colecao[m[33m)[m HEAD@{436}: checkout: moving from issue/165-HOTFIX-home to issue-164/Hotfix-colecao +[33m58cf2a7[m HEAD@{437}: checkout: moving from develop to issue/165-HOTFIX-home +[33m58cf2a7[m HEAD@{438}: checkout: moving from issue-164/Hotfix-colecao to develop +[33m2c5f58a[m[33m ([m[1;31morigin/issue-164/Hotfix-colecao[m[33m, [m[1;32missue-164/Hotfix-colecao[m[33m)[m HEAD@{439}: rebase (finish): returning to refs/heads/issue-164/Hotfix-colecao +[33m2c5f58a[m[33m ([m[1;31morigin/issue-164/Hotfix-colecao[m[33m, [m[1;32missue-164/Hotfix-colecao[m[33m)[m HEAD@{440}: rebase (reword): Issue #164/HOTFIX collection +[33me276d83[m HEAD@{441}: rebase (reword): done +[33m58cf2a7[m HEAD@{442}: rebase (start): checkout develop +[33m2a97aaa[m HEAD@{443}: checkout: moving from develop to issue-164/Hotfix-colecao +[33m58cf2a7[m HEAD@{444}: pull: Fast-forward +[33mb06cea0[m HEAD@{445}: checkout: moving from issue-164/Hotfix-colecao to develop +[33m2a97aaa[m HEAD@{446}: commit: done +[33mb06cea0[m HEAD@{447}: checkout: moving from develop to issue-164/Hotfix-colecao +[33mb06cea0[m HEAD@{448}: checkout: moving from issue-164/Hotfix-colecao to develop +[33mb06cea0[m HEAD@{449}: checkout: moving from develop to issue-164/Hotfix-colecao +[33mb06cea0[m HEAD@{450}: pull: Fast-forward +[33mfd5247e[m HEAD@{451}: checkout: moving from issue/158-fix-about-page to develop +[33mad77385[m[33m ([m[1;31morigin/issue/158-fix-about-page[m[33m, [m[1;32missue/158-fix-about-page[m[33m)[m HEAD@{452}: rebase (finish): returning to refs/heads/issue/158-fix-about-page +[33mad77385[m[33m ([m[1;31morigin/issue/158-fix-about-page[m[33m, [m[1;32missue/158-fix-about-page[m[33m)[m HEAD@{453}: rebase (pick): Issue #158/FIX about page +[33mfd5247e[m HEAD@{454}: rebase (start): checkout develop +[33me85b8e4[m HEAD@{455}: checkout: moving from develop to issue/158-fix-about-page +[33mfd5247e[m HEAD@{456}: pull: Fast-forward +[33m0762558[m HEAD@{457}: checkout: moving from issue/158-fix-about-page to develop +[33me85b8e4[m HEAD@{458}: rebase (finish): returning to refs/heads/issue/158-fix-about-page +[33me85b8e4[m HEAD@{459}: rebase (fixup): Issue #158/FIX about page +[33m9a55a4b[m HEAD@{460}: rebase (reword): Issue #158/FIX about page +[33m9eb9070[m HEAD@{461}: rebase: fast-forward +[33m0762558[m HEAD@{462}: rebase (start): checkout develop +[33mb91a62f[m HEAD@{463}: checkout: moving from develop to issue/158-fix-about-page +[33m0762558[m HEAD@{464}: checkout: moving from issue/158-fix-about-page to develop +[33mb91a62f[m HEAD@{465}: commit: fixed +[33m9eb9070[m HEAD@{466}: rebase (finish): returning to refs/heads/issue/158-fix-about-page +[33m9eb9070[m HEAD@{467}: rebase (reword): fixed +[33m55ec9be[m HEAD@{468}: rebase: fast-forward +[33m0762558[m HEAD@{469}: rebase (start): checkout develop +[33m55ec9be[m HEAD@{470}: checkout: moving from develop to issue/158-fix-about-page +[33m0762558[m HEAD@{471}: checkout: moving from issue/158-fix-about-page to develop +[33m55ec9be[m HEAD@{472}: commit: fixed +[33m0762558[m HEAD@{473}: checkout: moving from develop to issue/158-fix-about-page +[33m0762558[m HEAD@{474}: pull: Fast-forward +[33m8c42da0[m HEAD@{475}: pull: Fast-forward +[33mca14f32[m HEAD@{476}: checkout: moving from fix-detail to develop +[33m635ecb2[m[33m ([m[1;31morigin/fix-detail[m[33m, [m[1;32mfix-detail[m[33m)[m HEAD@{477}: rebase (finish): returning to refs/heads/fix-detail +[33m635ecb2[m[33m ([m[1;31morigin/fix-detail[m[33m, [m[1;32mfix-detail[m[33m)[m HEAD@{478}: rebase (reword): Simple change (no issue) +[33m948e1ee[m HEAD@{479}: rebase: fast-forward +[33mca14f32[m HEAD@{480}: rebase (start): checkout develop +[33m948e1ee[m HEAD@{481}: checkout: moving from develop to fix-detail +[33mca14f32[m HEAD@{482}: checkout: moving from fix-detail to develop +[33m948e1ee[m HEAD@{483}: commit: detail fixed +[33mca14f32[m HEAD@{484}: checkout: moving from develop to fix-detail +[33mca14f32[m HEAD@{485}: pull: Fast-forward +[33mc64803f[m HEAD@{486}: checkout: moving from issue/144-about-page-changes to develop +[33m004ea21[m[33m ([m[1;31morigin/issue/144-about-page-changes[m[33m, [m[1;32missue/144-about-page-changes[m[33m)[m HEAD@{487}: checkout: moving from develop to issue/144-about-page-changes +[33mc64803f[m HEAD@{488}: clone: from gitlab.c3sl.ufpr.br:mecred/frontend-mecred.git diff --git a/next.config.mjs b/next.config.mjs index 7fe6a5fa6fffdcfa49fe673b76216ad5f96b3af3..1c3824f5eed1a0c01605f125d68c34d79f1971c0 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -40,6 +40,12 @@ const nextConfig = { port: '443', pathname: '/**', }, + { + protocol: 'https', + hostname: 's3.c3sl.ufpr.br', + port: '', + pathname: '/**', + }, ], }, }; diff --git a/src/app/colecao/[id]/components/collectionItems.js b/src/app/colecao/[id]/components/collectionItems.js index 9cdadf17844f3add2ab6df8bf695601eb9c23434..ba20d57e755983ddc308075a6cb04a931799442d 100644 --- a/src/app/colecao/[id]/components/collectionItems.js +++ b/src/app/colecao/[id]/components/collectionItems.js @@ -1,27 +1,27 @@ import { useMediaQuery } from "@mui/material"; import Cards from "@/app/components/Cards"; -export default function CollectionItems({ collection }) { +export default function CollectionItems({ collection, resources }) { const isSm = useMediaQuery((theme) => theme.breakpoints.down('sm')); return ( <div className="flex flex-col bg-white-HC-dark p-4 rounded-lg"> <div className="text-darkGray-HC-white-underline font-bold text-xl mb-3">Recursos na coleção</div> <div className="flex flex-col gap-3"> - {collection.collection_items.sort((a,b) => a.position - b.position).map((item, index) => { + {resources?.sort((a,b) => a.position - b.position).map((item, index) => { return ( <Cards collectionSource={collection["id"]} horizontal={!isSm} noAvatar={!isSm} - id={item["collectionable"]["id"]} + id={item.id} key={index} - title={item["collectionable"]["name"]} - author={item["collectionable"]["publisher"]["name"]} - avatar={item["collectionable"]["publisher"]["avatar"]} - image={item["collectionable"]["thumbnail"]} - type={item["collectionable"]["object_type"]} - updated_at={item["collectionable"]["updated_at"]} + title={item.name} + author={item.author} + avatar={`https://s3.c3sl.ufpr.br/mecredteste/avatar/${collection.user_id}`} + image={`https://s3.c3sl.ufpr.br/mecredteste/thumbnail/resource/${item.id}`} + type={item.type} + updated_at={item.updated_at} thumbWidth={isSm ? "100%" : "230px"} thumbHeight="auto" width="100%" diff --git a/src/app/colecao/[id]/components/publisherInfoCollection.js b/src/app/colecao/[id]/components/publisherInfoCollection.js index 8c8ac1b2536fc529e57899c5bab2d6e8b87f4dd5..9b5c4c54efca84ed12334e23591c4c814aad1a99 100644 --- a/src/app/colecao/[id]/components/publisherInfoCollection.js +++ b/src/app/colecao/[id]/components/publisherInfoCollection.js @@ -23,7 +23,7 @@ export default function PublisherInfoCollection({ publisher, disabledButton = fa const followHandler = () => { loginBarrier(); mecredApi.put( - `users/${publisher.id}/follow/`, + `public/users/follow/${publisher.id}`, {}, { headers: { diff --git a/src/app/colecao/[id]/page.js b/src/app/colecao/[id]/page.js index 4ef56f1beff4765ed49d768fb1f79a8103dd2e82..c298e0b0c9be2b4e4ab0ae54e13b90f19542a10a 100644 --- a/src/app/colecao/[id]/page.js +++ b/src/app/colecao/[id]/page.js @@ -27,35 +27,27 @@ export default function Colecao({ params }) { useEffect(() => { const fetchData = async () => { try { - let headers = {}; + const collectionResponse = await mecredApi.get(`public/collections/${params.id}`); + const collection = collectionResponse.data; + const resourcesResponse = await mecredApi.get(`public/collections/${params.id}/resources`); + const resources = resourcesResponse.data; + const ownerResponse = await mecredApi.get(`public/userCollections/${params.id}/owner`) + const owner = ownerResponse.data; - if (isLoggedIn()) { - headers = { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, - }; - } - - const response = await mecredApi.get(`collections/${params.id}`); - - setCollection(response.data); + setCollection({ ...collection, resources: resources, owner: owner }); } catch (error) { + console.error("Erro ao buscar dados:", error); setError(true); } }; - fetchData(); - }, [params.id, client, token, uid]); + }, [params.id]); useEffect(() => { // Função para checar o tamanho da tela const checkScreenSize = () => { setIsSmallScreen(window.innerWidth < 1280); }; - checkScreenSize(); // Checa no primeiro render window.addEventListener("resize", checkScreenSize); // Adiciona o listener @@ -78,33 +70,33 @@ export default function Colecao({ params }) { <div className="bg-ice-HC-dark p-3 w-full"> <div className=" flex justify-center"> {/* Pré-visualização */} - <CollectionPreview collection={collection} /> + <CollectionPreview collection={collection.collection} resources={collection?.resources.resources} /> </div> <div> <div> <div className="text-darkGray-HC-white mt-5 text-2xl font-bold"> {/* Título */} - <h1>{collection.name}</h1> + <h1>{collection.collection.name}</h1> </div> <div className="text-darkGray-HC-white text-sm font-bold"> {/* tags */} - <Tags tags={collection.tags} /> + <Tags tags={collection.collection.tags} /> </div> </div> </div> <div className="flex flex-row gap-3 pb-4 pt-4"> - <DownloadButton id={collection.id} objects={collection.collection_items} /> - <ShareButton id={collection.id} type={"colecao"} /> + <DownloadButton id={collection.collection.id} objects={collection?.resources} /> + <ShareButton id={collection.collection.id} type={"colecao"} /> </div> <div> {/* Publicador */} - <PublisherInfoCollection publisher={collection?.owner} /> + <PublisherInfoCollection publisher={collection?.owner[0]} /> </div> </div> </div> <div className="px-[25px] bg-ice-HC-dark"> <div> {/* recommendations */} </div> - <CollectionItems collection={collection} /> + <CollectionItems collection={collection.collection} resources={collection?.resources.resources || []}/> </div> </> )} diff --git a/src/app/components/Cards.js b/src/app/components/Cards.js index 29fec7c0c4b8c95db30f29ca13029ef0991fc01a..8f4ac7e72a60ae143a3318149953933bc0c00e80 100644 --- a/src/app/components/Cards.js +++ b/src/app/components/Cards.js @@ -63,6 +63,7 @@ export default function Cards(props) { return thumbnail_url; }; + /** * * @param {String} updated_time @@ -118,7 +119,6 @@ export default function Cards(props) { component={Link} href={`/recurso/${props["id"]}` + (props.collectionSource ? `?collectionId=${props.collectionSource}` : "")} > - <CardMedia id="conteudo" tabIndex="0" @@ -129,9 +129,9 @@ export default function Cards(props) { }} component="img" image={ - props["image"] === null - ? getDefaultThumbnail(props["type"]) - : mecredURL + props["image"] + props.image === null + ? getDefaultThumbnail(props.type) + : props.image } alt="imagem" title={props.title} @@ -162,7 +162,7 @@ export default function Cards(props) { {props?.noAvatar || !props["avatar"] ? <div className={`flex items-center shrink-0 justify-center text-xl font-bold ml-1 text-ice-HC-dark rounded-full h-[33px] w-[33px] ${getRandomBg(props["id"])}`} >{props["author"][0]}</div> : <img - src={mecredURL + props["avatar"]} + src="https://s3.c3sl.ufpr.br/mecredteste/avatar/1" alt={props["author"]} className="w-[33px] h-[33px] object-cover rounded-full" diff --git a/src/app/components/DownloadButton.js b/src/app/components/DownloadButton.js index c2f4403e239599abc43d48c20e7e8bd56374681d..03d3406f8e7aa9501aed7ad0accf72f0ed8e7fa7 100644 --- a/src/app/components/DownloadButton.js +++ b/src/app/components/DownloadButton.js @@ -1,6 +1,6 @@ import * as React from 'react'; import DownloadOutlinedIcon from '@mui/icons-material/Download'; -import { mecredURL, mecredURLv1 } from '@/axiosConfig'; +import mecredApi, { mecredURL, mecredURLv1 } from '@/axiosConfig'; /** * Responsável pelo Download dos recursos de uma coleção @@ -10,25 +10,34 @@ import { mecredURL, mecredURLv1 } from '@/axiosConfig'; */ export default function DownloadButton({ id, objects }) { - const handleDownloadCollection = (e) => { - e.preventDefault(); - let zip = false; - - alert("Caso esta coleção contenha links externos, eles serão abertos em novas abas.\n Talvez seja preciso permitir a abertura de várias abas nas opções do seu navegador!"); - objects.forEach(async (object) => { - if (object.collectionable.link !== null) { - let url = mecredURLv1 + `/learning_objects/${object.collectionable.id}/download`; - window.open(url, '_blank'); - } else { - zip = true; - } - }); - - if (zip) { - window.location = mecredURL + `zipper/${id}`; + const handleDownloadCollection = async (e) => { + e.preventDefault(); + + try { + const response = await mecredApi.get( + `/public/collections/${id}/download`, + { responseType: "blob" } // importante para baixar arquivos + ); + + const url = window.URL.createObjectURL(response.data); + const a = document.createElement("a"); + a.href = url; + a.download = `collection-${id}.zip`; // ou outro nome apropriado + a.click(); + window.URL.revokeObjectURL(url); + + } catch (error) { + if (error.response?.data?.message) { + alert(error.response.data.message); // substitua por toast/modal se preferir + } else { + alert("Erro ao baixar a coleção."); + } + console.error(error); } - }; + }; + + return ( <button diff --git a/src/app/components/GroupCardsCollections.js b/src/app/components/GroupCardsCollections.js index a76a601604486ec21f9d1a141c2ef999bd53c017..da03df706ccc22ed44bce5bbac78f4ab0608f208 100644 --- a/src/app/components/GroupCardsCollections.js +++ b/src/app/components/GroupCardsCollections.js @@ -2,6 +2,8 @@ import { useEffect, useState } from "react"; import Cards from "./Cards"; import { useRouter } from "next/navigation" +import mecredApi from "@/axiosConfig"; +import { authHeaders } from "../handlers/loginHandler"; /** * Retorna na tela uma coleção * @param {Array.<Object>} data - recursos da coleção @@ -10,9 +12,10 @@ import { useRouter } from "next/navigation" export default function GroupCardsCollections({ data, cardsPerRow, collectionId }) { const [expanded, setExpanded] = useState(false); const [showButton, setShowButton] = useState(false); + const [resources, setResources] = useState(null) const router = useRouter() - - console.log(data) + const [totalCount, setTotalCount] = useState(0) + const [got, setGot] = useState(false) const handleResize = (data) => { setShowButton(data?.length > cardsPerRow); @@ -26,24 +29,56 @@ export default function GroupCardsCollections({ data, cardsPerRow, collectionId handleResize(data); }), [cardsPerRow]; + useEffect(() => { + const fetchResources = async () => { + // if (idLogin === id) { + + await mecredApi + .get(`public/collection-resources/${collectionId}/resources`, { + headers: authHeaders(), + }) + /** + * Além de setar as coleções, indica o número total de coleções + * Isso facilita na verificação + */ + .then(({ data, headers }) => { + setTotalCount(headers["x-total-count"]) + setResources(data) + + setGot(true) + }); + // } else { + // await mecredApi + // .get(`public/collections/${id}/collections`) + // .then(({ data, headers }) => { + // setTotalCount(headers["x-total-count"]) + // setCollections(data) + // console.log(data) + // setGot(true) + // }); + // } + }; + fetchResources(collectionId); + }, []); + return ( <div className="flex flex-col"> <div className="mx-1 flex flex-col"> <div id="contentSize" className={`flex content flex-wrap max-sm:justify-center mb-4 max-sm:ml-0 md:ml-0 ${expanded ? "" : "overflow-y-hidden h-[270px]"}`}> - {data?.length !== 0 ? data?.sort((a,b) => a.position - b.position).map((item, index) => { + {resources?.length !== 0 ? resources?.sort((a,b) => a.position - b.position).map((item, index) => { return ( <Cards collectionSource={collectionId} key={index} - id={item['collectionable']['id']} - title={item["collectionable"]["name"]} - author={item["collectionable"]["publisher"]["name"]} - authorId={item["collectionable"]["publisher"]["id"]} - avatar={item["collectionable"]["publisher"]["avatar"]} - image={item["collectionable"]["thumbnail"]} - updated_at={item["collectionable"]["updated_at"]} + id={item.resources.id} + title={item.resources.name} + author={item.resources.author} + authorId={item.resources.user_id} + avatar={`https://s3.c3sl.ufpr.br/mecredteste/avatar/${item.resources.user_id}`} + image={`https://s3.c3sl.ufpr.br/mecredteste/thumbnail/resource/${item.resources.id}`} + updated_at={item.resources.updated_at} /> ); }) diff --git a/src/app/components/Header.js b/src/app/components/Header.js index 62d9ef58f553dae4f4f1725d1a1c8bb26479abe3..6d736958ef563f68da2119dcb52bf87f2badc925 100644 --- a/src/app/components/Header.js +++ b/src/app/components/Header.js @@ -100,7 +100,7 @@ function DefaultContent({ <div className="max-md:hidden"><AccountMenu /></div> </> - ) : ( + ) : ( <button type="button" className="group bg-orange-HC-white hover:bg-darkOrange-HC-dark px-4 h-10 mr-8 max-sm:ml-2 rounded text-white-HC-dark-underline flex items-center font-bold flex-shrink-0 hover:text-white-HC-underline outline outline-1 outline-ice-HC-white" @@ -108,7 +108,7 @@ function DefaultContent({ > Entrar </button> - )} + )} </div> </div> diff --git a/src/app/components/ImageCropper.js b/src/app/components/ImageCropper.js index 2dbe5447dcb352e1ee888f46dfb958cc01d41e33..5c0efe75c80292fe98f91b85109f4742c7cadb22 100644 --- a/src/app/components/ImageCropper.js +++ b/src/app/components/ImageCropper.js @@ -4,182 +4,236 @@ import "react-image-crop/dist/ReactCrop.css"; import { canvasPreview } from "./canvasPreview"; import { getStoredValue, saveToLocalStorage } from "@/app/handlers/localStorageHandler"; import mecredApi from "@/axiosConfig"; +import { Modal } from "@mui/material"; +import { authHeaders } from "../handlers/loginHandler"; +import { useRouter } from "next/navigation" -export default function ImageCropper({ payloadHeader, type, userId, setChangePhoto }) { - // Estados para gerenciar a foto original, URL da foto, configuração do corte, corte completo e imagem cortada - const [photo, setPhoto] = useState(null); - const [photoURL, setPhotoURL] = useState(null); - const [crop, setCrop] = useState(null); - const [completedCrop, setCompletedCrop] = useState(false); - const [croppedImage, setCroppedImage] = useState(null); +export default function ImageCropper({ userId, setChangePhoto }) { + // Estados para gerenciar a foto original, URL da foto, configuração do corte, corte completo e imagem cortada + const [photo, setPhoto] = useState(null); + const [photoURL, setPhotoURL] = useState(null); + const [crop, setCrop] = useState(null); + const [completedCrop, setCompletedCrop] = useState(false); + const [croppedImage, setCroppedImage] = useState(null); + const [sucessOpen, setSucessOpen] = useState(false) + const [notSucessOpen, setNotSucessOpen] = useState(false) + const router = useRouter() - // Referências para a imagem e o canvas de pré-visualização - const imgRef = useRef(null); - const previewCanvasRef = useRef(null); + // Referências para a imagem e o canvas de pré-visualização + const imgRef = useRef(null); + const previewCanvasRef = useRef(null); + // Hook personalizado para aplicar debounce em efeitos + function useDebounceEffect(fn, waitTime, deps = []) { + useEffect(() => { + const t = setTimeout(() => { + fn.apply(undefined, deps); + }, waitTime); - // Recupera tokens de autenticação do armazenamento local - const token = getStoredValue("access_token"); - const client = getStoredValue("client"); - const uid = getStoredValue("uid"); + return () => { + clearTimeout(t); + }; + }, deps); + } - // Hook personalizado para aplicar debounce em efeitos - function useDebounceEffect(fn, waitTime, deps = []) { - useEffect(() => { - const t = setTimeout(() => { - fn.apply(undefined, deps); - }, waitTime); - - return () => { - clearTimeout(t); - }; - }, deps); - } + // Função para fazer upload da foto cortada + const uploadPhoto = async () => { + try { + let payload = new FormData(); + payload.set('file', croppedImage); + payload.set('id_user', String(userId)); + payload.set('content_type', croppedImage.type); // tipo MIME do arquivo (image/png, image/jpeg etc) - // Função para fazer upload da foto cortada - const uploadPhoto = async () => { - let payload = new FormData(); - payload.set(payloadHeader, croppedImage); - - await mecredApi.put(`/${type}/${userId}`, payload, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - }) - .catch(error => { - setChangePhoto(false); - if (error?.response.status === 500) // TODO: alterar isso quando tivermos um novo backend, pois não deveria retornar 500 toda vez. - console.error(error); // Talvez o backend tenha falhado, mas provavelmente a foto do perfil foi alterada. - }); - - await mecredApi.get(`/users/${userId}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - }) - .then(res => { - let userData = JSON.parse(getStoredValue("user_data")); - userData["avatar_file_name"] = res.data.avatar; - saveToLocalStorage("user_data", JSON.stringify(userData)); - }); - }; - - // Manipulador para quando o usuário seleciona uma foto - const handlePhoto = (e) => { - e.preventDefault(); - const file = e.target.files[0]; - if (file) { - setPhoto(file); - setPhotoURL(URL.createObjectURL(file)); - } - }; + const response = await mecredApi.post(`api/s3/upload/avatar`, payload, { + headers: authHeaders() + }); - // Função para centralizar o corte com uma proporção específica - function centerAspectCrop(mediaWidth, mediaHeight, aspect) { - return centerCrop( - makeAspectCrop( - { unit: "%", width: 50 }, - aspect, - mediaWidth, - mediaHeight - ), - mediaWidth, - mediaHeight - ); - } + console.log("Foto enviada com sucesso:", response.data); + setSucessOpen(true) - // Função chamada quando a imagem é carregada - function onImageLoad(e) { - const { width, height } = e.currentTarget; - const newCrop = centerAspectCrop(width, height, 1); - setCrop(newCrop); - setCompletedCrop(convertToPixelCrop(newCrop, width, height)); + } catch (error) { + setNotSucessOpen(true) + console.error("Erro ao enviar foto:", error); + } + }; + // Manipulador para quando o usuário seleciona uma foto + const handlePhoto = (e) => { + e.preventDefault(); + const file = e.target.files[0]; + if (file) { + setPhoto(file); + setPhotoURL(URL.createObjectURL(file)); } + }; - // Efeito com debounce para gerar a pré-visualização da imagem cortada - useDebounceEffect( - () => { - if ( - completedCrop?.width && - completedCrop?.height && - imgRef.current && - previewCanvasRef.current - ) { - // Gera a pré-visualização no canvas - canvasPreview( - imgRef.current, - previewCanvasRef.current, - completedCrop, - 1, - 0 - ); - // Converte o conteúdo do canvas em um blob e atualiza o estado - previewCanvasRef.current.toBlob((blob) => { - console.log("meu blob: ", blob); - setCroppedImage(blob); - }); - } - }, - 100, - [completedCrop] + // Função para centralizar o corte com uma proporção específica + function centerAspectCrop(mediaWidth, mediaHeight, aspect) { + return centerCrop( + makeAspectCrop( + { unit: "%", width: 50 }, + aspect, + mediaWidth, + mediaHeight + ), + mediaWidth, + mediaHeight ); + } + + // Função chamada quando a imagem é carregada + function onImageLoad(e) { + const { width, height } = e.currentTarget; + const newCrop = centerAspectCrop(width, height, 1); + setCrop(newCrop); + setCompletedCrop(convertToPixelCrop(newCrop, width, height)); + } + + // Efeito com debounce para gerar a pré-visualização da imagem cortada + useDebounceEffect( + () => { + if ( + completedCrop?.width && + completedCrop?.height && + imgRef.current && + previewCanvasRef.current + ) { + // Gera a pré-visualização no canvas + canvasPreview( + imgRef.current, + previewCanvasRef.current, + completedCrop, + 1, + 0 + ); + // Converte o conteúdo do canvas em um blob e atualiza o estado + previewCanvasRef.current.toBlob((blob) => { + console.log("meu blob: ", blob); + setCroppedImage(blob); + }); + } + }, + 100, + [completedCrop] + ); + const ModalSucess = ({ open, onClose }) => { return ( - <div className="flex flex-col items-center"> - <div className="flex space-x-4 mt-2 mb-5"> - <label className="bg-turquoise text-white-HC-dark-underline rounded-lg p-2 cursor-pointer"> - <input type="file" onChange={handlePhoto} className="hidden" /> - Selecionar Nova Foto - </label> - {completedCrop && ( - <button - className="text-sm p-2 text-white-HC-dark-underline border-main rounded-lg font-bold bg-turquoise hover:bg-turquoise-hover" - onClick={uploadPhoto} - > - Enviar - </button> - )} + <Modal open={open} onClose={onClose} className="grid place-items-center" slotProps={{ + backdrop: { + sx: { + backgroundColor: "rgba(0, 0, 0, 0.3)", // Ajuste a opacidade conforme necessário + }, + }, + }}> + <div className="flex flex-col justify-center bg-ice-HC-dark p-5 rounded"> + <p className="text-xl justify-center flex text-darkGray-HC-white-underline mb-2">Foto editada com sucesso!</p> + <div className="flex flex-row mt-2"> + + <button + className=" text-sm p-2 mr-1 text-white-HC-dark-underline border-main rounded-lg normal-case h-9 font-bold bg-turquoise hover:bg-turquoise-hover" + onClick={() => { + setChangePhoto(false); + router.push(`/perfil/${userId}`); + }} + > + Voltar para perfil + </button> + <button + className=" text-sm p-2 ml-1 text-darkGray-HC-white-underline border-main rounded-lg normal-case h-9 font-bold bg-ice-HC-dark hover:bg-ice-HC-dark-hover" + onClick={() => {onClose(); setChangePhoto(false)}} + > + Continuar editando + </button> + </div> + </div> + </Modal> + ) + } + + const ModalNotSucess = ({ open, onClose }) => { + return ( + <Modal open={open} onClose={onClose} className="grid place-items-center" slotProps={{ + backdrop: { + sx: { + backgroundColor: "rgba(0, 0, 0, 0.3)", // Ajuste a opacidade conforme necessário + }, + }, + }}> + <div className="flex flex-col justify-center bg-ice-HC-dark p-5 rounded"> + <p className="text-xl justify-center flex text-darkGray-HC-white-underline mb-2">Não foi possível alterar a foto</p> + <div className="flex flex-row mt-2"> + + <button + className=" text-sm p-2 mr-1 text-white-HC-dark-underline border-main rounded-lg normal-case h-9 font-bold bg-turquoise hover:bg-turquoise-hover" + onClick={() => { + setChangePhoto(false); + router.push(`/perfil/${userId}`); + }} + > + Voltar para perfil + </button> + <button + className=" text-sm p-2 ml-1 text-darkGray-HC-white-underline border-main rounded-lg normal-case h-9 font-bold bg-ice-HC-dark hover:bg-ice-HC-dark-hover" + onClick={() => {onClose(); setChangePhoto(false)}} + > + Continuar editando + </button> + </div> + </div> + </Modal> + ) + } + + return ( + <div className="flex flex-col items-center"> + <ModalNotSucess open={notSucessOpen} onClose={() => { setNotSucessOpen(false) }} /> + <ModalSucess open={sucessOpen} onClose={() => { setSucessOpen(false) }} /> + <div className="flex space-x-4 mt-2 mb-5"> + <label className="bg-turquoise text-white-HC-dark-underline rounded-lg p-2 cursor-pointer"> + <input type="file" onChange={handlePhoto} className="hidden" /> + Selecionar Nova Foto + </label> + {completedCrop && ( + <button + className="text-sm p-2 text-white-HC-dark-underline border-main rounded-lg font-bold bg-turquoise hover:bg-turquoise-hover" + onClick={uploadPhoto} + > + Enviar + </button> + )} + </div> + {photoURL && ( + <div className="flex space-x-4"> + <ReactCrop + crop={crop} + onChange={(_, percentCrop) => setCrop(percentCrop)} + onComplete={(c) => setCompletedCrop(c)} + aspect={1} + circularCrop={true} + > + <img + ref={imgRef} + alt="Imagem de Perfil" + src={photoURL} + onLoad={onImageLoad} + style={{ maxWidth: '400px', maxHeight: '400px' }} + /> + </ReactCrop> + {completedCrop && ( + <div className="flex justify-center items-center"> + <canvas + ref={previewCanvasRef} + style={{ + borderRadius: "50%", + border: "2px solid black", + objectFit: "contain", + width: Math.min(completedCrop.width, 200), + height: Math.min(completedCrop.height, 200), + }} + /> </div> - {photoURL && ( - <div className="flex space-x-4"> - <ReactCrop - crop={crop} - onChange={(_, percentCrop) => setCrop(percentCrop)} - onComplete={(c) => setCompletedCrop(c)} - aspect={1} - circularCrop={true} - > - <img - ref={imgRef} - alt="Imagem de Perfil" - src={photoURL} - onLoad={onImageLoad} - style={{ maxWidth: '400px', maxHeight: '400px' }} - /> - </ReactCrop> - {completedCrop && ( - <div className="flex justify-center items-center"> - <canvas - ref={previewCanvasRef} - style={{ - borderRadius: "50%", - border: "2px solid black", - objectFit: "contain", - width: Math.min(completedCrop.width, 200), - height: Math.min(completedCrop.height, 200), - }} - /> - </div> - )} - </div> - )} + )} </div> - ); + )} + </div> + ); } diff --git a/src/app/components/ItemNotification.js b/src/app/components/ItemNotification.js index ab649e3e0dcfdc62f123d24c1f64ecd2215ae6b0..d2c669ae88b605b9962608738b441f4074470d3f 100644 --- a/src/app/components/ItemNotification.js +++ b/src/app/components/ItemNotification.js @@ -1,7 +1,8 @@ -import { mecredURL } from "@/axiosConfig"; +import mecredApi, { mecredURL } from "@/axiosConfig"; import Image from "next/image"; import { useRouter } from "next/navigation"; - +import { useEffect, useState } from "react"; +import { authHeaders } from "../handlers/loginHandler"; const timeFunction = (updated_time) => { let data = new Date(updated_time) @@ -40,17 +41,15 @@ function getRandomBg(id) { function tradutor(nome) { switch (nome) { case "like.create": - return "curtiu" - case "like.destroy": - return "descurtiu" + return "curtiu " case "download.create": - return "baixou" + return "baixou " case "review.create": - return "avaliou" + return "avaliou " case "curator_assignment.create": return "você foi atribuido para avaliar " case "submission.rejected": - return "sua submissão foi rejeitada pela equipe de avaliadores." + return "sua submissão foi rejeitada pela equipe de avaliadores. " case "submission.accepted": return "sua submissão foi aceita pela equipe de avaliadores: " @@ -73,18 +72,34 @@ export default function ItemNotification({ notification, postViewNotification }) postViewNotification(payload) - router.push(`recurso/${notification.recipient?.id}`) + router.push(`/recurso/${notification.recipient?.id}`) } + const [imageExists, setImageExists] = useState(false); + const imageUrl = `https://s3.c3sl.ufpr.br/mecredteste/avatar/${notification.owner_id}`; + + useEffect(() => { + const checkImage = async () => { + await mecredApi.get(`public/s3/get/avatar/${notification.owner_id}`, { + headers: authHeaders() + }) + .then(({ headers }) => setImageExists(true)) + .catch((error) => { + setImageExists(false) + }) + }; + + checkImage(); + }, [notification.owner_id]); return ( <div className="flex flex-row px-3 py-4 mt-1 ml-2 hover:bg-ice-HC-dark hover:rounded-lg" onClick={viewOneNotification} > <div className="pr-3 pl-1 shrink-0 flex items-center"> - {!notification.owner?.avatar ? <div className={`flex items-center justify-center text-xl font-bold text-ice-HC-dark rounded-full h-[43px] w-[43px] ${getRandomBg(notification.owner.id)}`} >{notification.owner.name[0]}</div> + {!imageExists ? <div className={`flex items-center justify-center text-xl font-bold text-ice-HC-dark rounded-full h-[43px] w-[43px] ${getRandomBg(notification.owner_id)}`} >{notification.owner_name[0]}</div> : <Image - src={mecredURL + notification.owner.avatar} - alt={notification.owner.name} + src={imageUrl} + alt={notification.owner_name} width={43} height={43} className="w-[43px] h-[43px] object-cover rounded-full" @@ -94,16 +109,16 @@ export default function ItemNotification({ notification, postViewNotification }) <div> <p className="text-sm font-bold text-darkGray-HC-white line-clamp-1"> - {notification.owner.name} + {notification.actor_name} </p> <p className="text-sm font-normal text-darkGray-HC-white line-clamp-2 "> - {tradutor(notification.activity)} - <a className="text-turquoise-HC-underline -hover" href={`recurso/${notification.recipient?.id}`} > + {tradutor(notification.action_name)} + <a className="text-turquoise-HC-underline -hover" href={`/recurso/${notification.recipient?.id}`} > {notification.recipient?.name} </a> </p> <p className="text-sm font-light text-darkGray-HC-white "> - {timeFunction(notification.created_at)} + {timeFunction(notification.createdAt)} </p> </div> </div> diff --git a/src/app/components/ModalNotifications.js b/src/app/components/ModalNotifications.js index 84c12fb7be09256ce0d8881c0d30ab118f9b80f1..3040b9d0ff5a835435f25de94a30db119747605b 100644 --- a/src/app/components/ModalNotifications.js +++ b/src/app/components/ModalNotifications.js @@ -8,10 +8,6 @@ import Image from 'next/image'; import Loading from './Loading'; import ItemNotification from './ItemNotification'; - - - - export default function ModalNotifications({ countNotifications, notifications, postViewNotification }) { const [anchorEl, setAnchorEl] = useState(null); @@ -25,12 +21,15 @@ export default function ModalNotifications({ countNotifications, notifications, const setViewdAllNotification = () => { const payload = { - "activities": { - "ids": [] + activities: { + ids: notifications.map((noti) => noti.id), + viewed: true // <-- necessário pro Zod validar! } - } + }; notifications.forEach((noti) => payload.activities.ids.push(noti.id)); + + console.log(payload) postViewNotification(payload) } @@ -81,7 +80,7 @@ export default function ModalNotifications({ countNotifications, notifications, <div className='flex pr-2' > <div className='text-lg py-3 font-bold text-darkGray-HC-white pl-6 pr-16'> Notificações </div> <button className='text-darkGray-HC-white-underline text-sm bg-mediumGray-HC-dark rounded-xl px-2 h-10 mt-1 mr-1 hover:bg-mediumGray-HC-white hover:text-darkGray-HC-dark-underline outline outline-1 outline-ice-HC-white' onClick={setViewdAllNotification}> Marcar como lidas </button> - </div>t + </div> <div className='px-4'> <hr className='border-mediumGray-HC-white' /> </div> diff --git a/src/app/components/NavigationBar.js b/src/app/components/NavigationBar.js index c97b63a8d4f829987c206ed5b82e17b51c3dd61d..5572ab9e7e41b660b796813d457a79aed2924589 100644 --- a/src/app/components/NavigationBar.js +++ b/src/app/components/NavigationBar.js @@ -84,6 +84,17 @@ export default function NavigationBar({ mobileSearch }) { if (href === "#") return "#"; return `/busca?page=${href}`; }; + const navItems = [ + { label: "Pesquisar", href: "#", icon: SearchIcon }, + { label: "Perfil", href: "/perfil", icon: Person }, + { label: "Coleções", href: "/busca?page=Collection", icon: CollectionsBookmarkIcon }, + { label: "Recursos", href: "/busca?page=LearningObject", icon: SubjectIcon }, + { label: "Sobre", href: "/sobre", icon: HelpIcon }, + { label: "MEC", href: "/busca?page=MEC", icon: VerifiedIcon }, + { label: "Publicar", href: "/publicar", icon: FileUploadIcon }, + { label: "Contato", href: "/contato", icon: EmailRoundedIcon }, + { label: "Sair", href: "", icon: LogoutRounded}, + ] return ( <> diff --git a/src/app/components/Notifications.js b/src/app/components/Notifications.js index 080fb428bf9c1114869a57b9909d2f21daaf7189..29711cb5bf1706b4655eeef59dd74dfa2d914725 100644 --- a/src/app/components/Notifications.js +++ b/src/app/components/Notifications.js @@ -1,37 +1,25 @@ import mecredApi from "@/axiosConfig"; -import { useLoginBarrier } from "@/app/handlers/loginHandler"; +import { authHeaders, useLoginBarrier } from "@/app/handlers/loginHandler"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; import { useEffect, useState } from 'react' import ModalNotifications from "./ModalNotifications"; -export default function Notifications() { +export default function Notifications({id}) { const [notifications, setNotifications] = useState([]); const [countNotifications, setCountNotifications] = useState(null); const loginBarrier = useLoginBarrier() - const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") - useEffect(() => { if (!loginBarrier()) return - const url = `/feed?offset=0&limit=30` - - const getNotifications = async (url) => { + const getNotifications = async () => { await mecredApi - .get(url, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } + .get(`api/notifications`, { + headers: authHeaders() }) .then(({ data }) => { - + console.log(data) // temp pq o set fica um passo atras ai nao eh possivel usar o set do countNotifications let temp = data.filter((noti) => {return((noti.viewed === false))}) setNotifications(temp) @@ -39,23 +27,21 @@ export default function Notifications() { }) .catch((error) => console.error(error)) } + // const getOwnerNotification = async () => { + // await mecredApi + // .get(`/api/user/${notifications}`) + // } //chama funcao - getNotifications(url) + getNotifications() - }, [loginBarrier, uid, client, token]) + }, []) const postViewNotification = async (payload) => { - + console.log("oiii", payload) await mecredApi - .post("/activities/view", payload, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } + .post("api/notifications/updateMany", payload, { + headers: authHeaders() }) .then(() => { let temp = notifications.filter((noti) => (!payload.activities.ids.includes(noti.id))) diff --git a/src/app/components/SideBar.js b/src/app/components/SideBar.js index e5e314ae3d3a0af5f58c7548f5081e0fd17e8785..46c95be9bccae09a7823dd291e65df5d6ce95415 100644 --- a/src/app/components/SideBar.js +++ b/src/app/components/SideBar.js @@ -100,6 +100,15 @@ export default function SideBar({ setFilterState, filterState }) { const page = searchParams.get('page') const pathname = usePathname(); const loggedIn = useLoggedIn(); + const [id, setId] = useState(null); + + useEffect(() => { + if (loggedIn) { + let data = userData(); + console.log(data, "ALKSDJLAKSJD"); + setId(data?.user["id"]); + } + }, [loggedIn]); const getHref = (href) => { switch (href) { @@ -135,16 +144,6 @@ export default function SideBar({ setFilterState, filterState }) { } }; - const [id, setId] = useState(null); - - useEffect(() => { - if (loggedIn) { - let data = userData(); - console.log(data, "ALKSDJLAKSJD"); - setId(data?.["id"]); - } - }, [loggedIn]); - return ( <> <NeedLoginModal open={needLoginOpen} setOpen={setNeedLoginOpen} /> @@ -161,7 +160,7 @@ export default function SideBar({ setFilterState, filterState }) { key={index} alt={item.title} title={item.title} - className={`aspect-square cursor-pointer hover:bg-lightGray-HC-white hover:text-darkGray-HC-dark-underline focus:bg-lightGray-HC-white text-center rounded-lg items-center justify-center pt-2 w-[53%] h-[53%] + className={`aspect-square cursor-pointer hover:bg-lightGray-HC-white hover:text-darkGray-HC-dark-underline focus:bg-lightGray-HC-white text-center rounded-lg pt-2 w-[88px] ${(page === item.href) || (pathname.startsWith(item.href)) ? "bg-lightGray-HC-white text-darkGray-HC-dark-underline font-bold" : ""} `} > diff --git a/src/app/components/collectionPreview.js b/src/app/components/collectionPreview.js index 96554dc57a8996b37ed65f3c29f89287d479cd97..138819c7c1ad48a0e8700a1f11af34f6eb4757b0 100644 --- a/src/app/components/collectionPreview.js +++ b/src/app/components/collectionPreview.js @@ -50,7 +50,7 @@ const getDefaultThumbnail = (type) => { return thumbnail_url; }; -export default function CollectionPreview({ collection }) { +export default function CollectionPreview({ collection, resources }) { if (!collection?.id) return <></>; const uri = mecredURL + "inline/" + collection.id; @@ -70,7 +70,7 @@ export default function CollectionPreview({ collection }) { </div> ); - if (collection.items_thumbnails.length > 0) { + if (resources > 0) { content = ( <div className="relative aspect-video w-full h-full"> <Image @@ -81,7 +81,7 @@ export default function CollectionPreview({ collection }) { width: '100%', objectFit: 'cover' }} - src={mecredURL + collection.items_thumbnails[0]} + src={`https://s3.c3sl.ufpr.br/mecredteste/thumbnail/resource/${resource.id}`} alt={collection.name} /> </div> diff --git a/src/app/contato/page.js b/src/app/contato/page.js index bb6b42a83494968c70fc4036e947331b23e0b036..39c1939972dc0479c66ecad805c864a2b771ab0a 100644 --- a/src/app/contato/page.js +++ b/src/app/contato/page.js @@ -31,7 +31,7 @@ export default function Contact() { } await mecredApi - .post("/contacts", { + .post("public/contact", { name: formData.get("name"), email: formData.get("email"), message: formData.get("contents"), diff --git a/src/app/editar/[id]/components/UpdateInfo.js b/src/app/editar/[id]/components/UpdateInfo.js index 5ae05df06f26090ca81944ac4e54cdf01d3aeb18..6544ef5b6a27cd661f99f794ac0aa51d6349f963 100644 --- a/src/app/editar/[id]/components/UpdateInfo.js +++ b/src/app/editar/[id]/components/UpdateInfo.js @@ -1,316 +1,267 @@ +"use client" import { Avatar, Button, Modal, TextField } from "@mui/material" import FieldLabel from "@/app/components/FieldLabel" -import { useState, useMemo } from "react" +import { useState, useMemo, useEffect } from "react" import mecredApi, { mecredURL } from "@/axiosConfig" import { getStoredValue, saveToLocalStorage } from "@/app/handlers/localStorageHandler" import { useRouter } from "next/navigation" import ImageCropper from "@/app/components/ImageCropper" +import { authHeaders } from "@/app/handlers/loginHandler" export default function UpdateInfo({ user }) { - const [name, setName] = useState(user["name"]) - const [description, setDescription] = useState(user["description"] ? user["description"] : "") - const [sucessOpen, setSucessOpen] = useState(false) - const [notSucessOpen, setNotSucessOpen] = useState(false) - const [email, setEmail] = useState(user["email"] ?? "") - const [changePhoto, setChangePhoto] = useState(false) + const [name, setName] = useState(user["name"]) + const [description, setDescription] = useState(user["description"] ? user["description"] : "") + const [sucessOpen, setSucessOpen] = useState(false) + const [notSucessOpen, setNotSucessOpen] = useState(false) + const [email, setEmail] = useState(user["email"] ?? "") + const [changePhoto, setChangePhoto] = useState(false) + const reEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ - const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") - const router = useRouter() - const reEmail = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ + function getRandomBg(id) { + const colors = [ + "bg-turquoise", + "bg-orange", + "bg-turquoise-hover", + "bg-darkOrange-HC-gray ", + "bg-violet", + "bg-pink", + "bg-red", + "bg-darkGray-HC-white", + "bg-darkGray-HC-white-click", + "bg-ice-HC-dark ", + "bg-darkGray-HC-white", + "bg-darkGray-HC-white", + "bg-turquoise-HC-dark", + ] - function getRandomBg(id) { - const colors = [ - "bg-turquoise-HC-white", - "bg-orange-HC-white", - "bg-darkTurquoise-HC-white", - "bg-darkOrange-HC-white ", - "bg-violet-HC-white", - "bg-pink-HC-white", - "bg-red-HC-white", - "bg-darkGray-HC-white", - "bg-ice-HC-white", - ] - - return colors[id % colors.length]; + return colors[id % colors.length]; + } + + const handleSubmit = async (e) => { + e.preventDefault() + + if (name === "" || email === "") { + setNotSucessOpen(true) + return } + const payload = { + id: user.id, + name, + email, + description + }; + await mecredApi.post(`api/user/update`, payload, { + headers: authHeaders() + }) + .then(res => { + setSucessOpen(true); + }) + .catch(() => setNotSucessOpen(true)) + } - const handleSubmit = async (e) => { - e.preventDefault() + /** + * Handlers de texto + **/ + const handleNameChange = (e) => { + setName(e.target.value); + } - if (name === "" || email === "") { - setNotSucessOpen(true) - return - } + const handleDescriptionChange = (e) => { + setDescription(e.target.value); + } - const payload = { - user: { - name: name, - description: description, - email: email - } - } + const handleEmailChange = (e) => { + setEmail(e.target.value); + } - const url = `/users/${user["id"]}` + const router = useRouter() + + /* + * Modals + **/ + const ModalSucess = ({ open, onClose }) => { + return ( + <Modal open={open} onClose={onClose} className="grid place-items-center" slotProps={{ + backdrop: { + sx: { + backgroundColor: "rgba(0, 0, 0, 0.3)", // Ajuste a opacidade conforme necessário + }, + }, + }}> + <div className="flex flex-col justify-center bg-ice-HC-dark p-5 rounded"> + <p className="text-xl justify-center flex text-darkGray-HC-white-underline mb-2">Perfil editado com sucesso!</p> + <div className="flex flex-row mt-2"> - await mecredApi.put(url, payload, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - }) - .then(res => { - setSucessOpen(true); - }) - .catch(() => setNotSucessOpen(true)) + <button + className=" text-sm p-2 mr-1 text-white-HC-dark-underline border-main rounded-lg normal-case h-9 font-bold bg-turquoise hover:bg-turquoise-hover" + onClick={() => router.push(`/perfil/${user["id"]}`)} + > + Voltar para perfil + </button> + <button + className=" text-sm p-2 ml-1 text-darkGray-HC-white-underline border-main rounded-lg normal-case h-9 font-bold bg-ice-HC-dark hover:bg-ice-HC-dark-hover" + onClick={() => onClose()} + > + Continuar editando + </button> + </div> + </div> + </Modal> + ) + } - } + const ModalNotSucess = ({ open, onClose }) => { + return ( + <Modal open={open} onClose={onClose} className="grid place-items-center" slotProps={{ + backdrop: { + sx: { + backgroundColor: "rgba(0, 0, 0, 0.3)", // Ajuste a opacidade conforme necessário + }, + }, + }}> + <div className="flex flex-col justify-center bg-ice-HC-dark p-5 rounded"> + <p className="text-xl justify-center flex text-darkGray-HC-white-underline mb-2">Não foi possível fazer as alterações</p> + <div className="flex flex-row mt-2"> - /** - * Handlers de texto - **/ - const handleNameChange = (e) => { - setName(e.target.value); - } + <button + className=" text-sm p-2 mr-1 text-white-HC-dark-underline border-main rounded-lg normal-case h-9 font-bold bg-turquoise hover:bg-turquoise-hover" + onClick={() => router.push(`/perfil/${user.id}`)} + > + Voltar para perfil + </button> + <button + className=" text-sm p-2 ml-1 text-darkGray-HC-white-underline border-main rounded-lg normal-case h-9 font-bold bg-ice-HC-dark hover:bg-ice-HC-dark-hover" + onClick={() => onClose()} + > + Continuar editando + </button> + </div> + </div> + </Modal> + ) + } - const handleDescriptionChange = (e) => { - setDescription(e.target.value); - } + const ModalImageCropper = ({ open, onClose }) => { + return ( + <Modal + open={open} + onClose={onClose} + className="grid place-items-center" + slotProps={{ + backdrop: { + sx: { + backgroundColor: "rgba(0, 0, 0, 0.3)", // Ajuste a opacidade conforme necessário + }, + }, + }} + > + <div + className="flex flex-col bg-ice-HC-dark p-6 rounded-lg outline outline-1 outline-ice-HC-white overflow-auto" + style={{ + width: '90%', + maxWidth: '600px', + height: '70vh', + maxHeight: '90vh', + }} + > + <p className="text-xl text-darkGray-HC-white-underline text-center mb-4">Editar Foto de Perfil</p> - const handleEmailChange = (e) => { - setEmail(e.target.value); - } + <div className="flex-grow"> + <ImageCropper userId={user.id} setChangePhoto={setChangePhoto} /> + </div> - /* - * Modals - **/ - const ModalSucess = ({ open, onClose }) => { - return ( - <Modal open={open} onClose={onClose} className="grid place-items-center" slotProps={{ - backdrop: { - sx: { - backgroundColor: "rgba(0, 0, 0, 0.3)", // Ajuste a opacidade conforme necessário - }, - }, - }}> - <div className="flex flex-col justify-center bg-ice-HC-dark p-5 rounded"> - <p className="text-xl justify-center flex text-darkGray-HC-white-underline mb-2">Perfil editado com sucesso!</p> - <div className="flex flex-row mt-2"> + <button + className="text-sm p-2 text-darkGray-HC-white-underline border-main rounded-lg h-9 font-bold bg-ice-HC-dark hover:bg-ice-HC-dark-hover mt-4" + onClick={onClose} + > + Cancelar + </button> + </div> + </Modal> + ) + } - <button - className=" text-sm p-2 mr-1 text-white-HC-dark-underline border-main rounded-lg normal-case h-9 font-bold bg-turquoise hover:bg-turquoise-hover" - onClick={() => router.push(`/perfil/${user["id"]}`)} - > - Voltar para perfil - </button> - <button - className=" text-sm p-2 ml-1 text-darkGray-HC-white-underline border-main rounded-lg normal-case h-9 font-bold bg-ice-HC-dark hover:bg-ice-HC-dark-hover" - onClick={() => onClose()} - > - Continuar editando - </button> - </div> - </div> - </Modal> - ) - } + const [imageExists, setImageExists] = useState(false); + const imageUrl = `https://s3.c3sl.ufpr.br/mecredteste/avatar/${user.id}?nocache=${Date.now()}`; - const ModalNotSucess = ({ open, onClose }) => { - return ( - <Modal open={open} onClose={onClose} className="grid place-items-center" slotProps={{ - backdrop: { - sx: { - backgroundColor: "rgba(0, 0, 0, 0.3)", // Ajuste a opacidade conforme necessário - }, - }, - }}> - <div className="flex flex-col justify-center bg-ice-HC-dark p-5 rounded"> - <p className="text-xl justify-center flex text-darkGray-HC-white-underline mb-2">Não foi possível fazer as alterações</p> - <div className="flex flex-row mt-2"> + useEffect(() => { + const checkImage = async () => { + await mecredApi.get(`public/s3/get/avatar/${user.id}`, { + headers: authHeaders() + }) + .then(({ headers }) => setImageExists(true)) + .catch((error) => { + setImageExists(false) + }) + }; - <button - className=" text-sm p-2 mr-1 text-white-HC-dark-underline border-main rounded-lg normal-case h-9 font-bold bg-turquoise hover:bg-turquoise-hover" - onClick={() => router.push(`/perfil/${user["id"]}`)} - > - Voltar para perfil - </button> - <button - className=" text-sm p-2 ml-1 text-darkGray-HC-white-underline border-main rounded-lg normal-case h-9 font-bold bg-ice-HC-dark hover:bg-ice-HC-dark-hover" - onClick={() => onClose()} - > - Continuar editando - </button> - </div> - </div> - </Modal> - ) - } + checkImage(); + }, [user.id]); - const ModalImageCropper = ({ open, onClose }) => { - return ( - <Modal - open={open} - onClose={onClose} - className="grid place-items-center" - slotProps={{ - backdrop: { - sx: { - backgroundColor: "rgba(0, 0, 0, 0.3)", // Ajuste a opacidade conforme necessário - }, - }, - }} - > - <div - className="flex flex-col bg-ice-HC-dark p-6 rounded-lg outline outline-1 outline-ice-HC-white overflow-auto" - style={{ - width: '90%', - maxWidth: '600px', - height: '70vh', - maxHeight: '90vh', - }} - > - <p className="text-xl text-darkGray-HC-white-underline text-center mb-4">Editar Foto de Perfil</p> - - <div className="flex-grow"> - <ImageCropper payloadHeader={"user[avatar]"} type={"users"} userId={user.id} setChangePhoto={setChangePhoto} /> - </div> - - <button - className="text-sm p-2 text-darkGray-HC-white-underline border-main rounded-lg h-9 font-bold bg-ice-HC-dark hover:bg-ice-HC-dark-hover mt-4" - onClick={onClose} - > - Cancelar - </button> - </div> - </Modal> - ) - } - - return ( - <div> - <ModalNotSucess open={notSucessOpen} onClose={() => { setNotSucessOpen(false) }} /> - <ModalSucess open={sucessOpen} onClose={() => { setSucessOpen(false) }} /> - <form onSubmit={handleSubmit}> - <label className="text-3xl text-darkGray-HC-white font-bold mt-3 flex justify-center">Editar Perfil</label> - <div className="flex flex-col mt-4 items-center"> - <label className="text-xl text-darkGray-HC-white font-bold mx-6">Foto de perfil</label> - <div className="flex flex-col items-center my-2"> - {user["avatar"] ? ( - <img - src={mecredURL + user["avatar"]} - className="w-[150px] h-[150px] object-cover rounded-full" - alt="Editar perfil" - /> - ) : ( - <div - className={`flex items-center justify-center text-xl font-bold text-ice-HC-dark rounded-full h-[150px] w-[150px] ${getRandomBg(user["id"])}`} - > - {user["name"][0]} - </div> - )} - - <button - type="button" - className="bg-turquoise-HC-white hover:bg-darkTurquoise-HC-dark text-white-HC-dark-underline hover:text-white rounded-lg mt-2 px-4 py-2 outline outline-1 outline-ice-HC-white" - onClick={() => setChangePhoto(true)} - > - Editar Foto - </button> + return ( + <div> + <ModalNotSucess open={notSucessOpen} onClose={() => { setNotSucessOpen(false) }} /> + <ModalSucess open={sucessOpen} onClose={() => { setSucessOpen(false) }} /> + <form onSubmit={handleSubmit}> + <label className="text-3xl text-darkGray-HC-white-underline font-bold mt-3 flex justify-center">Editar Perfil</label> + <div className="flex flex-col mt-4 items-center"> + <label className="text-xl text-darkGray-HC-white font-bold mx-6">Foto de perfil</label> + <div className="flex flex-col items-center my-2"> + {imageExists ? + <Avatar src={imageUrl} sx={{ position: "inherit" }} alt="Foto de perfil" className=" h-[276px] w-[276px] " /> + : + <div className={`flex items-center justify-center text-8xl font-bold text-ice-HC-dark rounded-full h-[276px] w-[276px] bg-turquoise-HC-white ${getRandomBg(user.id)}`} >{user.name[0]}</div> + } + <button + type="button" + className="bg-turquoise text-white-HC-dark-underline rounded-lg mt-2 px-4 py-2" + onClick={() => setChangePhoto(true)} + > + Editar Foto + </button> - <ModalImageCropper open={changePhoto} onClose={() => setChangePhoto(false)} /> - </div> - </div> + <ModalImageCropper open={changePhoto} onClose={() => setChangePhoto(false)} /> + </div> + </div> - <div className="mx-4 mt-4"> - <label className=" text-xl text-darkGray-HC-white font-bold ">Nome Completo *</label> - <TextField - onChange={handleNameChange} - className="w-[100%] mt-2 outline outline-1 outline-ice-HC-white text-ice-HC-white" - defaultValue={user["name"]} - sx={{ - '& .MuiOutlinedInput-root': { - '& fieldset': { - borderColor: 'var(--mediumGray-HC-white)', // cor da borda - }, - '&:hover fieldset': { - borderColor: 'var(--turquoise-HC-white)', // ao passar o mouse - }, - '&.Mui-focused fieldset': { - borderColor: 'var(--turquoise-HC-white)', // quando estiver focado - }, - "& input": { - color: "var(--darkGray-HC-white)", - }, - }, - }} - /> - </div> - <div className="mx-4"> - <FieldLabel name="Sobre mim" description="Visível no seu perfil público" /> - <TextField - multiline - rows={3} - onChange={handleDescriptionChange} - helperText={`${description.length}/160`} - error={description.length > 160} - className="w-[100%] outline outline-1 outline-ice-HC-white" - defaultValue={user["description"]} - sx={{ - '& .MuiOutlinedInput-root': { - '& fieldset': { - borderColor: 'var(--mediumGray-HC-white)', // cor da borda - }, - '&:hover fieldset': { - borderColor: 'var(--turquoise-HC-white)', // ao passar o mouse - }, - '&.Mui-focused fieldset': { - borderColor: 'var(--turquoise-HC-white)', // quando estiver focado - }, - "& input": { - color: "var(--darkGray-HC-white)", - }, - }, - }} - /> - </div> - <div className="mx-4 mt-8"> - <label className=" text-xl text-darkGray-HC-white font-bold">Email *</label> - <TextField - onChange={handleEmailChange} - className="w-[100%] mt-2 outline outline-1 outline-ice-HC-white" - defaultValue={user["email"]} - sx={{ - '& .MuiOutlinedInput-root': { - '& fieldset': { - borderColor: 'var(--mediumGray-HC-white)', // cor da borda - }, - '&:hover fieldset': { - borderColor: 'var(--turquoise-HC-white)', // ao passar o mouse - }, - '&.Mui-focused fieldset': { - borderColor: 'var(--turquoise-HC-white)', // quando estiver focado - }, - "& input": { - color: "var(--darkGray-HC-white)", - }, - }, - }} - /> - </div> + <div className="mx-4 mt-4"> + <label className=" text-xl text-darkGray-HC-white-underline font-bold ">Nome Completo *</label> + <TextField + onChange={handleNameChange} + className="w-[100%] mt-2" + defaultValue={user["name"]} + /> + </div> + <div className="mx-4"> + <FieldLabel name="Sobre mim" description="Visível no seu perfil público" /> + <TextField + multiline + rows={3} + onChange={handleDescriptionChange} + helperText={`${description.length}/160`} + error={description.length > 160} + className="w-[100%]" + defaultValue={user["description"]} + /> + </div> + <div className="mx-4 mt-8"> + <label className=" text-xl text-darkGray-HC-white-underline font-bold ">Email *</label> + <TextField + onChange={handleEmailChange} + className="w-[100%] mt-2" + defaultValue={user["email"]} + /> + </div> - <div className="flex justify-end mt-5 mr-4"> + <div className="flex justify-end mt-5 mr-4"> - <button type="button" onClick={() => router.push(`/perfil/${user["id"]}`)} className="bg-white-HC-dark hover:bg-white text-darkGray-HC-white-underline hover:text-darkGray-HC-dark p-2 rounded-lg mr-1 outline outline-1 outline-ice-HC-white ">Voltar para perfil</button> - <button type="submit" className="bg-turquoise-HC-white hover:bg-darkTurquoise-HC-dark text-white-HC-dark-underline hover:text-white p-2 rounded-lg ml-1 outline outline-1 outline-ice-HC-white">Salvar alterações</button> - </div> - </form> + <button type="button" onClick={() => router.push(`/perfil/${user["id"]}`)} className="bg-white-HC-dark text-darkGray-HC-white-underline p-2 rounded-lg hover:bg-ice-HC-dark-hover mr-1 ">Voltar para perfil</button> + <button type="submit" className="bg-turquoise text-white-HC-dark-underline p-2 rounded-lg hover:bg-turquoise-hover ml-1 ">Salvar alterações</button> </div> - ) + </form> + </div> + ) } diff --git a/src/app/editar/[id]/components/UpdatePassword.js b/src/app/editar/[id]/components/UpdatePassword.js index 65f4741381934cc036f12ec8e1f797782fcd1bba..eabca4b7dd47d9798eeec442650f4c752a111100 100644 --- a/src/app/editar/[id]/components/UpdatePassword.js +++ b/src/app/editar/[id]/components/UpdatePassword.js @@ -3,6 +3,7 @@ import { Modal, TextField } from "@mui/material" import { useState } from "react" import { getStoredValue } from "@/app/handlers/localStorageHandler" import { useRouter } from "next/navigation" +import { authHeaders } from "@/app/handlers/loginHandler" export default function UpdatePassword({ user }) { const [currentPassword, setCurrentPassword] = useState("") @@ -11,21 +12,6 @@ export default function UpdatePassword({ user }) { const [equal, setEqual] = useState(true) const [notSucessOpen, setNotSucessOpen] = useState(false) const [sucessOpen, setSucessOpen] = useState(false) - const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") - const authHeaders = { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - } - const router = useRouter() - - const handleCurr = (e) => { setCurrentPassword(e.target.value) @@ -59,14 +45,15 @@ export default function UpdatePassword({ user }) { return } - await mecredApi.put(url, payload, authHeaders) + await mecredApi.put(url, payload, { + headers: authHeaders() + }) .then(() => setSucessOpen(true)) .catch(() => setNotSucessOpen(true)) - - } + const ModalNotSucess = ({ open, onClose }) => { return ( <Modal open={open} onClose={onClose} className="grid place-items-center" slotProps={{ @@ -136,54 +123,25 @@ export default function UpdatePassword({ user }) { <ModalSucess open={sucessOpen} onClose={() => { setSucessOpen(false) }} /> <form onSubmit={handleSubmit}> <div className="mx-4 mt-8 flex flex-col"> - <label className=" text-xl text-darkGray-HC-white font-bold ">Alterar senha</label> - <label className=" text-base text-darkGray-HC-white mt-4 ">Nova senha *</label> + <label className=" text-xl text-darkGray-HC-white-underline font-bold ">Alterar senha</label> + <label className=" text-base text-darkGray-HC-white-underline mt-4 ">Nova senha *</label> <TextField onChange={handleNew} type="password" - className="w-[100%] mt-2 outline outline-1 outline-ice-HC-white" - sx={{ - '& .MuiOutlinedInput-root': { - '& fieldset': { - borderColor: 'var(--mediumGray-HC-white)', // cor da borda - }, - '&:hover fieldset': { - borderColor: 'var(--turquoise-HC-white)', // ao passar o mouse - }, - '&.Mui-focused fieldset': { - borderColor: 'var(--turquoise-HC-white)', // quando estiver focado - }, - }, - }} + className="w-[100%] mt-2" /> - <label className=" text-base text-darkGray-HC-white mt-4 ">Repita nova senha *</label> + <label className=" text-base text-darkGray-HC-white-underline mt-4 ">Repita nova senha *</label> <TextField onChange={handleRepeat} type="password" - className="w-[100%] mt-2 outline outline-1 outline-ice-HC-white" - sx={{ - '& .MuiOutlinedInput-root': { - '& fieldset': { - borderColor: 'var(--mediumGray-HC-white)', // cor da borda - }, - '&:hover fieldset': { - borderColor: 'var(--turquoise-HC-white)', // ao passar o mouse - }, - '&.Mui-focused fieldset': { - borderColor: 'var(--turquoise-HC-white)', // quando estiver focado - }, - "& input": { - color: "var(--darkGray-HC-white)", - }, - }, - }} + className="w-[100%] mt-2" /> {!equal && <label className="text-sm text-red-700 mt-1">*Senhas devem ser iguais</label>} </div> - <div className="flex justify-end mb-5 mr-4 "> + <div className="flex justify-end mb-5 mr-4"> - <button type="button" onClick={() => router.push(`/perfil/${user["id"]}`)} className="bg-white-HC-dark text-darkGray-HC-white-underline p-2 mt-5 rounded-lg hover:bg-white hover:text-darkGray-HC-dark mr-1 outline outline-1 outline-ice-HC-white">Voltar para perfil</button> - <button type="submit" className="bg-turquoise-HC-white text-white-HC-dark-underline hover:text-white p-2 mt-5 rounded-lg hover:bg-darkTurquoise-HC-dark ml-1 outline outline-1 outline-ice-HC-white">Salvar nova senha</button> + <button type="button" onClick={() => router.push(`/perfil/${user["id"]}`)} className="bg-white-HC-dark text-darkGray-HC-white-underline p-2 mt-5 rounded-lg hover:bg-ice-HC-dark-hover mr-1 ">Voltar para perfil</button> + <button type="submit" className="bg-turquoise text-white-HC-dark-underline p-2 mt-5 rounded-lg hover:bg-turquoise-hover ml-1">Salvar nova senha</button> </div> </form> diff --git a/src/app/editar/[id]/page.js b/src/app/editar/[id]/page.js index a9a984d529cf7d2b2f60bf56cc981e798bf709da..3fc8c66946a04631043d2ae86aa00329d5ac5bab 100644 --- a/src/app/editar/[id]/page.js +++ b/src/app/editar/[id]/page.js @@ -4,30 +4,21 @@ import EditForm from "./components/EditForm"; import { useEffect, useState } from "react"; import mecredApi from "@/axiosConfig"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; -import { useLoginBarrier } from "@/app/handlers/loginHandler"; +import { authHeaders, useLoginBarrier } from "@/app/handlers/loginHandler"; import Loading from "../../components/Loading"; export default function Edit({ params }) { const [userData, setUserData] = useState() - const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") const loginBarrier = useLoginBarrier() const [got, setGot] = useState(false) useEffect(() => { - if (!loginBarrier()) - return + // if (!loginBarrier()) + // return const fetchUser = async (id) => { await mecredApi - .get(`/users/${id}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } + .get(`api/user/${id}`, { + headers: authHeaders() }) .then(({data}) => { setUserData(data); @@ -37,7 +28,7 @@ export default function Edit({ params }) { } fetchUser(params.id) - }, [params.id, token, client, uid, loginBarrier]) + }, [params.id]) const ErrorEdit = () => { return ( diff --git a/src/app/perfil/[id]/components/CardsComplaints.js b/src/app/perfil/[id]/components/CardsComplaints.js index 78e1cf17d10b5edf31ccb70250f50126bd7094f7..ce0832416831138173503d28c982e4e5c703a7c2 100644 --- a/src/app/perfil/[id]/components/CardsComplaints.js +++ b/src/app/perfil/[id]/components/CardsComplaints.js @@ -32,14 +32,14 @@ export default function CardsComplaints({ item, key}) { }} component="img" image="/images/preview-recurso-denunciado.png" - title={item[0]?.name} + title={item?.name} alt="img" /> <CardHeader className="self-start flex-shrink h-[100px]" title={ <Typography variant="body2" color="" className="line-clamp-2 text-darkGray-HC-white-underline font-bold"> - {item[0]?.name} + {item?.name} </Typography> } subheader={ @@ -49,7 +49,7 @@ export default function CardsComplaints({ item, key}) { color="text.secondary" className="line-clamp-1 text-darkGray-HC-white font-light" > - {item[0]?.name} + {item?.name} </Typography> </> } @@ -57,7 +57,7 @@ export default function CardsComplaints({ item, key}) { <div className="hover:bg-ice-HC-dark-hover flex items-end rounded-lg"> <Button className="text-darkGray-HC-white-underline font-light" alt='Avaliar' - onClick={() => window.open(location.protocol + `//` + location.host + `/recurso/${item[0]?.learning_object_id}`)} + onClick={() => window.open(location.protocol + `//` + location.host + `/recurso/${item?.id}`)} > Avaliar </Button> diff --git a/src/app/perfil/[id]/components/CardsHomologation.js b/src/app/perfil/[id]/components/CardsHomologation.js index b95ca213a40908fa6c6569ddb93f81587a93a02d..f713f650eebdd82f756a169aa5ba162b942a4554 100644 --- a/src/app/perfil/[id]/components/CardsHomologation.js +++ b/src/app/perfil/[id]/components/CardsHomologation.js @@ -5,6 +5,7 @@ import Avatar from "@mui/material/Avatar"; import Typography from "@mui/material/Typography"; import Link from "next/link"; import { mecredURL } from "@/axiosConfig"; +import { useEffect, useState } from "react"; const getDefaultThumbnail = (type) => { let thumbnail_url; @@ -52,6 +53,34 @@ const getDefaultThumbnail = (type) => { */ export default function CardsHomologation({ item, key, tag }) { + const [imageMap, setImageMap] = useState({}); + + const verifyImage = async (id) => { + try { + await mecredApi.get(`public/s3/get/thumbnail/resource/${id}`, { + headers: authHeaders() + }); + return true; // Existe + } catch (error) { + if (error.response && error.response.status === 404) { + return false; // Não existe + } + return false; + } + }; + + useEffect(() => { + const checkImage = async () => { + const exists = await verifyImage(item.id); + setImageMap({ [item.id]: exists }); + }; + + if (item) { + checkImage(); + } + }, [item]); + + return ( <Card className="transition bg-white-HC-dark outline outline-1 outline-ice-HC-white items-center mt-5 mx-2 min-h-[320px]" @@ -78,22 +107,21 @@ export default function CardsHomologation({ item, key, tag }) { }} component="img" image={ - tag ? null : - item["learning_object"]["thumbnail"] === null - ? getDefaultThumbnail(item["learning_object"]["object_type"]) - : mecredURL + item["learning_object"]["thumbnail"] - } - title={ tag ? item[0]?.name : item["learning_object"]["thumbnail"]} + imageMap[item.id] + ? `https://s3.c3sl.ufpr.br/mecredteste/thumbnail/resource/${item.id}` + : getDefaultThumbnail(item.objectTypeName) + } + title={item[0]?.name} alt="img" /> <CardHeader className="self-start flex-shrink h-[100px]" - avatar={tag ? null : item["submitter"]["avatar"] === null ? null : + avatar={ <Link href="/perfil"> <Avatar - src={mecredURL + item["submitter"]["avatar"]} - alt={item["submitter"]["name"]} - title={item["submitter"]["name"]} + src={`https://s3.c3sl.ufpr.br/mecredteste/avatar/${item.user_id}`} + alt={item.author} + title={item.author} // className="-mt-9" sx={{ width: 28, @@ -106,7 +134,7 @@ export default function CardsHomologation({ item, key, tag }) { } title={ <Typography variant="body2" color="" className="line-clamp-2 text-darkGray-HC-white-underline font-bold"> - { tag ? item[0]?.name : item["learning_object"]["name"]} + { tag ? item[0]?.name : item.name} </Typography> } subheader={ @@ -116,7 +144,7 @@ export default function CardsHomologation({ item, key, tag }) { color="text.secondary" className="line-clamp-1 text-darkGray-HC-white-underline font-light" > - {tag ? item[0]?.name : item["submitter"]["name"]} + {tag ? item[0]?.name : item.author} </Typography> </> } diff --git a/src/app/perfil/[id]/components/CreateCollectionModal.js b/src/app/perfil/[id]/components/CreateCollectionModal.js index b10a63a74af440ab1b2736c79aae561c8703a481..22ae4f30a3b67a8d680c8cb5cfda5defd0250c9c 100644 --- a/src/app/perfil/[id]/components/CreateCollectionModal.js +++ b/src/app/perfil/[id]/components/CreateCollectionModal.js @@ -2,6 +2,7 @@ import { FormLabel, Modal, TextField, RadioGroup, FormControlLabel, Radio } from import { useState } from "react"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; import mecredApi from "@/axiosConfig"; +import { authHeaders } from "@/app/handlers/loginHandler"; /** * @param {Object} props @@ -56,26 +57,19 @@ export default function CreateCollectionModal({ open, onClose, idLogin }) { * Informações necessárias para o backend para criar uma nova coleção */ const payload = { - "collection": { - "name": name, - "owner_id": idLogin, - "owner_type": "User", - "privacy": e.target["privacy-radio-group"].value - } + "user_id": idLogin, + "name": name, + "privacy": e.target["privacy-radio-group"].value }; /** * Requisição para criação da coleção */ + console.log(typeof idLogin); // deve mostrar "number" se estiver certinho + try { // Requisição para criação da coleção - const response = await mecredApi.post("/collections", payload, { - headers: { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, - }, + const response = await mecredApi.post("api/collections/create", payload, { + headers: authHeaders(), }); setOpenSuccess(true); setName(""); @@ -114,12 +108,12 @@ export default function CreateCollectionModal({ open, onClose, idLogin }) { <FormLabel > <RadioGroup name="privacy-radio-group"> <FormControlLabel - value="public" + value="false" control={<Radio className="" />} label="Coleção Pública" /> <FormControlLabel - value="private" + value="true" control={<Radio />} label="Coleção Privada" /> diff --git a/src/app/perfil/[id]/components/EditCollectionModal.js b/src/app/perfil/[id]/components/EditCollectionModal.js index 2dbe06a83b7fd20a0db3813b13006037b09e0c56..083c074883ed0b21d4b96861a64bbfe4ad160134 100644 --- a/src/app/perfil/[id]/components/EditCollectionModal.js +++ b/src/app/perfil/[id]/components/EditCollectionModal.js @@ -2,6 +2,7 @@ import { useState } from "react"; import { Modal, TextField, RadioGroup, FormControlLabel, Radio, FormLabel } from "@mui/material"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; import mecredApi from "@/axiosConfig"; +import { authHeaders } from "@/app/handlers/loginHandler"; /** * @param {Object} props @@ -23,25 +24,16 @@ export default function EditCollectionModal({ open, onClose, collectionId, colle const handleSubmit = async (e) => { e.preventDefault(); - const payload = { - collection: { - name, - owner_id: collectionData.owner_id, - owner_type: collectionData.owner_type, - privacy, - }, + id: collectionId, + name, + owner_id: collectionData.owner_id, + owner_type: collectionData.owner_type, + privacy, }; - try { - const response = await mecredApi.put(`/collections/${collectionId}`, payload, { - headers: { - "access-token": token, - "token-type": "Bearer", - client, - uid, - Expires: 0, - }, + const response = await mecredApi.post(`api/collections/update`, payload, { + headers: authHeaders(), }); console.log(response.data) diff --git a/src/app/perfil/[id]/components/FollowersCards.js b/src/app/perfil/[id]/components/FollowersCards.js index f4102bea7aa42188521e4426b68563419c8bc37c..dba01ae8978f1865143c5b4e23f242e9753990e5 100644 --- a/src/app/perfil/[id]/components/FollowersCards.js +++ b/src/app/perfil/[id]/components/FollowersCards.js @@ -5,7 +5,7 @@ import UsersPageCard from "@/app/components/UsersPageCard"; import { Button } from "@mui/material"; import NotFound from "./NotFound"; import Loading from "@/app/components/Loading"; - +import { authHeaders } from "@/app/handlers/loginHandler"; /** * * @param {Object} props @@ -16,25 +16,15 @@ import Loading from "@/app/components/Loading"; export default function FollowersCards({ id, count }) { const [numberCards, setNumberCards] = useState(0); const [followers, setFollowers] = useState([]); - const token = getStoredValue("access_token"); - const client = getStoredValue("client"); - const uid = getStoredValue("uid"); - const expiry = getStoredValue("expiry"); const [got, setGot] = useState(false); useEffect(() => { const fetchData = async () => { try { - const { data } = await mecredApi.get(`/users/${id}/followers?offset=${numberCards}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': expiry - } + const { data } = await mecredApi.get(`public/user/followers/${id}?offset=${numberCards}`, { + headers: authHeaders() }); - setFollowers((prevFollowers) => [...prevFollowers, ...data]); + setFollowers((prevFollowers) => [...prevFollowers, ...(Array.isArray(data) ? data : [])]); setGot(true); } catch (error) { console.error(error); @@ -45,7 +35,7 @@ export default function FollowersCards({ id, count }) { // token changes after each request so if we put as dependecy it will keep changing and make more than one request. // to solve this we probably need useContext. // eslint-disable-next-line react-hooks/exhaustive-deps - }, [id, numberCards, client, uid, expiry]); + }, [id, numberCards]); const toggleContent = () => { setNumberCards((prevNumberCards) => prevNumberCards + 12); diff --git a/src/app/perfil/[id]/components/FollowingCards.js b/src/app/perfil/[id]/components/FollowingCards.js index b04101d724275a7c75b1949c3e9e5cc41ce71250..cdfbe7a5f64ad7af37b086a100c9e6ede4366aa1 100644 --- a/src/app/perfil/[id]/components/FollowingCards.js +++ b/src/app/perfil/[id]/components/FollowingCards.js @@ -5,6 +5,7 @@ import UsersPageCard from "@/app/components/UsersPageCard"; import { Button } from "@mui/material"; import NotFound from "./NotFound"; import Loading from "@/app/components/Loading"; +import { authHeaders } from "@/app/handlers/loginHandler"; /** * @@ -21,19 +22,14 @@ export default function FollowingCards({ id, count }) { const uid = getStoredValue("uid"); const expiry = getStoredValue("expiry"); const [got, setGot] = useState(false); + useEffect(() => { const fetchData = async () => { try { - const { data } = await mecredApi.get(`/users/${id}/following/User?offset=${numberCards}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': expiry - } + const { data } = await mecredApi.get(`public/user/follows/${id}`, { + headers: authHeaders() }); - setFollowing((prevFollowing) => [...prevFollowing, ...data]); + setFollowing((prevFollowing) => [...prevFollowing, ...(Array.isArray(data) ? data : [])]); setGot(true); } catch (error) { console.error(error); diff --git a/src/app/perfil/[id]/components/GroupButton.js b/src/app/perfil/[id]/components/GroupButton.js index cfa838fe776be69c505541989c6abe5080436a91..6b1014d1ad8097661b911f0f2596c1106e03a718 100644 --- a/src/app/perfil/[id]/components/GroupButton.js +++ b/src/app/perfil/[id]/components/GroupButton.js @@ -42,8 +42,8 @@ export default function GroupButton({ profileData, idLogin }) { * Fetch de seguir ou parar de seguir outro usuário */ const followHandler = () => { - if (!loginBarrier()) - return + // if (!loginBarrier()) + // return mecredApi.put( `users/${profileData["id"]}/follow/`, {}, diff --git a/src/app/perfil/[id]/components/MedalAchievements.js b/src/app/perfil/[id]/components/MedalAchievements.js index 293427e891b54a071f31ff9c2c253ae62cb42a73..406b17972a509df9c1d52bd515cb9bf0fe01707e 100644 --- a/src/app/perfil/[id]/components/MedalAchievements.js +++ b/src/app/perfil/[id]/components/MedalAchievements.js @@ -7,19 +7,27 @@ export default function MedalAchievements({ items }) { return ( <div className="flex flex-row w-1/3 max-sm:w-full justify-end max-sm:justify-center xl:gap-x-6 max-sm:gap-x-2 md:gap-x-2 md:max-xl:ml-[80px] xl:mr-10 max-sm:mb-5"> - {items?.map((avatar, index) => - avatar.being_used && ( - <div key={index} className="flex shrink-0 flex-row relative"> - <img src="/medalha-exibicao-da-conquista.svg" alt="medal" className=" flex w-[69px] h-[92px] max-sm:w-[50px] invertLogo-HC-white" /> - <Avatar - className="w-[57px] h-[55px] max-sm:w-[40px] max-sm:h-[40px] max-sm:top-4 max-sm:right absolute top-1.5 right-1.5 " - key={avatar.item ? avatar.name : null} - alt={avatar.item ? avatar.item.name : avatar.name} - src={mecredURL + (avatar.item ? avatar.item.image : null)} - /> - </div> + {(items?.length ?? 0) > 0 ? ( + items.map((avatar, index) => + avatar.is_active && ( + <div key={index} className="flex shrink-0 flex-row relative"> + <img + src="/medalha-exibicao-da-conquista.svg" + alt="medal" + className="flex w-[69px] h-[92px] max-sm:w-[50px] invertLogo-HC-white" + /> + <Avatar + className="w-[57px] h-[55px] max-sm:w-[40px] max-sm:h-[40px] max-sm:top-4 max-sm:right absolute top-1.5 right-1.5" + key={avatar.item ? avatar.name : null} + alt={avatar.item ? avatar.item.name : avatar.name} + src={mecredURL + (avatar.item?.image ?? '')} + /> + </div> + ) ) + ) : ( + <div></div> )} </div> - ); + ) } diff --git a/src/app/perfil/[id]/components/ProfileCollections.js b/src/app/perfil/[id]/components/ProfileCollections.js index 3be47b76c2da5556b5ca3a78bb1081342e2213b4..5ff3e82cb339f54e77bd876d18c91f5827ef86a4 100644 --- a/src/app/perfil/[id]/components/ProfileCollections.js +++ b/src/app/perfil/[id]/components/ProfileCollections.js @@ -13,6 +13,7 @@ import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; import EditCollectionModal from "./EditCollectionModal"; import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined'; import ShareButton from "@/app/components/ShareButton"; +import { authHeaders } from "@/app/handlers/loginHandler"; const ModalSucess = ({ open, onClose, modalOnClose }) => { return ( @@ -43,14 +44,11 @@ export default function ProfileCollections({ id, idLogin }) { const [editOpen, setEditOpen] = useState(false) const [collections, setCollections] = useState([]) const [totalCount, setTotalCount] = useState(0) - const [deleted, setDeleted] = useState(false) + const [deleted, setDeleted] = useState(false) const [modalOpen, setModalOpen] = useState(false) const [numberCards, setNumberCards] = useState(4) const [deleteOpen, setDeleteOpen] = useState(false) const [colToDelete, setColToDelete] = useState(0) - const token = getStoredValue("access_token"); - const client = getStoredValue("client"); - const uid = getStoredValue("uid"); const [got, setGot] = useState(false) const [cardsPerRow, setCardsPerRow] = useState(0); @@ -79,14 +77,8 @@ export default function ProfileCollections({ id, idLogin }) { if (idLogin === id) { await mecredApi - .get(`/users/${id}/collections?limit=${numberCards}`, { - headers: { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, - }, + .get(`api/collections/${id}/all-collections`, { + headers: authHeaders() }) /** * Além de setar as coleções, indica o número total de coleções @@ -94,21 +86,23 @@ export default function ProfileCollections({ id, idLogin }) { */ .then(({ data, headers }) => { setTotalCount(headers["x-total-count"]) - setCollections(data) + setCollections(data.fullCollections) + setGot(true) }); } else { await mecredApi - .get(`/users/${id}/collections?limit=${numberCards}`) + .get(`public/collections/${id}/collections`) .then(({ data, headers }) => { setTotalCount(headers["x-total-count"]) setCollections(data) + console.log(data) setGot(true) }); } }; fetchCollections(id); - }, [id, client, uid, token, numberCards, idLogin, deleted]); + }, [id, numberCards, idLogin, deleted]); /** * Inicialmente sempre vai aparecer 4 coleções para o usuário (se ele tiver mais que 4). @@ -122,13 +116,7 @@ export default function ProfileCollections({ id, idLogin }) { e.preventDefault(); const url = `/collections/${colToDelete}`; - const headers = { - "access-token": token, - "token-type": "Bearer", - client: client, - uid: uid, - Expires: 0, - }; + const headers = authHeaders(); try { await mecredApi.delete(url, { headers }); // Passando o objeto 'headers' corretamente @@ -187,16 +175,16 @@ export default function ProfileCollections({ id, idLogin }) { </button> )} </div> - + <ModalSucess open={modalOpen} onClose={() => setModalOpen(false)} modalOnClose={() => setDeleted(!deleted)} /> - - {collections.length === 0 ? ( + + {collections?.length === 0 ? ( <NotFound name="coleções" /> ) : ( <div className="justify-center mt-5"> - {collections.map((item, index) => ( + {collections?.map((item, index) => ( <div key={index} className="bg-white-HC-dark outline outline-1 outline-ice-HC-white mb-10 pt-6 px-4 rounded-2xl relative"> - + {/* Cabeçalho com título, autor e botões */} <div className="flex justify-between items-start"> {/* Título e autor */} @@ -205,7 +193,12 @@ export default function ProfileCollections({ id, idLogin }) { <Link href={`/colecao/${item.id}`}>{item.name}</Link> </p> <p className="ml-1 text-darkGray-HC-white-underline"> - por <Link className="hover:underline" href={`/perfil/${item.owner.id}`}>{item.owner.name}</Link> + por {item.owner?.id && ( + <Link className="hover:underline" href={`/perfil/${item.owner.id}`}> + {item.owner.name} + </Link> + )} + </p> </div> @@ -230,7 +223,7 @@ export default function ProfileCollections({ id, idLogin }) { {/* Botão de Excluir */} <button className="p-2 max-md:my-3 text-sm rounded-xl text-black-HC-white font-bold normal-case flex justify-center items-center gap-2 hover:bg-red-HC-white hover:text-white-HC-dark" - onClick={() => { setDeleteOpen(true); setColToDelete(item.id);} } + onClick={() => { setDeleteOpen(true); setColToDelete(item.id); }} aria-label="Excluir" // Texto para leitores de tela > <DeleteOutlinedIcon fontSize="small" /> {/* Ícone de lata de lixo */} @@ -242,13 +235,13 @@ export default function ProfileCollections({ id, idLogin }) { {/* Cartões de coleção abaixo */} <div className="mt-4"> - <GroupCardsCollections data={item.collection_items} cardsPerRow={cardsPerRow} /> + <GroupCardsCollections collectionId={item.id} cardsPerRow={cardsPerRow} /> </div> </div> ))} </div> )} - + {/* Botão "Ver mais" abaixo das coleções */} {numberCards < totalCount && ( <Button @@ -268,6 +261,6 @@ export default function ProfileCollections({ id, idLogin }) { )} </> ); - + } diff --git a/src/app/perfil/[id]/components/ProfileComplaints.js b/src/app/perfil/[id]/components/ProfileComplaints.js index df7bc0b3f458eb7029bf754c2228740b3fbcda40..9c60a40d7be3f34e71b739c2d9930783cae898e8 100644 --- a/src/app/perfil/[id]/components/ProfileComplaints.js +++ b/src/app/perfil/[id]/components/ProfileComplaints.js @@ -4,6 +4,7 @@ import mecredApi from "@/axiosConfig"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; import Loading from "@/app/components/Loading"; import CardsComplaints from "./CardsComplaints"; +import { authHeaders } from "@/app/handlers/loginHandler"; /** * @returns Cards dos recursos para homologação (Só aparece para curadores) @@ -25,14 +26,8 @@ export default function ProfileComplaints({ id }) { useEffect(() => { const fetchComplaints = async (id) => { await mecredApi - .get(`/learning_objects_complaints?offset=0&limit=${numberCards}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': expiry - } + .get(`api/complaint/resources`, { + headers: authHeaders() }) .then(({ data, headers }) => { setComplaints(data); @@ -57,7 +52,7 @@ export default function ProfileComplaints({ id }) { {got ? ( <Card className='p-3 my-10 rounded-md min-w-[200px] min-h-[180px] bg-white-HC-dark shadow-none '> <div className="flex content flex-wrap justify-center"> - {complaints.map((item, i) => ( + {complaints?.map((item, i) => ( i % 2 === 0 && ( <div key={i} className="flex"> {complaints[i] && <CardsComplaints item={complaints[i]} tag={true} />} diff --git a/src/app/perfil/[id]/components/ProfileHomologation.js b/src/app/perfil/[id]/components/ProfileHomologation.js index 662eb58e7ad679b91a7230d6f4b79d4e7582d44c..d7a36422821b38c73e82cd0dfc1f497c23d776b1 100644 --- a/src/app/perfil/[id]/components/ProfileHomologation.js +++ b/src/app/perfil/[id]/components/ProfileHomologation.js @@ -4,6 +4,7 @@ import mecredApi from "@/axiosConfig"; import { getStoredValue } from "@/app/handlers/localStorageHandler"; import CardsHomologation from "./CardsHomologation"; import Loading from "@/app/components/Loading"; +import { authHeaders } from "@/app/handlers/loginHandler"; /** * @returns Cards dos recursos para homologação (Só aparece para curadores) @@ -22,16 +23,11 @@ export default function ProfileHomologation({ id }) { useEffect(() => { const fetchHomologation = async (id) => { await mecredApi - .get(`/submissions/all_users_submissions/${id}?offset=${numberCards}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } + .get(`api/homologation/all`, { + headers: authHeaders() }) .then(({ data, headers }) => { + console.log(data) setHomologated(prevData => [...prevData, ...data]); setTotalCount(Number(headers["x-total-count"])) setGot(true) @@ -53,7 +49,7 @@ export default function ProfileHomologation({ id }) { {got ? ( <Card className='p-3 my-10 rounded-md min-w-[200px] min-h-[180px] bg-white-HC-dark shadow-none '> <div className="flex content flex-wrap justify-center"> - {homologated.map((item, i) => ( + {homologated?.map((item, i) => ( <CardsHomologation item={item} key={i} /> ))} </div> diff --git a/src/app/perfil/[id]/components/ProfileItens.js b/src/app/perfil/[id]/components/ProfileItens.js index d46d37faebb2683c2f6d9fccba2fced9d9521152..956b84fa6dbedacd07c35f30a23ce032a9b9a9b9 100644 --- a/src/app/perfil/[id]/components/ProfileItens.js +++ b/src/app/perfil/[id]/components/ProfileItens.js @@ -11,320 +11,346 @@ import Link from 'next/link'; import Image from 'next/image'; export default function ProfileItens({ profileData, setItems, items, store, type }) { - const [showDescription, setShowDescription] = useState(null); - const [equip, setEquip] = useState(null); - const [errorEquip, setErrorEquip] = useState(false); - const [fullEquiped, setFullEquiped] = useState(false); - const [buyItem, setBuyItem] = useState(null); - const [arrayAcquired, setArrayAcquired] = useState(new Array(store.length).fill(0)); - - const token = getStoredValue("access_token"); - const client = getStoredValue("client"); - const uid = getStoredValue("uid"); + const [showDescription, setShowDescription] = useState(null); + const [equip, setEquip] = useState(null); + const [errorEquip, setErrorEquip] = useState(false); + const [fullEquiped, setFullEquiped] = useState(false); + const [buyItem, setBuyItem] = useState(null); + const [arrayAcquired, setArrayAcquired] = useState(new Array(store.length).fill(0)); - useEffect(() => { - const handlePurchase = () => { - setArrayAcquired(prev => { - const newArray = [...prev]; - for (let i = 0; i < store.length; i++) - newArray[i] = items.some((obj) => obj.item?.id === store[i]?.id) ? 1 : 0; - return newArray; - }); - } - - handlePurchase(); - }, [items, store]); - - console.log(arrayAcquired); + const token = getStoredValue("access_token"); + const client = getStoredValue("client"); + const uid = getStoredValue("uid"); - const iconEggs = <Image - src="/gema.svg" - alt="gema icon" - width={15} - height={10} - className="inline mx-1 mb-1 invertLogo-HC-white" - /> + useEffect(() => { + const handlePurchase = () => { + setArrayAcquired(prev => { + const newArray = [...prev]; + for (let i = 0; i < store.length; i++) + newArray[i] = items.some((obj) => obj.item?.id === store[i]?.id) ? 1 : 0; + return newArray; + }); + } + handlePurchase(); + }, [items, store]); - const ModalBuyItem = ({ name, price, open, onClose, index, id }) => { - const restEggs = profileData["points"] - price; - - return ( - <Modal - open={open} - onClose={onClose} - className="grid place-items-center m-5" - slotProps={{ - backdrop: { - sx: { - backgroundColor: "rgba(0, 0, 0, 0.3)", - }, - }, - }} - > - <div className="bg-ice-HC-dark outline outline-1 outline-ice-HC-white p-5 rounded-lg"> - <div className='flex justify-end'> - <IconButton onClick={onClose} className='group hover:bg-ice-HC-white'> - <CloseIcon fontSize='large' className='text-darkGray-HC-white group-hover:text-darkGray-HC-dark' /> - </IconButton> - </div> - <div className="flex flex-col gap-5 justify-center "> - <p className="font-bold text-xl text-darkGray-HC-white">Deseja realmente comprar este item?</p> - <p className="font-bold text-darkGray-HC-white">Esta compra não envolve nenhum dinheiro real.</p> - <p className="inline text-darkGray-HC-white">O item que você deseja comprar, - <span className="font-bold"> {name}</span>, custa - <span className="font-bold text-turquoise-HC-white "> {iconEggs} {price}</span> gemas. Você possui - <span className="font-bold text-turquoise-HC-white "> {iconEggs} {profileData["points"]}</span> gemas. - </p> - {restEggs < 0 ? ( - <p className="font-bold text-darkGray-HC-white">Você não possui gemas o suficiente para comprar este item.</p> - ) : ( - <> - <p className="inline text-darkGray-HC-white">Comprar este item lhe deixará com - <span className="font-bold text-turquoise-HC-white "> {iconEggs} {restEggs} </span> - gemas. - </p> - </> - )} - </div> - <div className="flex justify-end mt-4"> - <button onClick={onClose} className="bg-ice-HC-dark p-2 rounded-lg hover:bg-ice-HC-dark-hover text-darkGray-HC-white-underline mr-1">Cancelar</button> - {restEggs >= 0 && ( - <button onClick={() => { - handlePostRequestStore(id, index); - onClose(); // Fecha o modal - }} className="bg-turquoise-HC-white text-white-HC-dark-underline hover:text-white-HC-underline p-2 rounded-lg hover:bg-darkTurquoise-HC-dark ml-4 outline outline-1 outline-ice-HC-white">Comprar</button> - )} - </div> - </div> - </Modal> - ); - } + console.log(arrayAcquired); - const ModalFullEquiped = ({ open, onClose }) => { - return ( - <Modal - open={open} - onClose={onClose} - className="grid place-items-center m-5" - slotProps={{ - backdrop: { - sx: { - backgroundColor: "rgba(0, 0, 0, 0.3)", - }, - }, - }} - > - <div className="bg-ice-HC-dark outline outline-1 outline-ice-HC-white p-5 rounded-lg"> - <div className='flex justify-end'> - <IconButton onClick={onClose} className='group hover:bg-ice-HC-white'> - <CloseIcon fontSize='large' className='text-darkGray-HC-white group-hover:text-darkGray-HC-dark' /> - </IconButton> - </div> - <div className="flex flex-col justify-center "> - <p className="pt-3 text-xl text-darkGray-HC-white">Você só pode equipar até 3 insígnias simultaneamente</p> - </div> - <div className="flex justify-end mt-4"> - <button onClick={onClose} className="bg-ice-HC-dark p-2 rounded-lg hover:bg-ice-HC-dark-hover text-darkGray-HC-white-underline mr-1">Fechar</button> - </div> - </div> - </Modal> - ) - } + const iconEggs = <Image + src="/gema.svg" + alt="gema icon" + width={15} + height={10} + className="inline mx-1 mb-1 invertLogo-HC-white" + /> - const ModalErrorEquip = ({ open, onClose }) => { - return ( - <Modal - open={open} - onClose={onClose} - className="grid place-items-center m-5" - slotProps={{ - backdrop: { - sx: { - backgroundColor: "rgba(0, 0, 0, 0.3)", - }, - }, - }} - > - <div className="outline outline-1 outline-ice-HC-white bg-ice-HC-dark p-5 rounded-lg"> - <div className="flex flex-col items-center justify-center "> - <p className="pt-3 text-xl text-darkGray-HC-white "> - Erro na comunicação com o servidor. - Por favor entre em contato com o suporte: - </p> - <a href="/contato" className="flex mt-4 w-24 bg-turquoise text-md text-white-HC-dark-underline p-2 px-6 justify-center rounded-lg hover:bg-turquoise-hover"> - Contato - </a> - </div> - <div className="flex justify-end mt-4"> - <button onClick={onClose} className="bg-ice-HC-dark p-2 rounded-lg hover:bg-ice-HC-dark-hover text-darkGray-HC-white-underline mr-1">Fechar</button> - </div> - </div> - </Modal> - ) - } - const handlePostRequestStore = async (id, index) => { - try{ - await mecredApi - .post(`/users/purchase_item`, - {"item_id": id}, - { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - }) - - - setArrayAcquired(prev => { - const newArray = [...prev]; // Cria uma cópia do array - newArray[index] = 1; - return newArray; // Retorna o novo array atualizado - }) - - await mecredApi - .get(`/users/${profileData.id}/items/?item_type=badge&limit=1000`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - }) - .then(({ data }) => { - setItems(data); - }) - .catch(() => setError(true)) + const ModalBuyItem = ({ name, price, open, onClose, index, id }) => { + const restEggs = profileData["points"] - price; + return ( + <Modal + open={open} + onClose={onClose} + className="grid place-items-center m-5" + slotProps={{ + backdrop: { + sx: { + backgroundColor: "rgba(0, 0, 0, 0.3)", + }, + }, + }} + > + <div className="bg-ice-HC-dark outline outline-1 outline-ice-HC-white p-5 rounded-lg"> + <div className='flex justify-end'> + <IconButton onClick={onClose} className='group hover:bg-ice-HC-white'> + <CloseIcon fontSize='large' className='text-darkGray-HC-white group-hover:text-darkGray-HC-dark' /> + </IconButton> + </div> + <div className="flex flex-col gap-5 justify-center "> + <p className="font-bold text-xl text-darkGray-HC-white">Deseja realmente comprar este item?</p> + <p className="font-bold text-darkGray-HC-white">Esta compra não envolve nenhum dinheiro real.</p> + <p className="inline text-darkGray-HC-white">O item que você deseja comprar, + <span className="font-bold"> {name}</span>, custa + <span className="font-bold text-turquoise-HC-white "> {iconEggs} {price}</span> gemas. Você possui + <span className="font-bold text-turquoise-HC-white "> {iconEggs} {profileData["points"]}</span> gemas. + </p> + {restEggs < 0 ? ( + <p className="font-bold text-darkGray-HC-white">Você não possui gemas o suficiente para comprar este item.</p> + ) : ( + <> + <p className="inline text-darkGray-HC-white">Comprar este item lhe deixará com + <span className="font-bold text-turquoise-HC-white "> {iconEggs} {restEggs} </span> + gemas. + </p> + </> + )} + </div> + <div className="flex justify-end mt-4"> + <button onClick={onClose} className="bg-ice-HC-dark p-2 rounded-lg hover:bg-ice-HC-dark-hover text-darkGray-HC-white-underline mr-1">Cancelar</button> + {restEggs >= 0 && ( + <button onClick={() => { + handlePostRequestStore(id, index); + onClose(); // Fecha o modal + }} className="bg-turquoise-HC-white text-white-HC-dark-underline hover:text-white-HC-underline p-2 rounded-lg hover:bg-darkTurquoise-HC-dark ml-4 outline outline-1 outline-ice-HC-white">Comprar</button> + )} + </div> + </div> + </Modal> + ); + } - } catch (error) { - setErrorEquip(true); - console.error("Erro ao fazer a requisição:", error); + const ModalFullEquiped = ({ open, onClose }) => { + return ( + <Modal + open={open} + onClose={onClose} + className="grid place-items-center m-5" + slotProps={{ + backdrop: { + sx: { + backgroundColor: "rgba(0, 0, 0, 0.3)", + }, + }, + }} + > + <div className="bg-ice-HC-dark outline outline-1 outline-ice-HC-white p-5 rounded-lg"> + <div className='flex justify-end'> + <IconButton onClick={onClose} className='group hover:bg-ice-HC-white'> + <CloseIcon fontSize='large' className='text-darkGray-HC-white group-hover:text-darkGray-HC-dark' /> + </IconButton> + </div> + <div className="flex flex-col justify-center "> + <p className="pt-3 text-xl text-darkGray-HC-white">Você só pode equipar até 3 insígnias simultaneamente</p> + </div> + <div className="flex justify-end mt-4"> + <button onClick={onClose} className="bg-ice-HC-dark p-2 rounded-lg hover:bg-ice-HC-dark-hover text-darkGray-HC-white-underline mr-1">Fechar</button> + </div> + </div> + </Modal> + ) + } + + const ModalErrorEquip = ({ open, onClose }) => { + return ( + <Modal + open={open} + onClose={onClose} + className="grid place-items-center m-5" + slotProps={{ + backdrop: { + sx: { + backgroundColor: "rgba(0, 0, 0, 0.3)", + }, + }, + }} + > + <div className="outline outline-1 outline-ice-HC-white bg-ice-HC-dark p-5 rounded-lg"> + <div className="flex flex-col items-center justify-center "> + <p className="pt-3 text-xl text-darkGray-HC-white "> + Erro na comunicação com o servidor. + Por favor entre em contato com o suporte: + </p> + <a href="/contato" className="flex mt-4 w-24 bg-turquoise text-md text-white-HC-dark-underline p-2 px-6 justify-center rounded-lg hover:bg-turquoise-hover"> + Contato + </a> + </div> + <div className="flex justify-end mt-4"> + <button onClick={onClose} className="bg-ice-HC-dark p-2 rounded-lg hover:bg-ice-HC-dark-hover text-darkGray-HC-white-underline mr-1">Fechar</button> + </div> + </div> + </Modal> + ) + } + + const handlePostRequestStore = async (id, index) => { + try { + await mecredApi + .post(`/users/purchase_item`, + { "item_id": id }, + { + headers: { + 'access-token': token, + 'token-type': 'Bearer', + 'client': client, + 'uid': uid, + 'Expires': 0 } + }) + + + setArrayAcquired(prev => { + const newArray = [...prev]; // Cria uma cópia do array + newArray[index] = 1; + return newArray; // Retorna o novo array atualizado + }) + + await mecredApi + .get(`/users/${profileData.id}/items/?item_type=badge&limit=1000`, { + headers: { + 'access-token': token, + 'token-type': 'Bearer', + 'client': client, + 'uid': uid, + 'Expires': 0 + } + }) + .then(({ data }) => { + setItems(data); + }) + .catch(() => setError(true)) + + + } catch (error) { + setErrorEquip(true); + console.error("Erro ao fazer a requisição:", error); } + } - {/* + {/* id: id do item a ser alterado url: É a variação se vai equipar ou desequipar tal item index: A posição do item na lista de itens do json */} - const handlePostRequestItem = async (id, url, index) => { + const handlePostRequestItem = async (id, url, index) => { - const result = items.filter((item) => item.being_used === true); + const result = items.filter((item) => item.being_used === true); - if (result.length === 3 && url === "equip_item" ) { - setFullEquiped(true); - return; - } - - items[index].being_used = !items[index].being_used; - setItems([...items]); - - console.log(profileData["user_items"]); + if (result.length === 3 && url === "equip_item") { + setFullEquiped(true); + return; + } + + items[index].being_used = !items[index].being_used; + setItems([...items]); - try{ - await mecredApi - .post(`/users/${url}`, - {"item_id": id}, - { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } - }) - } catch (error) { - setErrorEquip(true); - console.error("Erro ao fazer a requisição:", error); - } + console.log(profileData["user_items"]); + try { + await mecredApi + .post(`/users/${url}`, + { "item_id": id }, + { + headers: { + 'access-token': token, + 'token-type': 'Bearer', + 'client': client, + 'uid': uid, + 'Expires': 0 + } + }) + } catch (error) { + setErrorEquip(true); + console.error("Erro ao fazer a requisição:", error); } - - return ( - <> - <ModalErrorEquip open={errorEquip} onClose={() => setErrorEquip(false)} /> - <ModalFullEquiped open={fullEquiped} onClose={() => setFullEquiped(false)} /> - {/* Cards de itens do usuário*/} - {(type === "item" ? items : store)?.map((e, index) => { - - return ( - <div key={index} className="relative flex flex-c bg-ice-HC-dark w-[250px] h-[370px] justify-center outline outline-1 outline-ice-HC-white rounded-2xl m-2 text-center"> - {/* Parte de trás (detalhes) */} - {showDescription == index && ( - <div className="absolute inset-0 flex flex-col gap-5 text-[100%] text-darkGray-HC-white bg-ice-HC-dark bg-opacity-90 p-6 rounded-2xl pt-8 z-10 text-left"> - <div className="h-[270px] flex flex-col gap-6"> - <p className="font-bold">{e.item?.name || e.name}</p> - <p className="font-light overflow-y-auto scrollbar-none">{e.item?.description || e.description}</p> - </div> - - <button - className="absolute bottom-0 pb-8 text-turquoise-HC-white-underline hover:text-darkTurquoise-HC-white text-left" - onClick={() => setShowDescription(null)} - > - Voltar - </button> - </div> - )} + } - <div className="relative flex flex-col text-xs pt-8" > - <div className="flex justify-center items-center text-darkGray-HC-white-underline pb-4"> - <Avatar - alt={e.item?.name || e.name} - src={mecredURL + (e.item?.image || e.image)} - sx={{ width: 145, height: 145 }} - /> - </div> - <div className="flex flex-col justify-center text-base items-center"> - {(e.item === undefined) ? ( - <> - <h1 className="flex text-lg text-darkGray-HC-white text-[100%] font-bold px-6 items-center min-h-[40px]"> - {e.item?.name || e.name} - </h1> - <button className="text-turquoise-HC-white-underline hover:text-darkTurquoise-HC-white pb-2" onClick={() => setShowDescription(index)}>Ver mais</button> - <div className='flex flex-wrap gap-x-4'> - <h1 className='flex text-darkGray-HC-white font-bold gap-x-1'>{iconEggs}{e.price}</h1> - </div> - <ModalBuyItem - name={e.name} - price={e.price} - open={buyItem === e.id} - onClose={() => setBuyItem(null)} - index={index} - id={e.id} - /> - <button className="flex h-[43px] w-[158px] justify-center items-center bg-lightGray-HC-dark hover:bg-darkGray-HC-white rounded-[10px] outline outline-1 outline-ice-HC-white font-bold text-darkGray-HC-white-underline hover:text-white-HC-dark-underline mt-2" - onClick={() => !arrayAcquired[index] && setBuyItem(e.id)} - > - {arrayAcquired[index] ? "Adquirido" : "Comprar"} - </button> - </> - ) : ( - <> - <h1 className="flex text-lg text-darkGray-HC-white text-[100%] font-bold px-6 items-center min-h-[60px]"> - {e.item?.name || e.name} - </h1> - <button className="text-turquoise-HC-white-underline hover:text-darkTurquoise-HC-white" onClick={() => setShowDescription(index)}>Ver mais</button> - <button className="flex h-[43px] w-[158px] justify-center items-center bg-lightGray-HC-dark hover:bg-darkGray-HC-white rounded-[10px] outline outline-1 outline-ice-HC-white font-bold text-darkGray-HC-white hover:text-white-HC-dark-underline mt-4" - onClick={() => handlePostRequestItem(e.item?.id || null, e.being_used ? "unequip_item" : "equip_item", index)} - > - {e.being_used ? "Desequipar" : "Equipar"} - </button> - </> - )} - - </div> - </div> - </div> - ); - })} - </> - ); -} + return ( + <> + <ModalErrorEquip open={errorEquip} onClose={() => setErrorEquip(false)} /> + <ModalFullEquiped open={fullEquiped} onClose={() => setFullEquiped(false)} /> + {/* Cards de itens do usuário */} + {(type === "item" ? items : store)?.length > 0 ? ( + (type === "item" ? items : store).map((e, index) => { + return ( + <div + key={index} + className="relative flex flex-c bg-ice-HC-dark w-[250px] h-[370px] justify-center outline outline-1 outline-ice-HC-white rounded-2xl m-2 text-center" + > + {/* Parte de trás (detalhes) */} + {showDescription == index && ( + <div className="absolute inset-0 flex flex-col gap-5 text-[100%] text-darkGray-HC-white bg-ice-HC-dark bg-opacity-90 p-6 rounded-2xl pt-8 z-10 text-left"> + <div className="h-[270px] flex flex-col gap-6"> + <p className="font-bold">{e.item?.name || e.name}</p> + <p className="font-light overflow-y-auto scrollbar-none"> + {e.item?.description || e.description} + </p> + </div> + <button + className="absolute bottom-0 pb-8 text-turquoise-HC-white-underline hover:text-darkTurquoise-HC-white text-left" + onClick={() => setShowDescription(null)} + > + Voltar + </button> + </div> + )} + + <div className="relative flex flex-col text-xs pt-8"> + <div className="flex justify-center items-center text-darkGray-HC-white-underline pb-4"> + <Avatar + alt={e.item?.name || e.name} + src={mecredURL + (e.item?.image || e.image)} + sx={{ width: 145, height: 145 }} + /> + </div> + <div className="flex flex-col justify-center text-base items-center"> + {e.item === undefined ? ( + <> + <h1 className="flex text-lg text-darkGray-HC-white text-[100%] font-bold px-6 items-center min-h-[40px]"> + {e.item?.name || e.name} + </h1> + <button + className="text-turquoise-HC-white-underline hover:text-darkTurquoise-HC-white pb-2" + onClick={() => setShowDescription(index)} + > + Ver mais + </button> + <div className="flex flex-wrap gap-x-4"> + <h1 className="flex text-darkGray-HC-white font-bold gap-x-1"> + {iconEggs} + {e.price} + </h1> + </div> + <ModalBuyItem + name={e.name} + price={e.price} + open={buyItem === e.id} + onClose={() => setBuyItem(null)} + index={index} + id={e.id} + /> + <button + className="flex h-[43px] w-[158px] justify-center items-center bg-lightGray-HC-dark hover:bg-darkGray-HC-white rounded-[10px] outline outline-1 outline-ice-HC-white font-bold text-darkGray-HC-white-underline hover:text-white-HC-dark-underline mt-2" + onClick={() => + !arrayAcquired[index] && setBuyItem(e.id) + } + > + {arrayAcquired[index] ? "Adquirido" : "Comprar"} + </button> + </> + ) : ( + <> + <h1 className="flex text-lg text-darkGray-HC-white text-[100%] font-bold px-6 items-center min-h-[60px]"> + {e.item?.name || e.name} + </h1> + <button + className="text-turquoise-HC-white-underline hover:text-darkTurquoise-HC-white" + onClick={() => setShowDescription(index)} + > + Ver mais + </button> + <button + className="flex h-[43px] w-[158px] justify-center items-center bg-lightGray-HC-dark hover:bg-darkGray-HC-white rounded-[10px] outline outline-1 outline-ice-HC-white font-bold text-darkGray-HC-white hover:text-white-HC-dark-underline mt-4" + onClick={() => + handlePostRequestItem( + e.item?.id || null, + e.being_used ? "unequip_item" : "equip_item", + index + ) + } + > + {e.being_used ? "Desequipar" : "Equipar"} + </button> + </> + )} + </div> + </div> + </div> + ); + }) + ) : <div></div>} + </> + ); +} \ No newline at end of file diff --git a/src/app/perfil/[id]/components/ProfileResources.js b/src/app/perfil/[id]/components/ProfileResources.js index 1450300d12340911792cdd095b9e30566c9246f0..e5098627e4bf94182552edfbdde49e5d0c6e1e9d 100644 --- a/src/app/perfil/[id]/components/ProfileResources.js +++ b/src/app/perfil/[id]/components/ProfileResources.js @@ -6,6 +6,7 @@ import { getStoredValue } from "@/app/handlers/localStorageHandler"; import { Button, Card } from "@mui/material"; import NotFound from "./NotFound"; import Loading from "@/app/components/Loading"; +import { authHeaders } from "@/app/handlers/loginHandler"; /** * @returns Recursos do usuário @@ -19,10 +20,6 @@ export default function ProfileResources({ id, idLogin }) { const [uniqueResources, setUniqueResources] = useState([]) const [resources, setResources] = useState([]) const [homologaResources, setHomologaResources] = useState([]) - const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") - const expiry = getStoredValue("expiry") const [numberCards, setNumberCards] = useState(0) const [resourcesCount, setResourcesCount] = useState(0) const [homologaCount, setHomologaCount] = useState(0) @@ -32,14 +29,8 @@ export default function ProfileResources({ id, idLogin }) { useEffect(() => { const fetchLearningObjects = async (id) => { await mecredApi - .get(`/users/${id}/learning_objects?offset=${numberCards}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': expiry - } + .get(`public/resource/allResourceByUser/${id}?offset=${numberCards}`, { + headers: authHeaders() }) .then(({ data, headers }) => { setResourcesCount(Number(headers["x-total-count"])); @@ -56,13 +47,7 @@ export default function ProfileResources({ id, idLogin }) { const fetchSubmissions = async (id) => { await mecredApi .get(`/submissions/user_submissions/${id}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': expiry - } + headers: authHeaders() }) .then(({ data }) => { setHomologaResources((prevHomologaResources) => [...prevHomologaResources, ...data]); @@ -78,7 +63,7 @@ export default function ProfileResources({ id, idLogin }) { //só aparece os recursos em homologação se o perfil acessado for o mesmo do logado if (idLogin === id) fetchSubmissions(id); - }, [id, numberCards, token, client, uid, expiry, idLogin]); + }, [id, numberCards, idLogin]); const toggleContent = () => { setNumberCards(numberCards + 12) @@ -104,7 +89,42 @@ export default function ProfileResources({ id, idLogin }) { }, [resources, homologaResources]); + const [imageMap, setImageMap] = useState({}); + const verifyImage = async (id) => { + try { + await mecredApi.get(`public/s3/get/thumbnail/resource/${id}`, { + headers: authHeaders() + }); + return true; // Existe + } catch (error) { + if (error.response && error.response.status === 404) { + return false; // Não existe + } + return false; + } + }; + + useEffect(() => { + const checkImages = async () => { + const map = {}; + + await Promise.all( + resources.map(async (resource) => { + const exists = await verifyImage(resource.id); + map[resource.id] = exists; + }) + ); + + setImageMap(map); + }; + + if (resources.length) { + checkImages(); + } + }, [resources]); + + return ( <> {got ? ( @@ -136,12 +156,34 @@ export default function ProfileResources({ id, idLogin }) { <Cards id={resource.learning_object?.id || resource?.id} key={index} - title={resource?.name || resource.learning_object?.name} - author={resource.publisher?.name || resource.learning_object?.author} - avatar={resource.publisher?.avatar || resource.submitter?.avatar} - image={resource?.thumbnail || resource.learning_object?.thumbnail} - updated_at={resource?.updated_at || resource.learning_object?.updated_at} - homologa={resource?.status} + title={resource.name} + author={resource.author} agora a api retorna + avatar={`https://s3.c3sl.ufpr.br/mecredteste/avatar/${id}`} + image={ + imageMap[resource.id] + ? `https://s3.c3sl.ufpr.br/mecredteste/thumbnail/resource/${resource.id}` + : null + } + + type={resource.objectTypeName} + updated_at={resource.updated_at} + /> + ))} + {homologaResources.map((resource, index) => ( + <Cards + id={resource.id} + key={index} + title={resource.name} + author={resource.author} + avatar={`https://s3.c3sl.ufpr.br/mecredteste/avatar/${id}`} + image={ + imageMap[resource.id] + ? `https://s3.c3sl.ufpr.br/mecredteste/thumbnail/resource/${resource.id}` + : null + } + type={resource.objectTypeName} + updated_at={resource.updated_at} + homologa={resource.status} /> ))} </div> diff --git a/src/app/perfil/[id]/components/Stats.js b/src/app/perfil/[id]/components/Stats.js index 38bc6a5f8656b76c27da6ed936fbda9f48dd643c..3975f77ba6074840fa9ba268eb086de2f02b58f8 100644 --- a/src/app/perfil/[id]/components/Stats.js +++ b/src/app/perfil/[id]/components/Stats.js @@ -26,12 +26,12 @@ export default function ProfileStats({ profileData, achievements, progresses, it value: achievements?.length, src: "/conquistas.svg" }, - { - icon: <RotateRightTwoToneIcon fontSize="large"/>, - name: "Progresso:", - value: progresses?.length, - src: "/progressos.svg" - }, + // { + // icon: <RotateRightTwoToneIcon fontSize="large"/>, + // name: "Progresso:", + // value: progresses?.length, + // src: "/progressos.svg" + // }, { icon: <BusinessCenterTwoToneIcon fontSize="large"/>, name: "Itens:", @@ -57,7 +57,11 @@ export default function ProfileStats({ profileData, achievements, progresses, it alt={item.name} /> - <h1 className="flex">{item.name} {item.value}</h1> + <h1 className="flex">{item.name} + {item.value? + item.value : 0 + } + </h1> </div> ))} </div> diff --git a/src/app/perfil/[id]/components/UserCard.js b/src/app/perfil/[id]/components/UserCard.js index 818f73f534960ff3438d852a1ac17bb0eac26f7c..6780f3ee9c7577d4039830331ae8806028849b6f 100644 --- a/src/app/perfil/[id]/components/UserCard.js +++ b/src/app/perfil/[id]/components/UserCard.js @@ -7,7 +7,7 @@ import { Avatar } from '@mui/material'; import { useEffect, useState } from 'react'; import { getStoredValue } from '@/app/handlers/localStorageHandler'; import mecredApi, { mecredURL } from '@/axiosConfig'; -import { isLoggedIn } from '@/app/handlers/loginHandler'; +import { authHeaders, isLoggedIn, userData } from '@/app/handlers/loginHandler'; import Stats from './Stats'; import MedalAchievements from './MedalAchievements'; import AboutCard from "./AboutCard"; @@ -19,7 +19,6 @@ import FollowersCards from "./FollowersCards"; import ProfileComplaints from "./ProfileComplaints"; import ProfileAchievementsMenu from "./ProfileAchievementsMenu"; import { Person } from "@mui/icons-material"; -import { TramSharp } from '@mui/icons-material'; /* Não precisa mais com o Verificado const roles = [ @@ -108,6 +107,7 @@ export default function UserCard({ profileData, idLogin, achievements, progresse const [userVerified, setUserVerified] = useState(false) const [medalActive, setMedalActive] = useState(0) + const [profileInfo, setProfileInfo] = useState("") /** * faz fetch dos seguidores e seguindo, se não estiver logado não aparece essa informação @@ -115,35 +115,19 @@ export default function UserCard({ profileData, idLogin, achievements, progresse useEffect(() => { if (!isLoggedIn) return; + setProfileInfo(userData()["user"]) + console.log(profileData) const fetchFollowers = async () => { - const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") - const expiry = getStoredValue("expiry") - - await mecredApi.get('/users/' + profileData["id"] + "/followers", { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': expiry - } - + await mecredApi.get(`public/user/followers/${profileData.id}`, { + headers: authHeaders() }) .then(({ headers }) => setFollowers(Number(headers["x-total-count"]))) .catch((error) => { console.error(error) }) - await mecredApi.get('/users/' + profileData["id"] + "/following/User", { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': expiry - } + await mecredApi.get(`public/user/follows/${profileData.id}`, { + headers: authHeaders() }) .then(({ headers }) => { @@ -155,8 +139,8 @@ export default function UserCard({ profileData, idLogin, achievements, progresse } //Conta quantas medalhas ativas o usuário possui - const countMedalBeingUsed = items?.filter(item => item.being_used).length; - setMedalActive(countMedalBeingUsed) + // const countMedalBeingUsed = items?.filter(item => item.being_used).length; + // setMedalActive(countMedalBeingUsed) fetchFollowers() // Função que análisa se o usuário é considerado "verificado" conforme cargo @@ -178,28 +162,7 @@ export default function UserCard({ profileData, idLogin, achievements, progresse }; verifier() - /** - * Função que faz a tradução conforme os cargos do usuário. - * Busca em `roles` qual respectiva tradução no array. - * A função trata cargos repetidos e, como "submitter" é um cargo de todos os usuários, é retirado da lista. - * Função serve também para verificar se o usuário (no caso, o usuário logado) é curador, para ter permissão de homologação - - NÃO PRECISA MAIS DEVIDO AO VERIFICADO - const itemsRoles = async () => { - let items = [] - for (let i = 0; i < profileData["roles"].length; i++) { - let found = roles.find((element) => profileData["roles"][i]["name"] === element.role) - - if (!items.includes(found.translate) && found.role !== "submitter") items.push(found.translate) - } - - setVerifyCurator(items.includes("Curador")) - return items.join(' | '); - } - itemsRoles() - .then(roles => setTranslateItems(roles)) - */ }, [items, profileData]) @@ -207,54 +170,68 @@ export default function UserCard({ profileData, idLogin, achievements, progresse * Menu de seleção do usuário * Verifica se o usuário está logado para definir as opções */ - let options = [{ name: "Sobre", component: <AboutCard content={profileData["description"]} /> }] - - if (isLoggedIn() && profileData["id"] == idLogin) { + let options = [{ name: "Sobre", component: <AboutCard content={profileData.description} /> }] + if (profileData.id == profileInfo.id) { options.push({ name: "Conquistas", component: <ProfileAchievementsMenu profileData={profileData} achievements={achievements} progresses={progresses} setItems={setItems} items={items} store={store} /> }, - { name: "Meus Recursos", component: <ProfileResources id={profileData["id"]} idLogin={idLogin} /> }, - { name: "Minhas Coleções", component: <ProfileCollections id={profileData["id"]} idLogin={idLogin} /> }, - { name: "Seguidores", component: <FollowersCards id={profileData["id"]} count={followers} /> }, - { name: "Seguindo", component: <FollowingCards id={profileData["id"]} count={following} /> }, + { name: "Meus Recursos", component: <ProfileResources id={profileData.id} idLogin={idLogin} /> }, + { name: "Minhas Coleções", component: <ProfileCollections id={profileData.id} idLogin={idLogin} /> }, + { name: "Seguidores", component: <FollowersCards id={profileData.id} count={followers} /> }, + { name: "Seguindo", component: <FollowingCards id={profileData.id} count={following} /> }, ) if (userVerified) { options.push( - { name: "Homologação", component: <ProfileHomologation id={profileData["id"]} /> }, - { name: "Denúncias", component: <ProfileComplaints id={profileData["id"]} /> } + { name: "Homologação", component: <ProfileHomologation id={profileData.id} /> }, + { name: "Denúncias", component: <ProfileComplaints id={profileData.id} /> } ) } } - else if (profileData["id"] == 0) { + else if (profileData.id == 0) { options.push( - { name: "Recursos", component: <ProfileResources id={profileData["id"]} idLogin={idLogin} /> }, - { name: "Coleções", component: <ProfileCollections id={profileData["id"]} idLogin={idLogin} /> }, + { name: "Recursos", component: <ProfileResources id={profileData.id} idLogin={idLogin} /> }, + { name: "Coleções", component: <ProfileCollections id={profileData.id} idLogin={idLogin} /> }, ) } else { options.push( - { name: "Recursos", component: <ProfileResources id={profileData["id"]} idLogin={idLogin} /> }, - { name: "Coleções", component: <ProfileCollections id={profileData["id"]} idLogin={idLogin} /> }, - { name: "Seguidores", component: <FollowersCards id={profileData["id"]} count={followers} /> }, - { name: "Seguindo", component: <FollowingCards id={profileData["id"]} count={following} /> }, + { name: "Recursos", component: <ProfileResources id={profileData.id} idLogin={idLogin} /> }, + { name: "Coleções", component: <ProfileCollections id={profileData.id} idLogin={idLogin} /> }, + { name: "Seguidores", component: <FollowersCards id={profileData.id} count={followers} /> }, + { name: "Seguindo", component: <FollowingCards id={profileData.id} count={following} /> }, ) } - // const cargo = + const [imageExists, setImageExists] = useState(false); + const imageUrl = `https://s3.c3sl.ufpr.br/mecredteste/avatar/${profileData.id}`; + useEffect(() => { + const checkImage = async () => { + await mecredApi.get(`public/s3/get/avatar/${profileData.id}`, { + headers: authHeaders() + }) + .then(({ headers }) => setImageExists(true)) + .catch((error) => { + setImageExists(false) + }) + }; + + checkImage(); + }, [profileData.id]); + return ( <div className='overflow-y-auto min-h-dvh max-md:mx-[20px] max-md:mb-24 '> <div className='flex flex-col'> <div className='flex max-md:mx-1 mx-0.5 mt-2 max-lg:flex-col rounded-2xl gap-4 max-sm:gap-0 max-lg:items-center bg-white-HC-dark outline outline-1 outline-ice-HC-white' > <div className='p-10 max-sm:p-0 h-full items-center'> - {/*a imagem do usuário tem nomes diferentes no backend se for usuário público ou não */} - {profileData["avatar"] ? - <Avatar src={mecredURL + profileData["avatar"]} sx={{ position: "inherit" }} alt="Foto de perfil" className=" h-[276px] w-[276px] " /> + {imageExists ? + <Avatar src={imageUrl} sx={{ position: "inherit" }} alt="Foto de perfil" className=" h-[276px] w-[276px] " /> : - <div className={`flex items-center justify-center text-8xl font-bold text-ice-HC-dark rounded-full h-[276px] w-[276px] bg-turquoise-HC-white ${getRandomBg(profileData["id"])}`} >{profileData["name"][0]}</div> + <div className={`flex items-center justify-center text-8xl font-bold text-ice-HC-dark rounded-full h-[276px] w-[276px] bg-turquoise-HC-white ${getRandomBg(profileData["id"])}`} >{profileData.name[0]}</div> } + </div> <div className='flex flex-col pt-12 max-lg:pt-2 pb-6 justify-between w-full '> @@ -294,11 +271,12 @@ export default function UserCard({ profileData, idLogin, achievements, progresse </div> {/*Botões de editar perfil e compartilhar */} - <GroupButton profileData={profileData} idLogin={idLogin} /> + <GroupButton profileData={profileData} idLogin={profileInfo.id} /> </div> </div> {/* Stats do usuário*/} + {/* Não há um funcionamento definido, portanto, colocar depois com as rotas estabelecidas */} <Stats profileData={profileData} achievements={achievements} progresses={progresses} items={items} /> @@ -311,7 +289,7 @@ export default function UserCard({ profileData, idLogin, achievements, progresse content={profileData["description"]} optButton={optButton} id={profileData["id"]} - idLogin={idLogin} + idLogin={profileInfo.id} followersCount={followers} followingCount={following} achievements={achievements} diff --git a/src/app/perfil/[id]/page.js b/src/app/perfil/[id]/page.js index 431cb8d6a3e60ae5b2062f55ad00f986ecc779e0..95cd964f7a7b7f1e8d94e7f185488dd99f06ad7c 100644 --- a/src/app/perfil/[id]/page.js +++ b/src/app/perfil/[id]/page.js @@ -4,7 +4,7 @@ import { getStoredValue } from "../../handlers/localStorageHandler"; import { useEffect, useState } from "react"; import Overlay from "../../components/Overlay"; import mecredApi from "@/axiosConfig"; -import { isLoggedIn } from "@/app/handlers/loginHandler"; +import { authHeaders, isLoggedIn, userData } from "@/app/handlers/loginHandler"; import ErrorComponent from "@/app/components/ErrorComponent"; export default function Perfil({ params }) { @@ -15,9 +15,7 @@ export default function Perfil({ params }) { const [progresses, setProgresses] = useState(null); const [error, setError] = useState(false) const [idLogin, setIdLogin] = useState(0) - const token = getStoredValue("access_token") - const client = getStoredValue("client") - const uid = getStoredValue("uid") + const optTab = getStoredValue("tab"); @@ -33,7 +31,7 @@ export default function Perfil({ params }) { */ const fetchAchievements = async (id) => { await mecredApi - .get(`/unlocked_achievements/user/${id}?limit=1000`) + .get(`public/userAchievements/${id}/achievements`) .then(({ data }) => { setAchievements(data); }) @@ -42,20 +40,20 @@ export default function Perfil({ params }) { fetchAchievements(params.id); - const fetchProgresses = async (id) => { - await mecredApi - .get(`/user_progresses/${id}`) - .then(({ data }) => { - setProgresses(data); - }) - .catch(() => setError(true)) - } + // const fetchProgresses = async (id) => { + // await mecredApi + // .get(`/user_progresses/${id}`) + // .then(({ data }) => { + // setProgresses(data); + // }) + // .catch(() => setError(true)) + // } - fetchProgresses(params.id) + // fetchProgresses(params.id) const fetchItems = async (id) => { await mecredApi - .get(`/users/${id}/items/?item_type=badge&limit=1000`) + .get(`public/user-items/${id}/items?limit=1000`) .then(({ data }) => { setItems(data); }) @@ -65,44 +63,39 @@ export default function Perfil({ params }) { fetchItems(params.id) if (isLoggedIn()) { - let data = getStoredValue("user_data") - let dataJson = JSON.parse(data); + let data = userData() const fetchUser = async (id) => { await mecredApi - .get(`/users/${id}`, { - headers: { - 'access-token': token, - 'token-type': 'Bearer', - 'client': client, - 'uid': uid, - 'Expires': 0 - } + .get(`api/user/${id}`, { + headers: authHeaders() }) .then(({ data }) => { + console.log(data) setProfileData(data); }) .catch(() => setError(true)) } fetchUser(params.id) - setIdLogin(dataJson["id"]) + setIdLogin(data["user"]["id"]) - const fetchStore = async () => { + const fetchStore = async (id) => { await mecredApi - .get(`/items?filter={"state" : "active"}&item_type=badge&unlock_rule=purchase&limit=1000`) + .get(`public/user-items/${id}/items?filter={"state" : "active"}&item_type=badge&unlock_rule=purchase&limit=1000`) .then(({ data }) => { setStore(data) + console.log(data) }) .catch(() => setError(true)) } - fetchStore() + fetchStore(params.id) } else { const fetchUser = async (id) => { await mecredApi - .get(`/users/${id}`) + .get(`api/user/${id}`) .then(({ data }) => { setProfileData(data); }) @@ -112,7 +105,7 @@ export default function Perfil({ params }) { fetchUser(params.id) } - }, [params.id, client, token, uid]) + }, [params]) return ( <> diff --git a/src/app/recurso/[id]/components/actionButtons.js b/src/app/recurso/[id]/components/actionButtons.js index 342017b7e4e3d169bfc4323579e8052593a41991..1f5da660b33fc2a6f49708b2cf7f0984f8255c92 100644 --- a/src/app/recurso/[id]/components/actionButtons.js +++ b/src/app/recurso/[id]/components/actionButtons.js @@ -195,7 +195,7 @@ export default function ActionButtons({ learningObject, setNeedLoginOpen, state {/* Verifica se o usuário está logado antes de abrir o modal de colecionar */} {userData && <CollectModal open={collectOpen} onClose={() => setCollectOpen(false)} idLogin={userData["id"]} resourceId={learningObject.id} />} {!submitted ? - <div className="flex justify-start py-4 max-sm:no-scrollbar max-sm:overflow-x-auto animate-scrollHint"> + <div className="flex justify-start py-4 max-sm:no-scrollbar overflow-x-auto animate-scrollHint"> {buttonInfo.map(genButton)} </div> : diff --git a/src/axiosConfig.js b/src/axiosConfig.js index 9be313ece58b962894093d7e475408707efa3647..080e28fb611761743ba2eaa5cea206612c59597d 100644 --- a/src/axiosConfig.js +++ b/src/axiosConfig.js @@ -3,8 +3,8 @@ import { saveToLocalStorage, } from "./app/handlers/localStorageHandler"; -export const s3URL = "https://s3.c3sl.ufpr.br/mecredteste/"; -export const mecredURLv1 = "https://api.mecred.c3sl.ufpr.br/v1"; +export const mecredURL = "http://localhost:3000"; +export const mecredURLv1 = "http://localhost:3000"; const wrapper = (method) => { return (...args) => {