From 3db6ef59ee2e2d2bb5fe5a932f408c33b3d481ef Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <166854304+Jaime1108@users.noreply.github.com> Date: Wed, 29 Oct 2025 21:58:13 -0500 Subject: [PATCH 1/9] Create navbar.tsx --- src/components/navbar.tsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/components/navbar.tsx diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx new file mode 100644 index 0000000..0b6db0a --- /dev/null +++ b/src/components/navbar.tsx @@ -0,0 +1,20 @@ +import Link from "next/link"; + +export default function Navigation(){ + +} From 3ba6477b511bfb160717376e9eafbaa3129b059c Mon Sep 17 00:00:00 2001 From: James Nguyen Date: Thu, 30 Oct 2025 11:05:30 -0500 Subject: [PATCH 2/9] Update navbar.tsx --- src/components/navbar.tsx | 66 +++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx index 0b6db0a..3aa8191 100644 --- a/src/components/navbar.tsx +++ b/src/components/navbar.tsx @@ -1,20 +1,54 @@ import Link from "next/link"; +import Image from "next/image"; // Optional: if using Next.js Image optimization -export default function Navigation(){ - + + ); } From b388d18f433a5e319d58ca06116841484db4162b Mon Sep 17 00:00:00 2001 From: James Nguyen Date: Thu, 30 Oct 2025 11:05:38 -0500 Subject: [PATCH 3/9] Update layout.tsx --- src/app/layout.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..0509279 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -13,8 +13,8 @@ const geistMono = Geist_Mono({ }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Learning with ACM", + description: "ACM learning platform built with Next.js and Tailwind CSS", }; export default function RootLayout({ From cb5b3cdc2a1fc6fa1347bfb3576f57da4632f3fc Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <166854304+Jaime1108@users.noreply.github.com> Date: Thu, 30 Oct 2025 18:11:08 -0500 Subject: [PATCH 4/9] Add user authentication state to navbar and homepage Introduced user authentication state handling in the navigation bar and homepage. The Navigation component now accepts isSignedIn and User props to display user-specific options and avatar. Added mock user data and updated the homepage to use the new Navigation component. Added user and profile images to the public directory. --- public/frieren.jpg | Bin 0 -> 8991 bytes public/user.png | Bin 0 -> 24852 bytes src/app/page.tsx | 180 ++++++++++++++++-------------------- src/components/frieren.jfif | Bin 0 -> 8991 bytes src/components/navbar.tsx | 58 ++++++++++-- 5 files changed, 133 insertions(+), 105 deletions(-) create mode 100644 public/frieren.jpg create mode 100644 public/user.png create mode 100644 src/components/frieren.jfif diff --git a/public/frieren.jpg b/public/frieren.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ce099ffb5d1ffb0267df399a1d8a65605c4f343d GIT binary patch literal 8991 zcmb7IRZtuNkKP5!0tJdY%NCbHai>6m#oZl>6sNemyGwB`PLXBt;$B>eyR#H2Qv7=V z+}zAPUNV!1B$MxZ$Rv}zEWT_4aO9w}Pyi4J0093f;AI663P48%;o;#C;^W~F5fKs* z5)=N%5D^m+lMoRT6BCjUlTb23NXY0Y2?^hFyrpAeVPj(>rsCq~ddJ7e%Eki3z`(%9 z!Y0GPA!DVYq+|Vm%S$%^7Y(ol*g^(U1CVfm$hg3legOGDj<5ck>Hi7}015dODiHK9 zD31d`0wN(JqoJZBp&+Az{^cU!0+8|Ea-fK-zQU(AbqY!me%;Tn=s4EtA%6bL{D{vV`&)sRtM{R=VS{_`Ut0a1WRp#P!r z59loi9x|u6D*i`PYOYWJka`GSmI0W^|1xoraRH(L^3NdBIL0kI?RRJt*6dk-8pa&u zCC4aT*YY;;d1x^r8ME|7==!UD7-Q@~%oITeKB3mo=irg|ioBP5H7FS}6W@GhSQK1# zQl^vC5Jlm9G*Jvk0aTiRuv2;haE*7xkgZD%S zMBBkWzRR5NGry=!)91VWn}n#c+J&7{@Z&SLbN;J#=M=|A7ex)Z8`r`vMJY!sHjk7% zsjNA7Mv??u%xhAWg;vEMQ=rkfCKz20DOFqF-j6g`hwHIW#St(hK&IZPV@~d*BWbA+ z8qqy={1rSRaLaKw>BeW-#(;g+fGy=&NM0mPAwKq2PE~RyYxfuZcd5qx)LHs=b%pyq zPHQ#LFUw+r;~H%2+FANEh##{(GxB880KI2nO@~Im%!;_<*M3xg z*TK|;S#XxMMACQ$OS=6QSkSj#a5!gZz;hq8TuVTo;*ZT2yJUc zrix1uLKiG|Yelg5aP3T~^04*jsdKyhuvLXxmWCIWa8rp!91I_T(cC_=PkSU05WLA! zbnpD#^)$iCvU9(sXo4BiZymY^hDNqa#PH3QcG#5az2Lg&efOp3@*pVXUmfnlgskkZ`-7UlI1*=JI5GJb3q~CMx`iZSJ zrrNMQk)^yH!^K%%`x#unxul1fTPc?5T#Jdg6D;q)?8lj~&d}iEO4G%`I2IekgcG{EqH$ zL&0&S#4P&td16v?Vz#xRIpW-p^@`z zLW*%MpFoM3oU5XW$_ucWSyr;@Fu-3dX#V|rM}1wV-J?nR5OiN|IdS+<9-xo*0#KMm z^dZc6KFq8+j=SmKm*+--6eE`1MKcOB97xZ&d51Sy!v$R=J<_!QzAd@|c)@bNyu0bn z7ep7)zJ%2`gh;o~-V#z~_lHqMS2GF?9i5)<|Nc8(e#xqUg__Gfif_HVXkjmbXM$&H zX>y3p?{UbduqU&&Op$(gEXeX~h82J@f?x=vvPKF-4Fm{PR++S7asW}amQdg#zjwu= zxN>lR%~S=cCJosLElAjwPsK^=h%O2p%h^W#TWy$NO4m4T{~aZ{NmPL`r&NXDlB>qy zAZn#;Oi{}{LQXQEPCwK{p~s2=JHntLioS$*6hOAkIQ4N$z~NPHL>h~=dCqx;z$dd= zjuQM#(wtDtajn^sn={jP>svhSDvoGhoP+_rdY!5VB*eS*cb z(GUfjUnB40d9aL4Jr#M>8uJZIcmb42b2+uZ8~lw=QP(-FTHMSf&b!C>xLj%68pt}E zpy#K$jA}Tjj9#&x_8!UZ)W&~`!PiCzdQ9Kw!P~1(AQq{)TGhw;Fd4ojjqojEj}o+b zGg@n|>usy2F|~OlXR|~lXWb|lhy1Nwu@oAmaw~YuUb06zC#2Y87dfXPotpVIkj8_o zMypR3V_(WmH*z$td4_OI>*FqWb*(gM;O_b|gWEjSa}2|Q$_kaj!Eb$IWT&ojbpcVn zWxdbfDTK&OIq_AH+R}9`RY!3T!Q=53V7X0*i!+KhB#|%45wDKYQv&m|9Na^wWzRm}GS6v_gCvp`)ie_%;tB!wy-kzqlKx)r^MUXIGX+Tx zn+>l!uO~9Tl3PpGPiUz`{$rw`xFhZY7o6{N>V&uBteuaXfs~IOsg7JyAt7G?!@ExO z65GIER_qzSS?ea0@pKX)*zZg=rFFqP`CUirqpfCIhudL%=sAVX%_Q+Ym(lpMPsw|O zjhyzcgD_m%9EN{lVn&jPktOR!Smh;L^89oU7|^#h%To&;f$MPMoK(3=vdH2m=ke&} zziXHnE1&6NL)^Mswy+gw!TU;jyrq<-`6oQI8dDtQ8E>j5Ld|Q%hWAARm`Ch$V$AZo znktzrVVam|IMuIX3mVNizK~LkTi*#ku~WQzGw(Ec6`lQd?IdZnBDVn;Y!XRJk^7mW zRO>VYH2=La{LQ*k1p>sjw8`|?>=tFNtNxRlKR!le%!*SmsRlV11#8KvqUvf($~E%a zb}doKocm-mj%3~oV80r1Di(X|xTXu|e$ba^gjm_^%Zy<)(S<>_%Mtb_z?@u+7XTsA ze0@4ejSzAt2kutimY%{_{|{a@L>zMU9ShSh0I%(UERCD4o+nv0!+wunN(8ZzNG`}; z2(m0Eoryx*SYsT#DS|i-fUJ&CWdHK+XZI$pi|(q@J@feJb~h82{lC(=(jI9B@xiY) zbxT5qFoNIgSC&s=^J(2Eq5mE%Nm`)Q@NoBOWbsN+e=X641NWu*Q8(pcvB-{gK#sUC z6g#Z^b|=WVAv@CxP6y0#eF>iZR{QzOdATD3AuZGTD2aVuSJvCMAS?CO3^@gZT9R`c z;255d!-TlvU0;ZxYbiO$e3Qt7J(>Ewq2C=#`zoz)NqqQVC0ELd6`okA+29EP_>YmC zpOfm%_w7Qp}Ir*y?RH0s`C=bvC8_RD>Kz$6XbVdYiJ&wdmYnFX1R>I0KziQJ6bK{qx1gd0Wr0!o9$|~T~;rPV1O`~oFrGf4cOC{1=G*pl-dE{vF zv~gW6dmW0o$pxx71sVj$16PrpdH54L3%@)UFKJX?WR9Rig~|)S+nr=>sV!H*if!#U zsPn5fOrh?vu+mYQji}45Ugqr=i=x-=-KPVuUI3J0aIc4sbx-1=A*Y;0YzAyK?*2X+ z0>7$=N2zNSEhK6%fBNDef1uN|gft>Hje;b%}J3lwx|yIrw21W+F{}rfg5X7qiLrQ?HbS^ZM%?lyTA#3tjX0)MMYGf<2!QoErBD zcLqQ(`OStTj`O0hhF15stzsFiSI(|@^B7I1Ldp9EX#il%@G;#bxhUD}d*HfTfgeTtWKa`DJaM)e7v0)adO(M#KD_*bjy0zxn>WX!4}7nun8SKAR>?+j>81^e8dpyK z9w*sbu$S6faZ6c~;2L-+lnPw6!fLk9#IUiSInR#y*o0s6rp_KElRln0r(Ihd?OVe% zX6oWMD<;X=SZ%ZtOVd*2EDaF&2AKXWdf8s8Xo@s=8}L-b6%B;5lyTV~tnrAfXf|z5{iPQsu=q54ov(n5EqMr@t2-^!(D5aNFhpd##*Zkx}$Dzj0km|#j| zyMh+BHU`b@u}?{04yod5lM|+6*b}A0EtdpbWrY_xdND}mux3@0!!|~y+f}YngGJRC z&&upcO|2NvCxG;5kXu7O` zF~mP_a}lgtC1_5Xxeg`N9Ed3}X~?^VU_x@yINxYo9E;4VjRVRp_Gk~tX88FuCD=jS zAc-?yT8dKh51M;bS|vOKY9eNkw9zk>$CD@)qzbv++wMjh2fSAufkmSQ>R-G2^^YhK zdRq?bg0qQLe)WDj#+GVs*XXjBSqalk?e@gEBJAoBmFd%fu?lLB6E(zoV?qZSg1L)* zPNs6&*UF=WWh#%~(Xv{F%pi-#J`~jXlM*%g=FI za&1Gnbgsk00v37>>3fM%nSq>qju9mWnju2b_?b^%TYHpm+n*Tjz&(u3FI`vNy%uC70P}$B1pm@ z$jGCeMod_<3fR>g+()scKs)E;Q(MB>BGE%jgG9-yhbA^Ma}Fb+dTSUcnb#9kHk<4b zdDz<9RWa0HlA0tF9Dw+98BZLAB2QxZh%rrEQ00&qTMFMJ?9y!18wCG!zZe%`xS7(uGrJUJLM^} zCZZgbLrm?=4HIXoQ9r_DK`JumMK_+^v^K?CihHV831@tRx%F%xU3)(e+MxR{8KfrB z1M$C=jlIVRU|1r4PyM^Uio5{ZX~XWR0`*pS(`7#YFugkOz+~nzE5+6^Tl&yXdMTthHY6*)UGFRWs`OK z+T-vKxNI3bxlZK~x%Qom+B%a>Z8?2fTWC*)ED4`uPVCp)$cxGcijIP==?<<>q_q+l zv70B5ynCt{>Fk0pV!pa%H_>IZA%Y1UkI|FwT4xo$q&vWU)8H`!t4uhATv16;&6I+l zs>9Uo*^0jooVHV8M_hT$PjSa6EyzAmTf8Hzf${~LXTIzA>-+>;v42E6LlpA`GVJNR zmOXwuyc3p7n_K}3sOBu#9Ir~PHB9_De(R?(@d+v(Zs_JWtWOs6>8u)2c77pshNJX% zt<;jVQES#IclJ-_pBmz#2j%Z}4=0PxrmH5;f@+su6a0kkzj*6!?N`rWDxyak7gees zPmlOLWudnYNcDGho~lIqC?`Lf%+tuwgfZtArW;v0;atUx!IGbV2dw_JTss<{YT-Wl zlH^OlJ~$(nU^mh zqT=E{qGzt7Z{Q3)I4Z5cQ3M19dRN5it#4YqK*2S+rE^k__ERPFD&h7=#&+1>i+gW| ze{apjo9zAo?y5;9wMQ<5zp#JyhJ>Hi@4Knyn|g=SUeHRws!f2z8>z0&Yr|1q^v*An z|2$S1TJ@s=lonn(<0}y{^%va642am{IzG&akoSVbsnRo|9sWE8yAoH{f~LlSHCgo| z*X>Xj;x+M|K<3BFjp_F_j!p@2-Ts>5Bic??qRmeEe@Lrd0Fr+0F94
yVkRHc>m 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 literal 0 HcmV?d00001 diff --git a/src/app/page.tsx b/src/app/page.tsx index a932894..3840e14 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,103 +1,87 @@ import Image from "next/image"; - +import Link from "next/link"; +import Navigation from "@/components/navbar" +const stats = [ + { value: "120+", label: "Interactive lessons" }, + { value: "30K", label: "Learners enrolled" }, + { value: "92%", label: "Course completion rate" }, +]; +const features = [ + { + title: "Practice-first approach", + description: + "Build real applications with guided walkthroughs, code reviews, and community feedback.", + detail: "Every module ends with a practical milestone project.", + }, + { + title: "Mentor office hours", + description: + "Drop into weekly live sessions to ask questions, pair program, or get portfolio help.", + detail: "Sessions are recorded so you can revisit the tricky bits later.", + }, + { + title: "Career toolkit", + description: + "Access templates, interview drills, and resume reviews tailored for first-time developers.", + detail: "Gain confidence before you send that first application.", + }, +]; +const courses = [ + { + title: "Foundations of Web Development", + level: "Beginner", + duration: "6 weeks", + description: + "Learn the core building blocks of the web with hands-on HTML, CSS, and JavaScript challenges.", + }, + { + title: "Modern Frontend with React", + level: "Intermediate", + duration: "8 weeks", + description: + "Create interactive interfaces, manage state like a pro, and ship performant React apps.", + }, + { + title: "Backend APIs with Node and PostgreSQL", + level: "Intermediate", + duration: "7 weeks", + description: + "Design secure REST APIs, connect to databases, and deploy production-ready services.", + }, +]; +const testimonials = [ + { + name: "Shannon, Career Switcher", + quote: + "CS-Learn helped me close the gap between tutorials and building real products. I landed a junior role two months after finishing the program.", + }, + { + name: "Luis, College Student", + quote: + "The mix of guided lessons, projects, and mentor feedback kept me accountable. My portfolio finally feels job-ready.", + }, +]; export default function Home() { - return ( -
-
- Next.js logo -
    -
  1. - Get started by editing{" "} - - src/app/page.tsx - - . -
  2. -
  3. - Save and see your changes instantly. -
  4. -
+ var isSignedIn = false; + var mockUser = null; - -
- + /*if testing just commented out this block of code */ + isSignedIn = true; + mockUser = { + name: "Frieren", + email: "Frieren@gmail.com", + avatar: "frieren.jpg", + profileHref: "/profile", + coursesHref: "/user/courses", + historyHref: "/courses/history", + } + /////////////////// + + return ( +
+
+ {} +
); -} +} \ No newline at end of file diff --git a/src/components/frieren.jfif b/src/components/frieren.jfif new file mode 100644 index 0000000000000000000000000000000000000000..ce099ffb5d1ffb0267df399a1d8a65605c4f343d GIT binary patch literal 8991 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
yVkRHc>m z-tt(-)4L>I>=oZaUEhWTabfgTIy-DDI|;v1IH6G!9J&S7&A;VA$wlqCQLdOD5Ne`S zN6ZCZ807Jzf-6pMlrxNu{T@7n$i4`p{RHnQa8dm5&pv1TWA>-=I6w7_sN)h6%Pg&< z%F!>&Ze^#LZrH|t2pxlUHb#+DY;@m*B>g>)ZZVdv`>wPKJN`xlpw0OMV&yum1lUlP z@2w79k*QeFsE-;nStIySNwy4FllZ@C4DJu-qE{m4a!=h*1Vf9ts*~7u{11`h`?pvM z0kOlJvb5u)>gd_ zmzMh6;Dx-4?`uNSZo_T&U%8ldMmZr<>j@#_2p1LY+BfDl#QS|JCfVGf2lEiqu*XD- z-g#jC*o*>0CjD$FdT;2{xLSW>@3nM$0kv0CFk{PPC+kCf<5cXjTDHDC7kq!xbQvC> zG3{3l`ggAAy1tjFz6{(?%I2j;1J7I;_XH7w-XnrftBr=gZhk{|?EToaN#mztHzD;@ zIX(S;+t~e*b%!eMw^mv524#$Sg5Gj6pJi)w48KC#zVMLMGJuwySsW63Nkh%O!vp#o zdJ~am=zKs=*fxrirSlg68Q-CF%TUC%zR9448x5$_WK_lYNB&Osx4iX<#{*7P z3L^yCfkZWOm6sTt9?HfPsp<8O@HKuOhrU%$x9#)3aWbk|`-+O*++P-@G->TSWOT%~ z4wOfRFquG20_m;8S*+UQ_Xc;I9+7d%F2h8wDG3{w4(!WG*Wf`iFM!Hu2=47*L_#RK z=te&nwQ-cM_oB>(vP}5L$z#MsX*pY7hKVuXa0(OPIkv!gGAr+78@Eo=Cnd z+3Z2<(h<^oGQQu;LCx_IgKZpGn>V|@(ieuc(Q-2z)7iU*OszGIV7%Bsi^YR(P56ji z?Q}p$jJ9-#W=-8WEaFFFPJ$2iOt^D!sDtpn^;Hy|_}6RsnhXKQ*RXm@6Rns}_pn>(-o{R@%J*{bESrS` zu%)kB9iOMF_ct7iHr6ln{q^BkMaoNWV~;}3UjPN2X7Jq@OE*&d{)%9qZJ!g0>nR zBf`gsdY4!YY_b$-=L|Z1_#VC6_bYi96=Q8NXBO`DS8-=l zQB~wrD!K5kIdRPgoqOnQ!eG2sjFvR)W+=4litOm#Is@MDBejBf)h}J(`bxEfZl$;V z@OqWczInqKKYApd!sobe)-ZFlEsEcDCv;y(#`=*^y>5j+104kbNU-Zj;41s0_e*#o zFaBG;YK^c;gq2~@PX%!Fi<3!?u4c7L%8Fqv8lAA)c=>%PU?jX>JQ*#xrtrg9 zd=VEV6#GI;eAa5DXblnQSnuMB+j4h=UuxhSLC4y!(#nY@F^6I*qU+)7LX1eGqcn*V zU+0g9T$Ea7$?rW)EW3NaO&73FH*Y9k0N~0u+Gof;vd{HeKB9~bvDmN1eCGd%^gm+W zYC17HaENJotDq;-Zjp|>0LlhS^*gm4^P+Ok-*_eDewYY$i+%8zBR4X^rWbbpnscg`AwQ45d?WK* zsJAZPF2wBDTimwREozfM*5PB3zufQl*~XXr1;B&*vHo7;1;BQYqW5f7sK;gCoSWw) zM%HE^KBvopys82|Zd}4FN-ET(X?UdtI$Shs?Y@u}-|tP>{WFzd-f+u;(^c|5&O&$Y zmH{hjx5z9hTg;}1P->E=QAUdx^sxZ<;CKj=CCzNn$gGgyiRI`i8y^jen9 zW%v>4=zEZ26`xS8i<0rAL&tCRNlr&MdXEZj(n(g<9pmt=OWp(EG#49_BU)|s(bpnX zijC&_RblPoWFh@tf2USJG<5I*x=brQL6JaUzHSw+QVm5vOH+?ruzN&@#k7yX%{zc7 z7t%YOpH?oD*_bc?1B623ba#vf&HQC!-8LEf! zlG5paM5E?A>vgR%5aOBCj7#5~Qr|&tkhai32=Vmh?BjLsMZV!D4I*(l=HVP*=^3~9 zsbjF4-N#-yxE)H-j_IYS;e0D#xta!P6r**dq&bhjXPYG$C(T%+`wYYKIWpdjd9ViM zlGu-4?OtUfnE=U5Cu?KPVV|8di&(R8yV$nT{|4!S#Xs3?DBdN_N3Y}Vhc_ykuNa_= zzd*@PF6a?JVLp+4Kn9n1x1{Hki7r_Kbq( z>piKss}gOY61-(`sgx(q8~0<6^Ml<_EFn?yA@zxjf8g^H@Kt1U>ox!Gi{*F!8rOd0 zedfbLYQW#Mh-XN7d6iA+RgC#y!O`2Alx|^Dhp8U1+sggIWrR!Q2uCEYF!s(eCipmp zk6UNWu-+&-@9UUqzA9OC{tW(ASEx!(Dk57iGX6`lG?E07(Y%|}VsFR`0Op{wFM;E& zP^kUG{I51|t*-To=U6}k)dl>i>4KnY%=`hG<{EJDwDjzCwGbU)I~Cw_q*gKyKW%@dYq%_}8AtMJ`RB%gg2Y zcBn#U)S+L|Ng}Plvy*L YYWxM@(9zko^IXSWp;r5g
From 47d6b6665a074503d38f063d52e843fb387c9630 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <166854304+Jaime1108@users.noreply.github.com> Date: Thu, 30 Oct 2025 18:14:58 -0500 Subject: [PATCH 5/9] delete some info --- src/app/page.tsx | 61 +----------------------------------------------- 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 3840e14..adfb59a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,66 +1,7 @@ import Image from "next/image"; import Link from "next/link"; import Navigation from "@/components/navbar" -const stats = [ - { value: "120+", label: "Interactive lessons" }, - { value: "30K", label: "Learners enrolled" }, - { value: "92%", label: "Course completion rate" }, -]; -const features = [ - { - title: "Practice-first approach", - description: - "Build real applications with guided walkthroughs, code reviews, and community feedback.", - detail: "Every module ends with a practical milestone project.", - }, - { - title: "Mentor office hours", - description: - "Drop into weekly live sessions to ask questions, pair program, or get portfolio help.", - detail: "Sessions are recorded so you can revisit the tricky bits later.", - }, - { - title: "Career toolkit", - description: - "Access templates, interview drills, and resume reviews tailored for first-time developers.", - detail: "Gain confidence before you send that first application.", - }, -]; -const courses = [ - { - title: "Foundations of Web Development", - level: "Beginner", - duration: "6 weeks", - description: - "Learn the core building blocks of the web with hands-on HTML, CSS, and JavaScript challenges.", - }, - { - title: "Modern Frontend with React", - level: "Intermediate", - duration: "8 weeks", - description: - "Create interactive interfaces, manage state like a pro, and ship performant React apps.", - }, - { - title: "Backend APIs with Node and PostgreSQL", - level: "Intermediate", - duration: "7 weeks", - description: - "Design secure REST APIs, connect to databases, and deploy production-ready services.", - }, -]; -const testimonials = [ - { - name: "Shannon, Career Switcher", - quote: - "CS-Learn helped me close the gap between tutorials and building real products. I landed a junior role two months after finishing the program.", - }, - { - name: "Luis, College Student", - quote: - "The mix of guided lessons, projects, and mentor feedback kept me accountable. My portfolio finally feels job-ready.", - }, -]; + export default function Home() { var isSignedIn = false; var mockUser = null; From 79af7c2e7530ebe1ae6da2c467a5f873a696d085 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <166854304+Jaime1108@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:04:50 -0500 Subject: [PATCH 6/9] replacing with the shadcn components --- components.json | 22 + package.json | 20 +- pnpm-lock.yaml | 756 ++++++++++++++++++++++++++++ src/app/globals.css | 122 ++++- src/app/page.tsx | 4 +- src/components/frieren.jfif | Bin 8991 -> 0 bytes src/components/navbar.tsx | 112 +++-- src/components/ui/avatar.tsx | 53 ++ src/components/ui/button.tsx | 60 +++ src/components/ui/dropdown-menu.tsx | 257 ++++++++++ src/lib/utils.ts | 6 + 11 files changed, 1363 insertions(+), 49 deletions(-) create mode 100644 components.json delete mode 100644 src/components/frieren.jfif create mode 100644 src/components/ui/avatar.tsx create mode 100644 src/components/ui/button.tsx create mode 100644 src/components/ui/dropdown-menu.tsx create mode 100644 src/lib/utils.ts diff --git a/components.json b/components.json new file mode 100644 index 0000000..761072a --- /dev/null +++ b/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/app/globals.css", + "baseColor": "zinc", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/package.json b/package.json index a49d9b4..5d83641 100644 --- a/package.json +++ b/package.json @@ -12,16 +12,23 @@ "db:studio": "drizzle-kit studio" }, "dependencies": { - "react": "19.1.0", - "react-dom": "19.1.0", - "react-hook-form": "^7.63.0", - "zod": "^4.1.11", "@libsql/client": "^0.15.15", + "@radix-ui/react-avatar": "^1.1.10", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-slot": "^1.2.3", + "better-auth": "^1.3.26", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", "drizzle-orm": "^0.44.6", + "lucide-react": "^0.552.0", "next": "15.5.4", "next-safe-action": "8.0.11", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-hook-form": "^7.63.0", + "tailwind-merge": "^3.3.1", "web": "link:@libsql/client/web", - "better-auth": "^1.3.26" + "zod": "^4.1.11" }, "devDependencies": { "@eslint/eslintrc": "^3", @@ -31,10 +38,11 @@ "@types/react-dom": "^19", "dotenv": "^17.2.3", "drizzle-kit": "^0.31.5", - "tsx": "^4.20.6", "eslint": "^9", "eslint-config-next": "15.5.4", "tailwindcss": "^4", + "tsx": "^4.20.6", + "tw-animate-css": "^1.4.0", "typescript": "^5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 46b4b88..a790082 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,12 +11,30 @@ importers: '@libsql/client': specifier: ^0.15.15 version: 0.15.15 + '@radix-ui/react-avatar': + specifier: ^1.1.10 + version: 1.1.10(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-dropdown-menu': + specifier: ^2.1.16 + version: 2.1.16(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': + specifier: ^1.2.3 + version: 1.2.3(@types/react@19.1.13)(react@19.1.0) better-auth: specifier: ^1.3.26 version: 1.3.26(next@15.5.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + class-variance-authority: + specifier: ^0.7.1 + version: 0.7.1 + clsx: + specifier: ^2.1.1 + version: 2.1.1 drizzle-orm: specifier: ^0.44.6 version: 0.44.6(@libsql/client@0.15.15)(kysely@0.28.7) + lucide-react: + specifier: ^0.552.0 + version: 0.552.0(react@19.1.0) next: specifier: 15.5.4 version: 15.5.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -32,6 +50,9 @@ importers: react-hook-form: specifier: ^7.63.0 version: 7.63.0(react@19.1.0) + tailwind-merge: + specifier: ^3.3.1 + version: 3.3.1 web: specifier: link:@libsql/client/web version: link:@libsql/client/web @@ -72,6 +93,9 @@ importers: tsx: specifier: ^4.20.6 version: 4.20.6 + tw-animate-css: + specifier: ^1.4.0 + version: 1.4.0 typescript: specifier: ^5 version: 5.9.2 @@ -437,6 +461,21 @@ packages: resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@floating-ui/core@1.7.3': + resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} + + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} + + '@floating-ui/react-dom@2.1.6': + resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + '@hexagon/base64@1.1.28': resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==} @@ -786,6 +825,294 @@ packages: '@peculiar/x509@1.14.0': resolution: {integrity: sha512-Yc4PDxN3OrxUPiXgU63c+ZRXKGE8YKF2McTciYhUHFtHVB0KMnjeFSU0qpztGhsp4P0uKix4+J2xEpIEDu8oXg==} + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-avatar@1.1.10': + resolution: {integrity: sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-is-hydrated@0.1.0': + resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} @@ -1090,6 +1417,10 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + aria-query@5.3.2: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} @@ -1224,9 +1555,16 @@ packages: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} + class-variance-authority@0.7.1: + resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} + client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1302,6 +1640,9 @@ packages: resolution: {integrity: sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==} engines: {node: '>=8'} + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -1663,6 +2004,10 @@ packages: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + get-proto@1.0.1: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} @@ -1992,6 +2337,11 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + lucide-react@0.552.0: + resolution: {integrity: sha512-g9WCjmfwqbexSnZE+2cl21PCfXOcqnGeWeMTNAOGEfpPbm/ZF4YIq77Z8qWrxbu660EKuLB4nSLggoKnCb+isw==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + magic-string@0.30.19: resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} @@ -2207,6 +2557,36 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.1: + resolution: {integrity: sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + react@19.1.0: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} @@ -2385,6 +2765,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + tailwind-merge@3.3.1: + resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} + tailwindcss@4.1.13: resolution: {integrity: sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==} @@ -2428,6 +2811,9 @@ packages: resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==} engines: {node: '>= 6.0.0'} + tw-animate-css@1.4.0: + resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2469,6 +2855,31 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -2750,6 +3161,23 @@ snapshots: '@eslint/core': 0.15.2 levn: 0.4.1 + '@floating-ui/core@1.7.3': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.4': + dependencies: + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/react-dom@2.1.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@floating-ui/dom': 1.7.4 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + + '@floating-ui/utils@0.2.10': {} + '@hexagon/base64@1.1.28': {} '@humanfs/core@0.19.1': {} @@ -3092,6 +3520,266 @@ snapshots: tslib: 2.8.1 tsyringe: 4.10.0 + '@radix-ui/primitive@1.1.3': {} + + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-avatar@1.1.10(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-context': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.13)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-context@1.1.2(@types/react@19.1.13)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-direction@1.1.1(@types/react@19.1.13)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.1.13)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-id@1.1.1(@types/react@19.1.13)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.13)(react@19.1.0) + aria-hidden: 1.2.6 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-remove-scroll: 2.7.1(@types/react@19.1.13)(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@floating-ui/react-dom': 2.1.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/rect': 1.1.1 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + + '@radix-ui/react-slot@1.2.3(@types/react@19.1.13)(react@19.1.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.13)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.1.13)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.1.13)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.1.13)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.1.13)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.1.13)(react@19.1.0)': + dependencies: + react: 19.1.0 + use-sync-external-store: 1.6.0(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.1.13)(react@19.1.0)': + dependencies: + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-use-rect@1.1.1(@types/react@19.1.13)(react@19.1.0)': + dependencies: + '@radix-ui/rect': 1.1.1 + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/react-use-size@1.1.1(@types/react@19.1.13)(react@19.1.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.13)(react@19.1.0) + react: 19.1.0 + optionalDependencies: + '@types/react': 19.1.13 + + '@radix-ui/rect@1.1.1': {} + '@rtsao/scc@1.1.0': {} '@rushstack/eslint-patch@1.12.0': {} @@ -3383,6 +4071,10 @@ snapshots: argparse@2.0.1: {} + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + aria-query@5.3.2: {} array-buffer-byte-length@1.0.2: @@ -3543,8 +4235,14 @@ snapshots: chownr@3.0.0: {} + class-variance-authority@0.7.1: + dependencies: + clsx: 2.1.1 + client-only@0.0.1: {} + clsx@2.1.1: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -3611,6 +4309,8 @@ snapshots: detect-libc@2.1.1: {} + detect-node-es@1.1.0: {} + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -4097,6 +4797,8 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 + get-nonce@1.0.1: {} + get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 @@ -4412,6 +5114,10 @@ snapshots: dependencies: js-tokens: 4.0.0 + lucide-react@0.552.0(react@19.1.0): + dependencies: + react: 19.1.0 + magic-string@0.30.19: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -4614,6 +5320,33 @@ snapshots: react-is@16.13.1: {} + react-remove-scroll-bar@2.3.8(@types/react@19.1.13)(react@19.1.0): + dependencies: + react: 19.1.0 + react-style-singleton: 2.2.3(@types/react@19.1.13)(react@19.1.0) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.13 + + react-remove-scroll@2.7.1(@types/react@19.1.13)(react@19.1.0): + dependencies: + react: 19.1.0 + react-remove-scroll-bar: 2.3.8(@types/react@19.1.13)(react@19.1.0) + react-style-singleton: 2.2.3(@types/react@19.1.13)(react@19.1.0) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.1.13)(react@19.1.0) + use-sidecar: 1.1.3(@types/react@19.1.13)(react@19.1.0) + optionalDependencies: + '@types/react': 19.1.13 + + react-style-singleton@2.2.3(@types/react@19.1.13)(react@19.1.0): + dependencies: + get-nonce: 1.0.1 + react: 19.1.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.13 + react@19.1.0: {} reflect-metadata@0.2.2: {} @@ -4856,6 +5589,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + tailwind-merge@3.3.1: {} + tailwindcss@4.1.13: {} tapable@2.2.3: {} @@ -4903,6 +5638,8 @@ snapshots: dependencies: tslib: 1.14.1 + tw-animate-css@1.4.0: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -4981,6 +5718,25 @@ snapshots: dependencies: punycode: 2.3.1 + use-callback-ref@1.3.3(@types/react@19.1.13)(react@19.1.0): + dependencies: + react: 19.1.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.13 + + use-sidecar@1.1.3(@types/react@19.1.13)(react@19.1.0): + dependencies: + detect-node-es: 1.1.0 + react: 19.1.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.1.13 + + use-sync-external-store@1.6.0(react@19.1.0): + dependencies: + react: 19.1.0 + web-streams-polyfill@3.3.3: {} which-boxed-primitive@1.1.1: diff --git a/src/app/globals.css b/src/app/globals.css index a2dc41e..97afb5e 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,122 @@ @import "tailwindcss"; +@import "tw-animate-css"; -:root { - --background: #ffffff; - --foreground: #171717; -} +@custom-variant dark (&:is(.dark *)); @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); --font-sans: var(--font-geist-sans); --font-mono: var(--font-geist-mono); + --color-sidebar-ring: var(--sidebar-ring); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar: var(--sidebar); + --color-chart-5: var(--chart-5); + --color-chart-4: var(--chart-4); + --color-chart-3: var(--chart-3); + --color-chart-2: var(--chart-2); + --color-chart-1: var(--chart-1); + --color-ring: var(--ring); + --color-input: var(--input); + --color-border: var(--border); + --color-destructive: var(--destructive); + --color-accent-foreground: var(--accent-foreground); + --color-accent: var(--accent); + --color-muted-foreground: var(--muted-foreground); + --color-muted: var(--muted); + --color-secondary-foreground: var(--secondary-foreground); + --color-secondary: var(--secondary); + --color-primary-foreground: var(--primary-foreground); + --color-primary: var(--primary); + --color-popover-foreground: var(--popover-foreground); + --color-popover: var(--popover); + --color-card-foreground: var(--card-foreground); + --color-card: var(--card); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); } -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.141 0.005 285.823); + --card: oklch(1 0 0); + --card-foreground: oklch(0.141 0.005 285.823); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.141 0.005 285.823); + --primary: oklch(0.21 0.006 285.885); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.967 0.001 286.375); + --muted-foreground: oklch(0.552 0.016 285.938); + --accent: oklch(0.967 0.001 286.375); + --accent-foreground: oklch(0.21 0.006 285.885); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.92 0.004 286.32); + --input: oklch(0.92 0.004 286.32); + --ring: oklch(0.705 0.015 286.067); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.141 0.005 285.823); + --sidebar-primary: oklch(0.21 0.006 285.885); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.967 0.001 286.375); + --sidebar-accent-foreground: oklch(0.21 0.006 285.885); + --sidebar-border: oklch(0.92 0.004 286.32); + --sidebar-ring: oklch(0.705 0.015 286.067); } -body { - background: var(--background); - color: var(--foreground); - font-family: Arial, Helvetica, sans-serif; +.dark { + --background: oklch(0.141 0.005 285.823); + --foreground: oklch(0.985 0 0); + --card: oklch(0.21 0.006 285.885); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.21 0.006 285.885); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.92 0.004 286.32); + --primary-foreground: oklch(0.21 0.006 285.885); + --secondary: oklch(0.274 0.006 286.033); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.274 0.006 286.033); + --muted-foreground: oklch(0.705 0.015 286.067); + --accent: oklch(0.274 0.006 286.033); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.552 0.016 285.938); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.21 0.006 285.885); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.274 0.006 286.033); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.552 0.016 285.938); +} + +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } } diff --git a/src/app/page.tsx b/src/app/page.tsx index adfb59a..081668f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -6,7 +6,7 @@ export default function Home() { var isSignedIn = false; var mockUser = null; - /*if testing just commented out this block of code */ + /*if testing just commented out this block of code S isSignedIn = true; mockUser = { name: "Frieren", @@ -15,7 +15,7 @@ export default function Home() { profileHref: "/profile", coursesHref: "/user/courses", historyHref: "/courses/history", - } + }*/ /////////////////// return ( diff --git a/src/components/frieren.jfif b/src/components/frieren.jfif deleted file mode 100644 index ce099ffb5d1ffb0267df399a1d8a65605c4f343d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8991 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
yVkRHc>m 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 YYWxM@(9zko^IXSWp;r5g
  • - - Categories - + +
  • +
  • +
  • {isSignedIn && User ? ( <>
  • +
  • {/* Profile Pic Placeholder */}
  • - -
    - {/* Replace with actual image */} - {User.name} -
    - + + + + + {User.name?.charAt(0).toUpperCase() ?? "?"} + + + + +

    {User.name}

    +

    {User.email}

    +
    + + + Profile + + + My Courses + + + History + + + + + Logout + + +
    +
  • ) : ( <>
  • + +
  • - -
    - {/* Replace with actual image */} - + + + -
    - + + + + + + + +
  • )} diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx new file mode 100644 index 0000000..71e428b --- /dev/null +++ b/src/components/ui/avatar.tsx @@ -0,0 +1,53 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +function Avatar({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AvatarImage({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AvatarFallback({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..21409a0 --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,60 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2 has-[>svg]:px-3", + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", + icon: "size-9", + "icon-sm": "size-8", + "icon-lg": "size-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Button({ + className, + variant, + size, + asChild = false, + ...props +}: React.ComponentProps<"button"> & + VariantProps & { + asChild?: boolean + }) { + const Comp = asChild ? Slot : "button" + + return ( + + ) +} + +export { Button, buttonVariants } diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..bbe6fb0 --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,257 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function DropdownMenu({ + ...props +}: React.ComponentProps) { + return +} + +function DropdownMenuPortal({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuContent({ + className, + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +function DropdownMenuGroup({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuItem({ + className, + inset, + variant = "default", + ...props +}: React.ComponentProps & { + inset?: boolean + variant?: "default" | "destructive" +}) { + return ( + + ) +} + +function DropdownMenuCheckboxItem({ + className, + children, + checked, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function DropdownMenuRadioGroup({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuRadioItem({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function DropdownMenuLabel({ + className, + inset, + ...props +}: React.ComponentProps & { + inset?: boolean +}) { + return ( + + ) +} + +function DropdownMenuSeparator({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function DropdownMenuShortcut({ + className, + ...props +}: React.ComponentProps<"span">) { + return ( + + ) +} + +function DropdownMenuSub({ + ...props +}: React.ComponentProps) { + return +} + +function DropdownMenuSubTrigger({ + className, + inset, + children, + ...props +}: React.ComponentProps & { + inset?: boolean +}) { + return ( + + {children} + + + ) +} + +function DropdownMenuSubContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + DropdownMenu, + DropdownMenuPortal, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuLabel, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuSub, + DropdownMenuSubTrigger, + DropdownMenuSubContent, +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} From 1552456e4b532a311370eba7a52ff3c6029a7929 Mon Sep 17 00:00:00 2001 From: James Nguyen Date: Mon, 3 Nov 2025 00:49:21 -0600 Subject: [PATCH 7/9] walked back the theme, eliminate excessive color and restyle --- src/components/navbar.tsx | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx index 63c08dc..11d3f20 100644 --- a/src/components/navbar.tsx +++ b/src/components/navbar.tsx @@ -1,7 +1,6 @@ "use client"; import { useEffect, useRef, useState } from "react"; import Link from "next/link"; -import Image from "next/image"; // Optional: if using Next.js Image optimization import { DropdownMenu, DropdownMenuTrigger, @@ -10,6 +9,7 @@ import { DropdownMenuSeparator, DropdownMenuItem, } from "@/components/ui/dropdown-menu"; +import { Button } from "@/components/ui/button"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; type NavigationProps = { isSignedIn: boolean; @@ -28,45 +28,45 @@ export default function Navigation({ isSignedIn, User }: NavigationProps) { return (
    -