From 980d09b0d264284c63db83e5df41a06c88d80219 Mon Sep 17 00:00:00 2001 From: Taranpreet Kaur <141022139+Taranpreet10451@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:25:51 +0530 Subject: [PATCH 1/5] Adding Public Review Completed the task. --- server/controllers/canteenController.js | 80 ++++++++++ server/models/feedback.js | 12 ++ server/routes/canteen.js | 3 +- src/App.css | 49 ++++++ src/components/Feedback.jsx | 49 ++++++ src/pages/Home.jsx | 10 ++ src/pages/MenuPage.jsx | 202 +++++++++++++++++++----- 7 files changed, 368 insertions(+), 37 deletions(-) create mode 100644 server/models/feedback.js create mode 100644 src/components/Feedback.jsx diff --git a/server/controllers/canteenController.js b/server/controllers/canteenController.js index e36b07c..793f7ab 100644 --- a/server/controllers/canteenController.js +++ b/server/controllers/canteenController.js @@ -3,6 +3,11 @@ const Breakfast = require('../models/breakfast'); const Lunch = require('../models/lunch'); const Dinner = require('../models/dinner'); const Canteen = require("../models/canteenLoginInfo"); +<<<<<<< Updated upstream +======= +const Feedback = require("../models/feedback") +const Session = require("../models/session") +>>>>>>> Stashed changes const { uploader } = require('../config/cloudinaryConfig'); @@ -43,6 +48,76 @@ const getBreakfast = async(req , res , next) =>{ res.status(500).json({success : false , error : error}); } } +const feedback = async (req, res) => { + const { canteenId, feedback, rating } = req.body; + const token = req.body.studentId; // This is the token + + try { + // Find the session with the given token + const session = await Session.findOne({ token }); + + if (!session) { + return res.status(404).json({ message: 'Session not found' }); + } + + const userId = session.userId; // Extract userId from the session + + const newFeedback = new Feedback({ + canteen: canteenId, + student: userId, + comment: feedback, + rating: rating, + }); + + const savedFeedback = await newFeedback.save(); + res.status(201).json(savedFeedback); + } catch (error) { + res.status(500).json({ message: 'Error saving feedback', error: error.message }); + } +}; +const canteenFeedbackRender = async (req, res) => { + try { + const reviews = await Feedback.aggregate([ + { $sample: { size: 3 } }, // Fetch 3 random feedback entries + { + $lookup: { + from: 'students', // Collection name for students + localField: 'student', + foreignField: '_id', + as: 'studentInfo' + } + }, + { + $lookup: { + from: 'canteens', // Collection name for canteens + localField: 'canteen', + foreignField: '_id', + as: 'canteenInfo' + } + }, + { + $addFields: { + studentName: { $arrayElemAt: ['$studentInfo.name', 0] }, + canteenName: { $arrayElemAt: ['$canteenInfo.name', 0] } + } + }, + { + $project: { + _id: 1, + comment: 1, + rating: 1, + createdAt: 1, + studentName: 1, + canteenName: 1 + } + } + ]); + + res.json(reviews); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; const getLunch = async(req , res , next) =>{ @@ -297,4 +372,9 @@ module.exports = { updateBreakfastDish, updateLunchDish, updateDinnerDish, +<<<<<<< Updated upstream +======= + feedback, + canteenFeedbackRender +>>>>>>> Stashed changes }; diff --git a/server/models/feedback.js b/server/models/feedback.js new file mode 100644 index 0000000..d30298a --- /dev/null +++ b/server/models/feedback.js @@ -0,0 +1,12 @@ +const mongoose = require('mongoose'); + +const feedbackSchema = new mongoose.Schema({ + student: { type: mongoose.Schema.Types.ObjectId, ref: 'Student' }, + canteen: { type: mongoose.Schema.Types.ObjectId, ref: 'Canteen' }, + comment: String, + rating: Number, + createdAt: { type: Date, default: Date.now } +}); + +const Feedback = mongoose.model('Feedback', feedbackSchema); +module.exports = Feedback; diff --git a/server/routes/canteen.js b/server/routes/canteen.js index 83e6242..75097b3 100644 --- a/server/routes/canteen.js +++ b/server/routes/canteen.js @@ -7,7 +7,8 @@ const { auth, isCanteen } = require('../middlewares/auth'); const multerUploads = require('../middleware/multer.middleware'); router.get('/getcanteen' , canteenController.getAllCanteen); - +router.post("/feedback", canteenController.feedback) +router.get("/reviews", canteenController.canteenFeedbackRender) //yeh mere routes router.get('/:id/breakfast' , canteenController.getBreakfast); diff --git a/src/App.css b/src/App.css index 3464378..95be599 100644 --- a/src/App.css +++ b/src/App.css @@ -42,4 +42,53 @@ li:hover span { .nav-item{ font-size: 52px !important; +<<<<<<< Updated upstream +======= +} + +.star-rating { + display: flex; + flex-direction: row; +} + +.star { + font-size: 2rem; + color: #d3d3d3; + background: none; + border: none; + cursor: pointer; + transition: color 0.2s; +} + +.star.on { + color: #ffc107; +} + +.star.off { + color: #d3d3d3; +} +.reviews-container{ + display: flex; + flex-direction: row; + justify-content: space-around; + +} +.review-card{ + width: calc(90vw/3); + border: 1px solid green; + background-color: white; + background-color: aquamarine; +} +.stdfeedback{ + background-color: white; + padding: 2% 3%; +} +.stdname{ + margin: 2% 3%; +} + +.stars { + color: yellow; + font-size: 24px; /* Increase the font size to make the stars bigger */ +>>>>>>> Stashed changes } \ No newline at end of file diff --git a/src/components/Feedback.jsx b/src/components/Feedback.jsx new file mode 100644 index 0000000..0d3121c --- /dev/null +++ b/src/components/Feedback.jsx @@ -0,0 +1,49 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; + +const Reviews = () => { + const [reviews, setReviews] = useState([]); + + useEffect(() => { + const fetchReviews = async () => { + try { + const response = await axios.get(`${process.env.REACT_APP_BASE_URL}/reviews`); // Adjust URL based on your backend route + setReviews(response.data); + } catch (error) { + console.error('Error fetching reviews:', error); + } + }; + + fetchReviews(); + }, []); + + const renderStars = (rating) => { + const totalStars = 5; + const filledStars = '★'.repeat(rating); + const emptyStars = '☆'.repeat(totalStars - rating); + return ( + + {filledStars} + {emptyStars} + + ); + }; + + return ( +
{review.studentName}
+{review.comment}
+Canteen: {review.canteenName}
+{new Date(review.createdAt).toLocaleString()}
+Rating: {review.rating} / 5
+{review.review_text}
+(bKpM9-q8M6U(?Z_qk4EEPg=a5HxxD z2n3qvPWkJHiNU8EXWw9eu$+D*dAP7)2DA&g xvJ=obasI-M+uK`|i25D{fsfMV^tbd_q{ct1N*d!*?YJZa?r6sR<~Sh+ zpRQz$PI-A~E-8~o;eh7%8B&RF;FB_@315t8t7OTe@A&w5Z 4E-S{f!w(GR>B`@meuRFf?tFU6 Pca1SI$3gyegKbn z>F;p z6gm0~xT`ig4hmug6V*{ P?0M{yi}rU jl^O4-0VzK!S&W;I%D?>|c}Q^Ayx1a%5cF?4X^C0s4&G zZHTJ$d8+zf-WPb+J0Ar{US b3I!xI$8;FmOsP_k{y+?EkZ2^XNO06Sk{}P2=FaAsxvdEkAd$=-@609 zpH2#YiVJd)CNQ;*$SEWS{FbeG@4bm_3x0TpJ@{IcD=C89ih7SkdS|44xUH6R#(ULh z(amTl-#ze|##OG)6ns`%Qkis2I=#5(UOwX8L*-C;AzVCt$y{q(9a#*qnsf|hVq;=_ zHkhYWZfb`nBp+zt*9XXs^5sYFjlw?`>z`OP7^z2bqDKxMdDbDwxsKmBCOcsWrvb84 zbW`1)%aScXtjz{UpYjJ!+h? $N5v4|J=K2jSu!Ci_ zT9b@;w12-$ZO`+S3=ygmB3t$fj680i5c9E1mq&^U2hz1K=aM4(pJ*HNCg!OP p7JT{5(3y6W$6WV@LgBiYD`&mm1*` zW_Xtj@%EV1;#tH9pJ}7ZK<3aOm{|Kjf*XWtk9Ua1MY?gO$+HoAq^cPO+u6IJx^2SN zP{KNK3q-C5LQ_g{kT&@y*RDdV`Q?(YIY5cQ0V(b6%44+B=)VL?Af;7CT!b0P(MUu! z=!GQTC>S?=XL80g3tEy%t=TD1$#sw=wC0m&SwpHouqRLAhR^H~C>KQ~fLM%#A|H7) z%LX{~%FeTT;>8h=W*fv9!?Ledx!Y933a=6&W9V``%$E_K1x$V}hqsRY$%-}H{th^l zZy|qEtWrYN?+ds|1Xp3^R(L*LzE1}!j=!(BRcJO2*Oo%a1PmWNc*+}o<20KgJ^3`Z zc*$zgqJMSh^yWS?s#cf%>ejtk;jR%ZboMp5oRD0fL=wvTnxVG;fmBg>n|KLEwCbjX zHSvcVR9DF|#S~3_CqBwi@y!Cq3N gP`$ zY}K0c XhL{;VG__8t~W}l*s}rq(S^LTMxv) zNS9+?k&?~`O&V)z@@>%PEP)5(H)xV?vNYNU&@J`Ul$?ibFj&xu=7N|#=A5$(=>Z)v zScNa!I(>5Qy{k(JnH~aR71VRkIz!}vzYuhw<(nu~L4uAyQlhJ{x{ar^-Hv+b;oDh- z`k#!Cs%MSN0l+%+c^W23)Ns4A*ZmPun);_{id?5?G7S3%?7Xzp_uRFVH}8nynX;3V zGY93A_XSns`R}+UR3l ~&lQAF;KaXpTSjca=ZTcuf3};B$S5&3J2hJ~QRt)|=u? zT<)ELf@A%L_Ab?l2@v`NjhFH47x7+_?}_0{<`fwrDK`Qvf~e$?ug=_Dtge?x^`#vb zcRWX1zGQ1xW&~o-K3F6GpxB#CZ@}f;V`A)SGKjwN?mMrCrpHlv1WYSfQZ1Vu>F4y| z_&_hywo2!oUghOrWTnp!`B2G|de(Yx=2&Io!=*T{;spIq2^Ae@^l7l*o &24 zI@+tb5nFJADiNmQ&$hUVWQ|nGXUJ@V0`+y4#-m>lO)Rq)rhZx0XQY)BealcaP;+|- z=$~X$><_Nht&t)h&q9gAI&!M+z*S-$Q*bF+!lVtqRE 9^x)woZ8T@5Kz`jz2^8_V(mbC5s&)o*bI8R&xHO)*lWz5H)@9 zp2cy)BC5lt^yre*i-a^?Y?Tj)bZd|BQ^FNQEm-?#@NU}_NuRX7AQi3~Dx3EbM@ z@ O82s(&0>rzp|C1E~+1@}k{ zaVcTe7u&~iv*7+sNJOFYSw5VsGShP{UB${$Z!#jSDip{f=M%5b#p4stc|A&FbZ5kt zTp4kub-I>69MV;)HbB>(T~{5C-)!x(&rG}f^yX?U=)np~Pu<6O9k60aYTy1lBIZ!W=_Jsd!;1ao!RSuQ zZ~{4hqp7a$R&?OBqMW^$Kf3~Go?X6pTJL(MoBjLr;y<$=T_n^*mUPUTY#{Mz7PaFh z_H$pf!aZjVMVms*Y((I1!QWaz8A_JqjkB3Z^mj; m@jN$IEy8 zGEZ&a9KhrB2$df%zJ;K-{>hl~bgNpz{8j!mt*=g73`JLPodhRhV )fM6~R^{+-Tx=0iulNX?5XCetym5uJ@i#Hb@QV`c}P$*Xo(wd@4p` z7(Ak?$5WR}EWvUwaimNEZ3V=VKQJ6keZ{lAJeK^H|EnBA7C~INWwVoM26eh$+HNw_ zKGsggO#Ba8YHHQ`;BC7r|Ee~BGUL^&IFz2Wxnrw?vVIzt<5zzlq4l;{&z^Vmlpj!k zotjN9*b?f(GIl&*5)NzOj<(Z8t=v?pQzz?A)lU938jtq%)uWw#;B7~9qsyGA>tcS$ z{GEHu#8A`9SowQE%?p*rBnWqxE+)XJ{~8MuV=%OZ4WULOQQ-EC@9$G0+s|FQxo|(K zmY~#)z)~44`ITHD01ms8nJ#`3n0Wd~3CJPvVZX^MVvYdy64JXi7bb=_E)8d=tJ?}8 zv)9TZV`XBebap|;j!|ai{^bGoOVF<7>3B0~p&;KsLrt*X08;_rc5(}!OOr{UmCDnd z9*4qAg3oUbVjA9GRsnSh V*GwtMC|L7UI-FTIqyKR9Wqy=X} zJ5L&e3Llmqnu9;MrZQ;38>=__b39q8S~p%-4kv{OhH{ubH@!^oYpfeXv!UnDNw%+N zj#}}PHf-BprIc?R&%*c@ZgL^9lV?q(qe+@{&+hFl-cJ@II >5rN< z(?VSsA_{^hLoej2)%qv~i y>U$ll+j>#^8s@t=8{lMhh=1}k~J|AYC|;x z&x2gmceS;e0tABJkNyYWOM#J^V&_$lv|=l|akBpexd26s6uK9cZE<;O_am8Y--BA` zhm)O7`9qET=@5W^-kc;u7Am7fYytVDBVf!%6H10&*{H}E%_xZ~LY=UdqZQX+`*h#j z3A=RQ?L+zdGh@U=_&32ue+U6yOhj1|v+^J@vYdbb4XE^}@{#~^RlbV-jhD-v*^m1& z3@Z|Av_X1qZf_#${ut+p&PTin{Jk`S#*b#Ti#S2IqfT{l%x1b3YvxC5M#Q&f$iBm^ z`b_-{ORFnOe6AMfO|#^cT-w0OGQ~DvES72bMYDQEfbVX#$_L?*>r=A$UR(Dq%MvVp zH1P#ywsd;S=B4C$z?Idy%0vk>#jn?Gk=vCQIc 1 zjIqJSHZSPM_(sC)xF4$rsugkkl>3SASd%pQn8;Zbm`2iBnho}S)7B7=#F4|^y(M3J zLGc#LWeDwZAr$|2{mw_q=ytCONbA`9uX#Zoy5=enO;rJ<6L7k?4Qd-I(a}eH>a^h` zKHuDaJ#{5SfHuzi3s=*fkaKN}!|aIs0+4MYcNlPUnE|g&zRIP61vjAUulHHxKTt{3 zQNc| JVi{T2%o=>3<>+!D*9G{A%ILh9y8p~)zDPe6*7D`8#J>@ zVb6q2$}?Enc_SnPjwc{e<^*OR=l*P3j##o{ dX5*9#coXdqjl?ypd#0aw!zq!@JU)^ zk1jW>G@oj!<;a2jRz`TSmBmv^CfmmxO&{f$(gj;!WxB{)aT)z^W3L#fq;FYt5vd|5 zSCL_N9wF}Spj>|b>y}c~5XdGx|F4l*@u9a%q%FZ$>?lcg(FGPUS;#=yH?=4+Ct_Iu z<9Vo+IO9Zei5O*fm7KFAgR(x6gt#?5PfQU94HGFANXiISlA)+*RNEzx28KzRKLQfD zxf_d@@LM)txicX2^B&I<0TUy@kum(}fyPP*g$%DRD5|!yLCW|!=2H*(#0%K8Y_0;E zGd%Pl?VI+%*D|``lP=QxFiWEj2hd5t%fa{b6=1Wwwtz|vj^Ktj6~Y@tPZ$=+qC4!W z=X1D5Ve>ghSMlbrvN|SexTv-_|CzunH+gj5(VZGdS@*9}m}VB+B6xJa3EaSAU6PQ? z<*o3)UVxR_q!gS0hxSjyhA&VpYJE?}F($4z+u3HdzjNOD-OF*Kf{er3v6QhG38@RY zL=gvW3(i~j6=+rrtV?z5+k7%1nrmSuaKdAl;s}a>LZmD%qLx_cE_Q9}s>u;;7|(wr zZRj9mAprC8YpSORg y54*X G^rV(+cSj51>im&t{{hWFGQX&ifD#IM zZVQSD{rcZsmpZW7p%RN*q`io=z8H&|ErN^*iCHBap`d &Q&YeU~H&inV+9OZ&aIVg{VJHQuyGy zqZ(C2Q;kOMu^^kj53sSwOA=Q0{Gm~oxGUE>`nxFP86xsnNYy_Gf;F>4p?+I?Xeh1l z&dWB)`^%4A4q9)!-QILk3L9!zPPV2F26`+RvBWWv@q*0K(}-q82CUdXU9Ud1>dXD$ zKi{*&dv|qd3}B(`Xc#D*iV)Lm5R^1ZFXzHSE+p2TY`K>Bn->ajrei^$_d?tb9n^7v z!H!Lsk&a?ypr({CZVo-Z)ql72R5EX6`B9|3zG;!|0+d8{T8uP~P!n*q0Ik@;bkIDw zYK46mLjB1RYZw-Fi3l0gh#~P4u!KQVn7p +a9fwHH$)H^7xef49nheh%?8DwWEX&|J9` 10sOOJo_FoW~;j!cdGwjv|Ap z(xoClt{HRVjK?C=V(Rk9&4dm+VlYD;rO-r!SI}VB0x2%-w5TAKUK{l-l1o0WX(}R$ zvrv}+OM$BdNNg3n0GxEEz I5HBrD6h9KndjTnv{ zV!Ai~2Z)|KXXbGuuwjNJj$`veGB+bbBZmTgZJIYvxaBy`-8nnAUm@;l^pzQ4ee`R$ z_Ai>I9oC_*DJgobpx c!cd!$MwOj@*06J;GkE_nFP4FSKEI z-ZQTr{#(B;kdzg8kq6z>p)wV57@>rcw9rbMqYP_ZciC0>-ru&4p{obbhD>x7(jN`e zkwl}O#vF v^G1ks0 z;<*&X#o%0RV3(h-h^^$FViE`_Tt!K-poa={2iQ^Cj(5~<{G4F#yKEVu{3gq9+^aPe zrtXDuq3tDoOPpR{xl!>WA6^_lv51u9peuT?#!C3dH(z{i)k^zN06X%*cYi>t_&akw zG%7>zy%0UmMX6c=H3aDx4jd~)TX>r$&az>Kr9V xbaaR&D=F Wc} zxURctBr7+>u=My3_IZUsdKo@-lw+D?jYc7dp<2*A!0=V |=V% D8Ms`*?|wP6ysi)RA!ii~I>Py;x{1Rcf2oV&1T_$(V@SX!;tM8E5w*F5BI zZ0^a_YPA t)>_WG zZdb&edcEFbA=Zwyn5G#}?b}L^C9gxu>**ZF*);kr8)8_d+tYvK*i?BON){}1O-9c( z#gNf%%Gn#SfwERwcMjfxw|^;WNiT&mOI+nCn^sAn(Mg~nVUjT;#o1f~bt}{}Yzc_W zQ%Pf1EB!zjw2U<%N>ES?3|oySD%HErSs$|%!PT>um9eHAscjK5dqgURF*t-8z%@Ng z^96L^teJYY74vwJ8PEh *zQqxt2kFZY3z;_@J3e=so*m<{TMHXeC@9a^YLw_2^PNgddVSj$5>m$Ybqk1X`n z5s{W{-mm&xU|_90PSqbb%-7ZDwcOO}^)^MEWkU>0*X!LJ66Zvu0yh0=GZDtHnT2|x zN^H%URbTGI+|u-Yim8EX2{`o#VszqS8CzkhvRw6>dMiRM o&?(@tTrH$ZO6-7F!ZoL?v0~@JKdKAI~R|S)}~)+ypvF8@ UQ3{Y6TmB4Y|Xpdw!l3qNQI=KkqL?O8o13EUka6 zb~>H?^x1r_n$JOV?`7bzY&`OoCV6EqjlOU9V}d?!BhTo>ar_X)3|D 6%KZZ$LnW`aaSur%^e5`@&R)+k^osiX616Ym}S zuWuFX{cFZp!UFcZ)?C1Bbs9ahjkp*g5}};W>%s m6>7_lM1bp?qgpc|x4wmJwMB)rCH%}E4> z3B-aP6EMM1>iG!u jKi^ea^cK}84HXCWsEPBaeZe3@3G$f@dEqEx>f31 z4R)x=g(|m|L;+WXT*!Bk{!5ZBEK%j6C>jz~L#%1&87kTZfp$5;srD(j;@quR6L$OY z+r}Pv$K-JX*LTa96h(A|1I<#PDS#emh^b$e8DT1zx;F`)-f#x)RW~eQ7!KtgMV<}n zkCD*hg(zc1QDhA~l8eUO8?n)xzoM$^bCTY!$g`m5<6Y^x-p=EaSV2 &l3YOLG9|Lus}P-JqG>t6U}tMmfVz62N06b&Ly4NF2X#w1E>wxsq@a_O%4 zCE}{znL!XV^6Ji BzSW@5>m-4PT!W6`!eq9t1dZAq{!f}li-5G4{IMWXTQZuGOB`Oe( _N9O-M4<}!2;qco#~h15F`qw7_e&JSP-T_pba>%{ z^o5BR!?`U1Y}YThz4;1bU2-gGc5Ro4rEAhwpjN95rIoa{urVPx78i0(uSKM*nZECL zEH?|}^ZBD9A`#V4QEd}dP>N<8$60rh+!Y;I+{O>Hj%W8tii99`;D ?4_T7r9r<7S Vu(+Nr@%CX(8iIld4B92?nw(w-v2)KoEI|RH`KT za09<*#3C2|$u#Axh!d2F^u)}MB7X(Ef=G{U=%Ma5Zfbk;6~+}ESb`wPiGH4R7F>+j zsjASLIvu^3id*Q4D_-ht$v{*#gDd5FARVy;K~TJqL+HiXY7tJat#WhIt&e958Tg?C zRaf|$kSaovA5dO}R}oC6qhRHGhRtsMnLScgMN{%Ry83mZQ?D09s2YZ0N9AZ)mII+= zPdA@PXs5-2NV8@2`=Tgf7b9e4vv)gG?iJq^h0-+0w~k@yIsUjx(m>eUqV;*`HNr%T zdR{^)SSEZ$GW1A+5s+T74#k!*RvP)L!tS`LsQi};6lpl{0Tnnmb9PNSK;Ft#lvsve z@gU0#imq^_#D>%0UH#cY7UyTruX~sC6&+Ys_eosJe#FhN(UBVD{7#2@B~9RaVTHn5 z2L@=T{+A2+{;5}p1g6^lV+%{)D^hL-YeAAY3%BE|Qs?E`DmMp_pOqA9)rq;MZKQ-P zx4PxhnG9miDn0oQz8q|GH6T>Hw*T8`5K%|BivjCAsHCI4wJz+mh}P2UIia|v(%0%D zSA88UOf-v2Mj3f@*DSu~p#Yu~!i#;rtpyeGq7pH%fYJsMd?X$Hv65)v5F0v>!fR_O zL^+lvX~ zSEn!Y<$$PcE*ZP60Yy WroK8(^cM+l?yFt%s=Bd)^782aQexNBiKfAek2umHM>ajTQoWz`#NU zeOB=?OU?9*K(A?V%j+1Slyv25{y+3AIWt*ZB+VkqWl=-F;Dg1S{T%WBq%gkL29_Ym zt=6aQ(CfgvIosZx!e)wCQhgvDX~LcI78klSxg6-EAF}%UPwVESoeeJ}d7Q~)j=Sof zp6BygM*6#4t=G~CilVsbNMBS|)7KBbKZ57hb#S?&1B)MqWjV1`Moiig^0Hd~irEnD zGiDlL926;66Kw)tAW>Ei!>}WpkCM6 iSsm=#1<*8mx=ooQ3rMM53 n8 z+8J1ABo#k*yNNo5;j59Z<8O4NX8Dc-ODA0E{0de_E*&D4bkuU8xiGZc{Mw$}!V*MY zMX2np6|Kv1qEXZ-zk+qTb~@pT-kl25Ymij_ z)?h{&vQdPL1x$PAF_pL9cdGf_J6C^}y~RCW4bI6hn;LR@0d{C3R%0kx2{qM5-ETnY z(7dNOnxlt0i0>+q&vmRqaTpX=Lq^U)lG|5as$ZX$!X{iaaGo_VUy5-iQ^#bXj{3q3 zq?twBwe6N$J@&rk!60~f_Z!l}SLdw&wYUaTi=nd+2G8Q4W1Q|d^k=Wnl2*_yq?$oz|inhO~-+4sL&)8+mMA> z3BfcSXW*ie*HJea^=++d$@Gd2ESJlruvaaAJ<#b`#H>Liv{o1PU7qK)l>u|P+>}sR z7yA(&OM;ZvE!tU43cSGYZpCZq*r=h6G=_=vrfKcc2DWYAj}|9IL@na)({ZLdYK6uv zJ(kPm-e&$=xN31_^;jgy6SE4Fm82WCwJl-E2e>;Z9F%x_t-NwW%g;uN+PBpZ@4eK| zlxhGING}~6&xdAc@TC|Pr@Au^e!5}}J*fBpyv&Nwni`m+Art1I1zAXe4mnie#S$DP zF0KB%brx)Eun>U~A|T~CIfAc5@L9lB=o}?#Yr*# r#zvh0c3?oxV3h?>5cax64^(~MrL)xPFqrI?Q@ zt4@D^{~y!9L|(qcYiOyhk^fHDH8Vvq-L!o>y G?6E|+U-{`5kxSgBO_ z>&53tA5+>MR_v4ZN3YxJKEHNxMej~cVRJN_QRP6T@=)vNrLFB9ouM$vArGRJx04vV zyEz<+=iiwzUVMgSB#{@TIwCEGFMFs)H7tbHUFla@?EO=>W^ev~#3UeBUt0feh zMOe)oN?{Qs*5OOiiY1g6{A1Bm!mO+K+#;AOxXF}n@|RTOJ=upE{A4L=G5ntyVXPID zNQdcVk#{o4*%q#!>BoB)$FWDf@tK>AT@S4OT(jQ!JLkhi#JYz-@%iV7nF^P*aVa{X zNA6V|fk`sp$6!8vE)8lVZ4u+vKt$;Qq3kbRz;#KS6`t%%=uaZzPv1uyf!=jR2NuRy z9Vu$~+f}-vh~+|R{u=>e))uY=l}csIt^UJ`F4k=R_Njq^f!A`m+<&0gQ0MkqOw2fr zKY %03 z`2Ohs%jGhd+@5sa!lhva->btp-zd1E1B fx>W>2JSjpSddt zo?8)xTtD{tzquoO%a^t T^N(!_Rm0DX%(@{W#-hshP6A8?4>YWl<%QMm4j&Nl`< zAT{_F6BfbJjqPghcML~5Rcz`QsOuP8%<%2q)sgA nSI2u z7QNZ=xF3aD2E}?7nFSR?K@KHHgEk+a5NXFf_Td!~gH^`~<9vYZgpJ+RJU*Gf }>U|ck|Lv1wlixWqGc)tAlmNRlO{=y2VG_=2Heo9^WKE^UGya@UvXII5*+va# zj4fuf+38%Ld30>&z~iNC>3F9s&bf2vK6`fN>^%$40x;P766rLUZ&iaX4x*xVA(hf7 zik8l+xNnk(vhAhoiYs~rD3a__ KbW%qgwJ!6oJ_aUyKDS?D#esKo1(B+ivs zURkb2w5mF^Iymd}o=eA4M!vOsu0@IfzCtQ)q!lKk>9}ZkE}YQ&XT!nwf1Y8VIJ5c> zj}HIlbECj>;km s9cwWKC($%5;exKQhajtdxqZkTaWim z{N2-R{FA&|vwBeRgXj0XQ91q4@yQeW&$IIg24lpg4UZ+BHS`U#h_zV9txHECqnm`o zqSEZ^lV-6+=cuRe_7)Owo##jbIc({2ud6 Kzvyo}0x9Q8e}m&Icu{DPPfan-9D>@#a75 zKL5 6 zDs9K;J~uQuGkMqK+~j`B2^kp!krks6SKD5jMw-vU9bcp9f_$O2unbXA(=@H;G6)GP zyC5Q*)v9xys($N*D>|?+S@DR!Lh*^Hpm2X$y%CwNb-XYg)lzetL6B*Nj#A=J2)-;0xt`r(+YbeyEFB(8K- zh&En2T|LsK8M)17b9dXDQ=r#umWV}24WxT)MC2waEY)iDzdwEY^#6D2)TulD*}q$= z7Ihm`y5a47A5*odyCzOgJaqQ#*>S vVHxzDwIY@_9?@!u zh((;IboEiFGBU &UhdBy84AC?-d#Ut0r2oVyiQjQ=+J_4$O1=M~Tp)tVVdp??T zKI+Z*FK1o*kB8p+_RmV?!MDm*?hQ$O_XQ6wp8mnEH?tPJSqOn*1jn$W`jB(}d||ON zz3=$s&mWqB3)ht4Wi&L50Ck!XwE()o5ZD1%gp(l{o>ci#m-?*SBxB8)J3QwV1juL> z#f8pRv3YG!Zi?m`292sai)+2Xk3xekWAf%A#xvzsc$JknVQgt&S@($Lil^@-N%F*P zw^C;nNhp`Nx%Eo1i2bxZw;t%W6iTXJ%QJb5m8xH17$J^`wHksc2JbFbTpq3cZ)YoK zapvqa)DVCC5#Zlmj*mr^Hb~0Jie16PsW(wScMhIkLogOV&*)H?%8kclIfkw=I0#U$ z*I}%&a$Mc7)T#=#m9V$a8?CC)nmLwq9wptMC8EsMey+WNW!xC~`j3Bg>`(IV*@lL< z2w9Dh&FQGkRWNMjVe27I`-_Gb{BWPfKGv~2R`Y*axZ(W7V`pCf@k6CuI$Yi3`HWBw z;IP)xBP4p50$nm8hsshwBe4)6bp%TZ4V_)0Q-TyF^D>?8fS+S=CnkS$rCDQ(VN4Ty z>t!kleFZ+wYd+@tYdnv^c!xGuZ2wn3I`KdLF?k3T)!fMex&P-oGh^T1mEZM!Z$4Zc z9=W?~<>l2AfAQ`7uEOzGW{y8Jk9o|W|BvuF5jTKRP+;a6zX<2Fm2pKJ#*l4*(yz3j zL6B4`#H%Dq5Xr&PGp^A{8Z9e6`pxT6Uz|l>SbWOW@3 WPI2u+6t 4-(-Wj0H-ZX r@l%x|F5!=llNNC9h^k ztxoe+&M}rnj^)TTmt!I1vxQ%nvIftM!8GcU^?@klxrjiD!K4sOmC*?8@s8GkEo3C^ zn68k{3HkIBsV?Tc43QwGN(HU^qgIh Ij2Mmn5r=gwZ%lPK(V03 zAt#^cvIRA(8>P{{ Jru)gOHqVO`>#)eY8!C%a37wnAd&{)HK2tpysOcp{oQ zle_?iW>Viv*Bj(&gWMt}N~xY5w5lRukMT98tCONr*?{iKD4KaNbT@YM5ezkb8$MkF zEa7hjba4j~bVUcF5I6{lKUCL-KDq9OTUY#kvn*?pDj_0+EmX+F&-6U~zir!XLPcqi zyI#6#krr3NCg}dWP|%=48+}&6%p{(P=qT<4>i!mXt@PcBh;X%eTDSLK3`B)ObT(6u z(^kZC;Skjw@?YvzNsAB}bk4>7A?_E!fuTqG{uM=8_h<#{Gq8Mm(u6r-I11EI<9$Ii z7Er&CFZ*z$fFwvTZ!g}h21mONE~cbSlvoC!eT1a@svt}hxR&%Sh%LIj#mTZMmbphX zDab3AK|$_PA;+Xzn{=wu7Rt%yGaruXBQPU4s)w3nqp7;^tO#}HV%A^8yt{a7r$6sV z&Tdz;;p;9M%!aKxoR{LNK0Gyq%K~@`xK8h-A`V;bmCz8n9&%O=vJ`i{L9R9=o=VHx zQXZ`hsZM<20ZB6NXf^^BYF$RzD)sCJx8d%vBbQo>_&Ot$D3uUH<9f$BWM78tllQqX z+4kmjz`ER7nx@SmRlgUbu6T|{<9fZmH;CKK&{O-EDi(`JMg1N zW8B9@B+MU~lXwr9lRx~?JeD@ffZ zX&wvRLzZQAWL95ktjoZXldactz6!;YpvXz@31ccBg+0lKtA?2OL#(%=001BWNkl oOD?@Ht(7j1xug~wJt zkFzMUqRJL+RQjbY(_e&E$RM^D0zHDSMrgz~7QGs3fzy%i6Dv_M)*?h|fLJ4zW}=Nt z-!0#$dx^fE%kc53RY+}VvBX{ki#RNi+;!%?+K^Ul>$G(Om+5I$hcccDqp6@zE)b)< zBSB6HUKp>2^}V+2B2WX~7iPyv`hZ0eDEc=%89A0kpH=FZ%)ioDmpe;jt K679bQ|QMBbF;# YTS6SfpsJch^vfXX7#XOLrm4$V z@?*G-CNz0Dk;@(PR0U4#!i{?m+!q2%w-D4__)QNPJ%hZSop96-bR6*BX`~0y)eU;@ z99r7OyaO)f4k6A3V~MI;m~`XQMsD5YyG%dZ=jym)=le*%=6RdFujBXTA{alrIEAL{ zLCYENr4U+1hZ}i3O3e8N6o>m|PvuH?UAs#mRaNUWx(X%tbhIL>88kc3%*;F(qc?-i zFpLU!kV{*HwzMtQP+;2>5cwxDFi_+|Jw55X)M|(ui(V_L2lQH@{x7y}@4pmun{}^M zEHkac71cR9pR^HwMNyPTdVOzR `nm >}lShA+2 &&J zR8+j$O-Ari*RpdTvWG@k2?bw;X2;Nd35pl-H7qG}E&Kf>YhPizy!^xZVnyV{yRR94 zB=vpT)KCRgzI2D75E!^IzXR_s?mF;ZYv*tEI`A7x*B`jCd?Uup5#;?0@__*hN#B$b zG5X5kN1b@P7YCw}D?yS!P+~r;bj%Z6tytzsiD)y4T&Sa+pH=D!BJChqgQjS_mq;S> za@R*>hZxNaJ}%|&=vWOx!e7}vXD`5!s3H`>4&CIuQF2a^p!n3eE+NA*$f%jQwjHb! z)@@)h3}ccQrRg i4(D~u<&qz?%mF`#?0sQ{E o%~MiZ*F#CUn){>`n3*B0p#PvZ*RU{=nqu zH#swfre}9u4(TzQ7%@x8O9o^&h8b&Mu>^&C2}?_nij>M@q_+(R&J31$Bp`EshzcVz zc;uqF40&Xa%G!r}4k~CZhsr2FQ&LJ$Yz30d5c@HtAQ`~Ph*G)?%v(|{lj3Em2nEWT znj%*xqR!er!tIj=l`uj?-+wG2qnRk>vWT_YdJZfNuQ^_G>YQ;asS>={L##-U6q!d! zQW(KfGbrauM acEj2{ucG%58f{yUAt6oHTrkMH|ksr_^@TdH+4V{Af< &b{*WwjH# K3w535}U12CN~{LF<|?xEi6vL9&rUL8wEDl8u<( z9&_R9i*WQANJbrI?4alw7+mbf@R{qdH~i@PdVM8saOm!rCV%>HG!kPmTgReTfo0}k zM0sdc6N8OyxPERY1{aFhCJlbKZ3pX!b)V8jhce{>1lyK=c0G3~>fl}~mBU^0ECgNG zC#Yf~axL`U3(;)d!lfat prlI7=>r$Mt}jm2;Gwr2NH5t0ZrS3ugUN<85P+Xn(`|5w!JxpqMkWA zROmxi(GfR2FkgbjES{&}RhLy&psPX#Y6F0?c@tl5a^UOPNOyH&*#kVu-9>y0T9+JE zgqWm5;@m0~dc=^CO$_D=Pf6CVb&c+r_v6CJxpNPDs>FNesBestHHs8-4H&LMN9J@s zzB7>Tdsb$*ZJ7KDHp0L%I5>EyR;%%momhy87*P^+2sJXw3sfqVeQj?}f%;}jrP5=x z57ATePB2Tiuo5C?AlSiM5ld%?D4O?pX&MTJ!qK)DrO<3Px6RMb^W0)5zL9uN)3o{W z=%-(4d%-$m-3OLk`Qd}vSr6J`hyke#E!5yQL(YzM4FwG|KvnlJ70ldIoqy);wjHz( zun$fTu)?7dD 8*%mCDP516x~roT`U$KVd$P;k?rRT3kwT(iVA6`%A0tuzrX*7ZU4Ceu DmWL f*qG7( z__*GWem?`#(P4Nx (OVJAB_l1+MHjoxZoQ^*EJD|ZA{5fR3FKs> z+g>L2bik0avnU1yWSS-hlrlz)!6#hy-j2ONX7H*p;mtnumOZ`ODM*+%oA8vxbt@uQ z3F>b56 id=_X`Tft&YX7hIh7&)|$R`G6Muq-*Ip&pv+ehRoQ3 zZ79O3$|#f4MWiBjsb_=1G&7tR;yF!dZ2doeS{p_z-_qf8x;YbXQJHOG+BN z)0VH70?MyYHHd_Z`%2|Q%zeJ=xp^niOYrNRgd8h;Thh9fT3*-OV~Alu9)MNTq0KN{ zXKu$$rCndJ*`BUZ-8pymv%j2u3(7VV3#J3#h!AOs?57q<7|{E`<|1S(48Oj6-(77x z*dW+214}NKd%aL7Op2Pn=pzz379xVFR4Vs3on}{xKN3z0abdW+9NkDFBQI_yie`xU zxW#k1bga6Wzr1-r$vXovcoR3PP$)cUs7BX8g;1?lxg2ZS=}=s=bPv$=OxJC(SUf`2 z(~XJ^Gq9Al{njhH3fsSy^|COlGD^rm38+Jqx}6<(mXDg=#L31vOt`ZTE5R?i>a>{b zV^3el1|J!U@+f#F@=*qPIm^}LUB^Qh#0cUD4aaVK?-t%3t~L?#3xyOXYWti-O)ish z$T#X@&N~XMiiEP0!%lts;a&QUhke$ayVCRz?>}jueb6>tR5Tk7bGU0Jbu$~PfuffI zn~O0V_T$}|n;+5H$2Vkt1siE#A@ue29T95pLVH3)D)dMjsnyTV&)@GvPS^e+LZMJN zRxX!0S0JtVLQ4WsZ6bxWEnFHpEkU-h47$cBg6`| eXu=H}-1()CT(YFhnI z+y_FVD3i$?>@W3i*g*vwZD1KNhYlCz!n3BW!g3|3K6Ql#h(ZUh)P$GuV4ESP{RN!% zYxg2}y{jIsqThLZcVYAkhAlx}^dZ?X@8_WOy{yX6O&v_zO7LDXTHU)#IU)%?lj~O- zM8uNtqR0z8;+q*n$a*reO$FPPfu~2yzwv0Vj~@9y*mJga?t!LShiCYxMAf8!Eb#fh zH6PGz8O0!n?QG=FRQA!HUD4}}4K=W^%!j-}q3{Z=Cq<{Spp1(=3FSs8>X@IOf6(^r zo{7SORXE-#;NLL}?9+B`M4;ToP6%pSL2Gm7xB$wOF= t$gNPcB3vwm z-Z4emlv^nj3NN >u*j9hIB5?K)60^3Wv)O-ZVuG%%&DN4Ic!a4ilhs}%}~8^xjsdLZ*{SO0blXZoLL zdt(Yp@PqNG>h!;8q6uGi;lPGj(BQaD&TKYy9n6inlHgcz?9a00Pi+W`k6zet1B+>z z^Ng_<)85V$rHK59h&rm(Dn%`8mfJEcGc7XfLeqlwK~*QAmAi$vkBwxdvJo*jFnGW+ zt**Qk0(J7&>-D?S)B<9UiyWY!2M{)ru5B-DxFkc#yz|99zxs Vl)R6V^RMoHcl~>N&FrVUhMFq7^YESa^B;R<<`+Nw<-`dT3>wH^ZJ8mkr|8i~I7G%=5kkX+Hj#n#vd2Ey^M)kUy=V8I_9h?5&z(cno ZiV9SY?Fsb8nz1c7^^$C>ZJbP+uZY6En7+k%Na&de)5-ksyiA&|Oqoz>g_Z276 z`fVu4$|V$89{#kAtY_f8Bk#f}`k!!mu#wf^m7(wd^2o^v%)uS<@uqQ#Pkg45MO4sH z_C}CBt|7OW#k+H(e=uzQ=6Bk5vH`InvzNtU@kJ}J4mO*U_bNHkvxs>jOH?3umb{fS znVFf{zXRwxun=@rcXGMh(^)sW-;0|`jz!wiYq=aqn71M4SIo}N!jo$EE6oV1E5nj> zL_y4NY;jZivXqD*wI~?p{rDkz^jX;A8HF&I3NtpIVlVvX$_=;u%LjTL=IgJ&{^%U5 z?5PJ0#PV`aP7ow)ZH4td$4e2{s^^n@QQOPALNJg;S3Tucvf1nb8FJ6k LUOGQWAlAv+PC=;4h?Ec#sk%wT zDPfR_uCR(^ESwRRpO^VLjrehfT$h%ty`xnTN-VdmWm@kd4@8w*6=Ip|39(Q@S ({7zwzU5H6qvJpZx=04a8lKhP9Dab|=Bwxayo;x(O>(d*u zlerT%tSD@$RC=*gD!n57S41s8-SH`ywWQ= V-b&oHu_yS0194`_+7j{?Iu9b{bOCr*Of|TFTGx )NzF2k}}oO{)(K z3~ZV~1sgSDA!IXmO?+_rJOA>?nV 3y*_xp;%jcf_3V2b+d*t-sA@^~`qISJnwi2@?j&t)r$mX54pQ&9 z*6T{d4pm9vjL3_T%e|!~(7@q=p~-JHzCvkzZ!%VTD$9B{c~o0A8RU@@YTO-DvI8tg zjl24SUmmjAEh}zP)%}?<_lqO@&-eMLNzKH^Sn}b)K^( @x@3cC>-9p=Ip* zhJN!!s@c;FCT5nj@pqc*Qmt0^)cyL7ww 55Z(87az zNl8wU`1dQy`f2yYbfmJXJDUHTjut|M-|i$J-g^DG=!Q@K?Tc|A=oXoDi)4DepQ@LA zeSL=uxkAS!xqt&_yi%!rm2y%ddQ11jp_QxQ4iuJECq{bPPBu6;{951x)_WeX7W9cX zs`4K;W2*6!qLzn-(c~v#TCtJQWHjR`NHyt+_XgiLO6(Jlx9zBf9T rpXS8Or DlFD1 z$y>L`9WX`^#gKIdiG>JVVys4q4?!FyQKrbH(fN#}rSq${LKhK{gi5&LcY&qcTO=Yc z@aj<}%p&6(V2+GYa~L<}cOFpKhr1RN?BMYJQ~s%YCoqZmViVPZhX^(TzX?^6VZ;`+ ziVwZcFz6LYNEhFCwQRA{mhbK`Rd<&ZFoFTdhE!jy?c wO>F#2xdjs$+koYp O(--d zL4vL(CU_#5D!>O2T1LwuSJDp=wlsU=w(}Cx>so|0Rifk8AlWiBC+XLrEmPNE&M6oU z2l1ip@5B2`H{WNo_jaAFg5bw{-*V49^m^kYPAli(mIL^D10G8TLaHhi8U{+$JVxCz zcALAtWUx 0TS=1Sr1fOe`5eKnzEp^7OZZfY zJ~mMaqu=xS{6yB|oRzMF3Zc@h>?XYxF~E!HTkJ=$%Ujpxv!zmLQ${P;3^^8o?PLGl zx9YEc{l=gf|7jG;P{B}DJj7-IMfTu@9&9xLEFEw9=k_yO|LVJf7ar-xZ6Rc>4 R`6A75lphh<^t6jV5>FOlf!@2&Sm>E= zLE;inDVNJn<#IU)&J4{Slp{cowf0uTa(O^efQSUry)vST)aknyuq^91T? V?J5*Q<`slU^bWNg z??hGMZKPSQDmbdw`Z%otKx#!Lk*KD%swgc22v=L e!V-8B!QQid3K;L2gPs z4?|kTf$@>9%Zq%u|LExHNi^dSb4?o*$x5mWKlFH{LgW-;#`<#0YFZKzN#ZHRC!^MR z45juHNx2~=5f?_`c{e>!p}Pu9-$dCcW2Z6p$dG>bV_w@kmk|Xo>^bS4yZ2T5)PrX+ z56|=<88RHnLEzgc1r~A*6S6JCSY#M6hQGDjy7^1Gv2Q~;8(u6nRm6hCIq^t;fB&;0 z$09Q7;%Brn^)wqSEG$r!=*u;?)>X!m5NIE*^!N84EffmJX^;}G0K( gThx#bBj`~8 z6#*FWPZST16``4pv8cH?Q9Xl`^~r~W;JLkRJ4-=U_Z{2azw>{-u73xtQ0J=t7Sj^d zxfG(71$4Nz3gT#LF5hg;gU37s%tcIncaq=QT&`Rn$vz?}Zh7xeS8xDdp-9Gn8W~`* z$)gmD J7^o)dw=?BL _g+k#aE%)JGE2~X|P1%KKvJbxUDd3LthyUw`zAJ^##a5K8tEt~4C&BY- zs06bJ3K`P)N9a^x&n^7$mik{F*k$Z^++iQ=ctP0gHfI~~$Y=cLzwyh-*Izq!;+M#l zO1$&b(Wob-j%MV*r80)z5~A|*$(zYbCTisvsOZp2zAO(utyTnn!LyW}OPExcWCby~ z>PaoT(iT&cDkv(QC7&)n83FtY_U(~6mOoSeH~eTW?Gn&~-X+}?L$A2cCDCE!!;u#O zojQFp$cH85ye#ylfo+4^4hHPjj(M>(WOn a5^DP8LQk-J3 zcwonl9ZQ6=)!o%-%{W`w7)WdGib&-`A{M$n=yeoTh{}?vPSJHmj)WBb4h#%Tl*{Eq zZ9C|I+1l*wl}cqly`Qc@v0ss^5ywT(TbA`CakTnwxOxT^Y}SY+jos$ 9Zvd!7 zV58(H;zR^&DUTxaut}T`(a@;0B0^1JaGd~h5F;yD(4atX$WWXJx~oESW$Y?!$Bm_3 z|5GmW8y!36)2LLwv;P+}uN^$)&BD!ks1Y$I=LHFM001BWNkl y!LsT0m>X@IOzh`=S zdQGid6>7zjty@P%Mjk7bN={lST`+#P#JD#O-mXi4VExkhq^MVP%L{e zvLNyGiIPebS*sI=MT!%}x0rrUs(bMY)i`kBNG(>8iB#lV2BjH8Z|E4%@))zForP8$ zycUIvySBJH6dU}<-6>9Shrx9y4ueyCa49~xyA&(#(&Fy!?r?dBo0SJhR+5$EoW0N2 zB MK7Gg&D%B10`TDkX_8HXma&&0zYF)b!kcBeEZSkN`SMbj~=6EBc@h6x4 zb0w^MM(_IoX{*n4YKq`ySxW_|u#KMavGDjQWT+0>ORQhw7XNjAY;5e+YJcJ*B43Zm zXsIxx;bv@XybeDuW|p$tGtj;4aPp y?0_jOuov4oStTY zTo#_QsGXfBx9*LbNVi8nH`aSBqp{f!hU?p3%}cS;+squXqUsB<<*63feJJ~O>gcvz z7dMBgNa=zY27NVl{@WZLl24 i}MCwW+{ z$`G+3jhhg1AK~|Sw*Z7H6rr-ig`^W=EJ`yz{*;XT`QaQue`*hb{lRMG?tfY2@cvS^ zQSR2Oh4(WqHkzC*SwSW8N5#|#9+4LZG$K8i^DQwkQDx?+k&4FC=391@+6%li+d5 R|q5JnTf8xmMTpbf<5?-qhcYVKEO*~7g zfp8D|u~V+Vyr;j;>fOV{#?WWnXVt;XD6z$s;|+&35PME{YpQXMa43-n`S^l3p)90C zPO9T;0ulozuHWo`HfY!)A~S8&Lk6ydlJVXi3Q@Zxg^8_M2uZvS35_+hGfJ@ul?8X9 zs8kN9o?t%mjwiSf#NcX#3%@YLZ NuDkU#AM;RZvzb7{qdhBCA>RQpz_It2JRzcY) aJ6hyH@d{ZG;p7$;_B;Q;k&t&^DBGPz`bGJ3J*{$&N4&kgJ=ZPT zS2~1iQ&kCsrS{w@pTTyfRFZnvu8)h{AMKEs(BYXPmh@?DiS}5*nBjvO!HWs}ai&X# zVjV!yzf-HL+uiZO9n=JIt9pL}dY1!x)lZktG|kUcfWNp(Jb5NYFm4H}@LfK$$wVu= zt|sao-KfK-BjP>9Ba)Zt*k9_fp#(-#xt5^wJEXhdM|~MK5r;2T?yx{)SqxAjn`X=9 zHPCSnF<{&_6m${?1F@y)?rSDR7CnGWTT{t}kCidTe`&SUVWc*|TV_;f z9`rfDO0q%X>v;}h2zy $!-#uv^&hFA$~ zflTPiJ5(2`UI^CGoXH9Z`|TjCQvOoTxtB{Rdq2-{OWCePFgNdFV&vCzX|1*TjoA&^ ziO3RKvf7^l^(= Lh5pla%5D*Tbzvs3!uz39!StlQ1%P$pD zf4gIN9#5B{U{R^~k;~Q`;g=%8K!sYEl=wWLrd%L=7ClypJVgRjta@}vKww0C?-na| z&2@ca!>W3z&Xv#L7RS@{h0n-|Y0@QKv>SvI3$nho|Cx!bhwAq6a`Bl|%6_yZ3>T%n zo@gTT5Hl`4-~Hfyt?=>k-k~%7L*dw;{X05>3`9Gp?c>iikSo=s?r(;go13fr6t`r3 zIDwl+yX!eK?zk-vSIH3>zn6Z_dsX9MTur5&U^bLZ@}c3I?2fl{Qth54tu3gv8{Ee{ zDt`05lDgi>tB=JR{D(b)3OgB&MG%i4=wiu5#PZz>xPG^ hC#Ukb%Q`U{hMrHz zzC?NKG&D?8!YH wbbBC%(4KX1d0ZCH;>(^l#w5 zKim8?_lIbIJ#o^EGuN+=%Bw~G x&v4Td ze&it7A>%wgmWuNXxrf<^5-fUq+9+oL-)by7^so>(x1Y0WN+OBxKuZyRR$%k=@2`%w zm;RjwoOeclzW!Wo*nII$zMQrEXdUL)Ue3<$IeP$?EaVJnI{w)zc-!m~n*+X%sK2{e z%h>E4FL7?b{=%-yqyCQNxvpj+a}g78ZBJ~Jh-L5h9fe;sY9Td`h`x3Crox~=yn={F zS##=(@vi?+l6iyq6-WtpkmGn3p`LeG>0Up7yNACn*u7%okXC@_5_L`ao8nL;y%$=m zh){E+K@ob{Y~yJO9QQp^Shd`CKXj7czK6>lGdBOPb9}Qaqvfc|DtFy=fW^y_dPp6R zM&@FA_4D5u$-({gmiL%PNr2-VfP&>uAX3aQO1NHx_{8@jEObFWiLAJ(l37R$M!VfZ z82eh?Yf-iI(Ja-%jl0XZ7JpR#R>bLYGq_Wgk(4&9V59M;u53vkw6IwM#mF0DTz!8s zhe5hV*g?<`ZlDS5YJY#WisXL2_DcIGgEq(ZO17n|>J)h(o^PK24&`}LwXyDxZOy^x ziNf|y@a9*yM|Rt~GEkyr_#N-J&KJUlb*U~RD@#E}LL!((uE_>}9rGwWBP&y3FTi`r z*Z@Is>pb`^cWrtgbhgrZ&Ai;~1isUw&~#>%W`P}hu=ZoPu-Z#^QjyX4e82aV-i<5w z7VQNPvaPX3vw^NhY@O*1SL8^kX_47XV3Gsg-7GbJHNKC Epd;2#@}n z8195( !28lb;TZ{?z{Vl({LSwwc>s#|8HRkmbv zbkyvP6lPe(nI4d^Mow3n cxF!MzyzX%H#)ZP2P9)Bj$_OOV4@^!vz8the62 zf)PW=UEIJVcQLsT&-;;N;u*SaWU$=5Dw+dC0WHdg^JgB@SI!I=(TmOR_GwWfsHR~d zx#S(KPV?HDw~5-8%~$ z4ygTM6Gy6oqbr-!U#}?$7 zUir(~lXj_^o-5VyOu62Ny^laFLHArprML_=!F-;5Z~APZb{ni6Ge)y(zg` *! zMy?suN)esI@AuTLaSOs4m(_asjivj|)g{bUEFonT`_LQPaFliSbvW-WuR10+mVAv^ zGsR^blO^FU?+N+hWUaL8>BY j? zFs)nPv-N3?PZWE_+q1;`pfq1gC_enLeRORaltKrFl71X*k^m%weTq9}zWwZ+^z?z9 zEz% M7%sLyC4yZEL-K-xfT?`CePZyUmL+J<^>r?vEVc+f9Y=iH%-?mm%-||vXM)7 z@W|y8Unl?U!=ms$^tz;s2i_Z92i3Q-5Fl$CXbMl0yFI2J6zTKd{trAjz4a)cXITnH z$M+Q;Y5z8CgX{i@zi)pj6tbUGB>CT>m)*eA(x6NrUDct)C{%Mjj+*s()cH&ixs32M z5w%;y>lb>js$(bQLO2F}R0(}&cM{0C2U#0h 9&^xi+Wb3T9U2QxiZhv@0YXVkf;zvEK1wmJnT|P~`xAR;Ru*6> elgk$zmHD=R&ikbJjes6G7hH^5TNLOJgem4=zvaW7(lR<8kiw$lVt{lOLBiynK zm+*)wo6>`e8hVpe)XMvA5!C0W>d8%0xFX|)FMuDqPz%Z9{-FbaU}ys3aBFbg FX8b;?B&X9Bd+)(MKxhM zbu Ng*XX^IAVb|mo zIlqtU0keBrP*mXH>ej`pE!elqv9y`_4?=2KDx?+4iQoR9X_M=l5A$9$zb5cjLMx9j zLD(rLI`82<*F}2pg+o4JrV-{w9h=qP>0qZc@jgc{^LMl3hrOSa5W$>DZ!7tC$*klY zv1V&=Lr%#9b7!=@*Te8-{3X~}6HUiQGf>{P2Kt`-kQ8Z@;N1aqD+EL6^62QQy-S z67bj5A7jwSvYCM5!Jn)s+2nadAN2`G|0Cv%$BZdmu}gd0@D2M&pVPE<2QSa&Ii&$& zWlwquwC>tTAwfAOB4pX%({r#pp+8&LuNc*+43jX}Wl%hmUdeMzVHYiKiA^2Bs(r@^ z_fO+qW9B>Yn?Eghl@N7(#!I 1aHe^J9|t z%3ufZiGvuHzk1r;{+Woju*bQsmH&IDrgZXGCzb$cSV^t7MA}aO ni?{> BTgZky5{bDlrXS^6n zMzeU@!;f_#kKC48h=|pt;czbP2Ppqok2s)Wg`JhBV;BCDX3OjKkx$>B{ahw2%hAIq zGcj}(D2*bInP3l~?W-hBA-xg}K(B{P?gFgQg?KDdvWWptIh`z#Js*3&`t_($mZ0}3 zII5evECFNQxfRBjR+d>4QA-avf~sk_U(hp!q2@HFHW#(PyL6vL_DF_=R3BX3@EXJF zCiVQ~2Gguwip7Rh^fKqonYZk{ZP5e pS@}kiz)-u!7?tmnCF|e0zCnt}#V$iY8nx`cy^z?%v`tEshaBr*dIS;=(bP_2^ z!GVLR-0Ao?>1JF$2k6#LO6qe fIP`1AEV0{_Xc#(8N;mBQMe8Ic z?MdewzIB~TeV(mG-dnullSsoxzXaJ?WmL(Tpm9zIsH)ZZUIK)pIniuM(M0@b&WyZt zMmIsR);BVPaPnCv50wiz^cy{cx!aX{<-dmOK$3y8<3p+rwOYJddy|t+$NR)EF5$!R z@UC^YUOy=onsSYd%VG3UG+ZQM>4dy8Vz=H;8b5|+z7QND2SeHb-!ss{#) 5(c1UIc%Ws< zP!xUsE6Ene#I!ImY>7*Yol10WY00%3RZh;y9j-^H^r`@m@u>lmx3W7kq1)is>k^$G zR@i&K+U?PDQ3gmfvuezwh$FnrI9v^oDzI4kf$1u#_iKIXn|&{_KJ#vWmyIO4QXt=T zJ-nb~rdTpsdh2ZxZ3^Z2n63dleev6o#>aO{#BD8mUzkHprhCyB&wm5kDn#*v`o)AH ztCp}76^#4=yBjf+s)-__oUH4c>C k5xtvkxHzBNSY)98 zV?Gy`XFuhYG5kSP$%($$_L-ND|D=T _&4C?3_t2w2`t}}300cXA zs=+ZQcJR> U z7a4h7gQ8&C-51r}U~}WD^ZwJ&&3B&)fVYmesQ0)#y)mY}G>a2l?R7gZzn|l}{%onF z(;jdtBrz$dR8ltv`_KNra*2$ TZ{Kf1JgPXTk8QB-@Ts6z9f5bN-ty@ ztfG-zwRJ7Vz(-u_rTp)=X!K$G*9WOljJs%Y(H7zFWiuZ4T8X)alRqu(OuT+Uf(aUk zgYJcRE}KOg=~A&+;&FSD{T^xuF-Aiq$o3_%)y9yL#5T>;iKqW#V)@Ldnt{_(gteOd zw|J*`5LGhn{9yf3r{xq%k{y2a-t56km0+kv`o8{r_FOSpH4#0{mF^~y8IeIKk6tUD z27xegItHP0k!V-ZGItlY;K1W_$84#mecPgk7v&|Ah|cGrIt5~zQx*-6-ORgb- >;;Pjpm2DJDSDlm^bOgZDbBs>;s%HD8Zcd?p@q^g~J8@hfk5W#;EnYuC=jk5^*H z$r|YiWzr3oEY=9&z_6#^RJ{>sc?@D@-Rl_nTG@)x_9p8~5>K=fdSLFx1wll>AXDa?p`Ea{ipe p}M72%6$g zno{kd%oX2V@-a4zmoyppCB9s3K451kg74uk2zs(Rx8uHjpNO$z_kCZjBoQ?vxiukn z)I3X5e=Q3^L3izvl25L4GwgM 0>~jgaHFA?HRxv5ak_KN zOq;K8+slt;sxKVN7*4z70Tv0NrV?X_teLjt;61nfK9I}vv24#;K DYEP{@(kYN6=0EX*tvjT2Fqqi0oLzR+-<$2*v}`j26iIt_4gnXl&Xv(5 zvobi})M+4=b==YvsmsRl $O2A@)}-MH)A z21f+Hn>YK1h@=;4wsr7AtTE0SnwMF^T`WnGUUOl2l6^ckKsjBcM6Ek$U}l`7an*-% zO?K$U?Ew)zqq1s}`RKbtaokCSFnd&K$L>v&O^=rVuBA@Vb<;w$KrvN5F8x0-=5R*> zK;?1pF50W_RiRr#lXoIj*yF;hiuxZ )kRN+II(278D*WB7=7Xd{yN9;;)=WBhw~J(|3T6R-a2C(WnHuI~+ST_ifD zwctrHXccUxV@`{&mCxBD(QJzzT8;oG&WN~ K<6H3MFYp9GvN9-gm*^C_r zD@NBm>Q*_Zxa)^CmoNolRlBem={afF(ow@?HcNdy_-Q`b3T9^g7*%OsP{j%cdNd-f zm9Ok4_a$(Ogi8UJBwdxjCEaGZx86hKrU9*$#e)Vr<0xGCTliY`WJbr|5oLH94;mtB z v6$^f)0YiMm9ugkV>u@AEzeGQmFIQ%xDFc+~ZPX2FQoI*xv zZsk!+)AQHDYvsJR?7o>g?~b=?L6z|iP8z+a?5B|{u%XmmN-xf+L(eT=jxhLi@2G#= z)Pw5&hG@!QBO{z+JpKDlRkeeA2 0W1(E*F}B@$z`t)qa!AXwlfuuy zWC?y~nJtqB#rGy;^%I|$?(2?G8tulT30W=BR#oB7O!SCwS9JkiV4X9#__R1bJ8Om2 zPe~{$;me@4)PO?dX(WB^B|YV!P)MN@D}IH8mLuc=Wr>S*Y~WPUW75#`?4nCRgt+~S znLDA9kwE?L#!lysW_K6!8AI%dT-!C>kyuqNcGggZNk4BA6>|fSnzWi ?|2-TDGkGNU<{Qo^Jo#!)Q9vFX=~)dZ&mTcV451?MJp0L)Aj&rgy*O zw0wAI)Pk9WpZ{BOE21M=B=l_JT<>k+6PvDv8rpTvV(Ld#7I-x#H@vMy6O*vcR1@DK z-`}(&v9OH!Tn*%aZ=($GVo1G;u^+uyS4F~ep)57o70V})WKHzti&GZI8$P+U;j3!4 ztmKUUYMaZ;bn7BjkA8D{2-JAwm)}k|u!@r(sAQs!ns}=V&@fnSSe)<+)91IsS}=(V z3TgJIw9#cWreovc>`^vGnJDdL)8IH>x3Za!O=i8hQs)SBXUg*fFeD$`sG0yhw-8Fp4K7K_7L^F zVT#v*)jVPa0x|$ y{8$$_G zh7I}ER@ZWc-kvEFflivGFdv^ODLqg-NtM2a=mR?FZL}oW+U$On4qRzpvTekNE)MF7 ziOA^aq`jl4wSS-Fuql9cp8&xiQ<~E(#qh&dsL(HxUzemPN{1wnPs4wL(fy8tWEG*~ zrcV3X`hnP5Gp;6+mcMm<0Az-q8uzWX4}yjDF>N_kzG*H%*)-bhIQPnWPx~T}Wzm|! z-KNt6WSL>=spI>HJw|sh=L4TU#xUXh+P}D#`>yH)5m`CE2iFOow8i7!)+i8Y(*TMP zoM-Q!D=0R2jhMD_SrW9jk^#T$A0&VZrT!a(ifUgfL&P2Uub{hPVI<=|onE8Gp8=To z_ Date: Tue, 25 Jun 2024 02:40:29 +0530 Subject: [PATCH 4/5] fixed routing --- server/config/passport.js | 40 +++++++++++++++++++++++ server/controllers/Auth.js | 40 ++++++++++++++++++----- src/App.js | 67 +++++++++++++++++++++++++++++--------- src/components/Modal.js | 24 ++++++++++++++ src/pages/About.jsx | 2 +- src/pages/Login.jsx | 19 ++++++----- src/pages/News.jsx | 6 +--- src/pages/Signup.jsx | 9 ++--- 8 files changed, 163 insertions(+), 44 deletions(-) create mode 100644 server/config/passport.js create mode 100644 src/components/Modal.js diff --git a/server/config/passport.js b/server/config/passport.js new file mode 100644 index 0000000..e50b0ce --- /dev/null +++ b/server/config/passport.js @@ -0,0 +1,40 @@ +const passport = require('passport'); +const GoogleStrategy = require('passport-google-oauth20').Strategy; +const User = require('../models/studentLoginInfo'); +const Canteen = require('../models/canteenLoginInfo'); + +passport.use(new GoogleStrategy({ + clientID: process.env.GOOGLE_CLIENT_ID, + clientSecret: process.env.GOOGLE_CLIENT_SECRET, + callbackURL: '/auth/google/callback' +}, +async (accessToken, refreshToken, profile, done) => { + try { + let user = await User.findOne({ googleId: profile.id }); + if (!user) { + user = await User.create({ + googleId: profile.id, + name: profile.displayName, + email: profile.emails[0].value, + }); + } + return done(null, user); + } catch (error) { + return done(error, null); + } +})); + +passport.serializeUser((user, done) => { + done(null, user.id); +}); + +passport.deserializeUser(async (id, done) => { + try { + const user = await User.findById(id); + done(null, user); + } catch (error) { + done(error, null); + } +}); + +module.exports = passport; diff --git a/server/controllers/Auth.js b/server/controllers/Auth.js index 124011e..ec26468 100644 --- a/server/controllers/Auth.js +++ b/server/controllers/Auth.js @@ -18,8 +18,7 @@ exports.studentSignup = async (req, res) => { console.log("This is jwt", process.env.JWT_SECRET); try { console.log(req.body); - const { name, email, collegeName, accountType, password, confirmPassword } = - await req.body; + const { name, email, collegeName, accountType, password, confirmPassword } = req.body; if (password !== confirmPassword) { return res.status(400).json({ @@ -28,14 +27,12 @@ exports.studentSignup = async (req, res) => { }); } - const existingUser = await User.findOne({ - email, - }); + const existingUser = await User.findOne({ email }); if (existingUser) { return res.status(400).json({ success: false, - message: "User alredy exist", + message: "User already exists", }); } @@ -59,17 +56,42 @@ exports.studentSignup = async (req, res) => { password: hashedPassword, }); - await user.save(); + const payload = { + email: user.email, + id: user._id, + accountType: user.accountType, + }; + + let token = jwt.sign(payload, process.env.JWT_SECRET, { + expiresIn: "2h", + }); + + // creating a session + const session = new Session({ + userId: user._id, + token, + }); + await session.save(); + + user.password = undefined; + + res.cookie("token", token, { + httpOnly: true, + secure: true, + maxAge: 3600000, + }); return res.status(200).json({ success: true, - message: "User created succesfully", + message: "User created successfully", + token, + user, }); } catch (error) { console.error(error); return res.status(500).json({ success: false, - message: "USer can not be registred", + message: "User cannot be registered", }); } }; diff --git a/src/App.js b/src/App.js index 87fc149..0e1f1ce 100644 --- a/src/App.js +++ b/src/App.js @@ -1,6 +1,6 @@ import React from 'react'; import './App.css'; -import { Route, Routes } from 'react-router-dom'; +import { Route, Routes, Navigate, useLocation } from 'react-router-dom'; import Home from './pages/Home'; import Login from './pages/Login'; import Signup from './pages/Signup'; @@ -14,13 +14,10 @@ import Loader from './components/Loader/Loader'; import ForgotPassword from './pages/ForgotPassword'; import ResetPassword from './pages/ResetPassword'; import { ThemeProvider } from './themeContext'; - import ContactUs from './pages/ContactUs'; - -import { AuthProvider } from './authContext' +import { AuthProvider } from './authContext'; import EditProfile from './pages/EditProfile'; - const Layout = ({ children }) => { return ( @@ -30,32 +27,70 @@ const Layout = ({ children }) => { }; function App() { + const usertoken = localStorage.getItem('usertoken'); + const token = localStorage.getItem("token"); + const canteenId = localStorage.getItem('canteenId'); + const hasAnyToken = token || usertoken; + return ( -} /> - } /> + } /> + } /> } /> } /> } /> - } /> - } /> + {token ? ( + } /> + ) : ( + } /> + )} + + {token ? ( + } /> + ) : ( + } /> + )} + + {usertoken ? ( + } /> + ) : ( + } /> + )} + + {usertoken ? ( + } /> + ) : ( + } /> + )} + + {hasAnyToken ? ( + } /> + ) : ( + : } /> + )} + + {hasAnyToken ? ( + } /> + ) : ( + : } /> + )} + + {hasAnyToken ? ( + } /> + ) : ( + : } /> + )} - } /> -