From 5dbf7736ed657a45859cb16c130dede0216ad8cc Mon Sep 17 00:00:00 2001 From: joshydavid Date: Fri, 1 Aug 2025 09:49:06 +0800 Subject: [PATCH 1/3] chore: spin down aws resources Signed-off-by: joshydavid --- .../workflows/{merged_backend.yml => merged_backend.yml.disabled} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{merged_backend.yml => merged_backend.yml.disabled} (100%) diff --git a/.github/workflows/merged_backend.yml b/.github/workflows/merged_backend.yml.disabled similarity index 100% rename from .github/workflows/merged_backend.yml rename to .github/workflows/merged_backend.yml.disabled From a2444d6330e402f97bd520d0b7fcddb245c8f494 Mon Sep 17 00:00:00 2001 From: joshydavid Date: Fri, 1 Aug 2025 09:52:08 +0800 Subject: [PATCH 2/3] feat: add banner component Signed-off-by: joshydavid --- frontend/app/components/Banner/index.tsx | 14 ++ .../app/components/Header/bannerAlert.tsx | 0 frontend/app/components/Header/index.tsx | 22 ++- frontend/app/components/ui/banner.tsx | 139 ++++++++++++++++++ frontend/app/components/ui/button.tsx | 1 + frontend/bun.lockb | Bin 257394 -> 257426 bytes frontend/package.json | 5 +- 7 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 frontend/app/components/Banner/index.tsx create mode 100644 frontend/app/components/Header/bannerAlert.tsx create mode 100644 frontend/app/components/ui/banner.tsx diff --git a/frontend/app/components/Banner/index.tsx b/frontend/app/components/Banner/index.tsx new file mode 100644 index 0000000..b62f0dd --- /dev/null +++ b/frontend/app/components/Banner/index.tsx @@ -0,0 +1,14 @@ +import { Banner, BannerClose, BannerTitle } from "@/components/ui/banner"; + +interface BannerComponentInterface { + title: string; +} + +export default function BannerComponent({ title }: BannerComponentInterface) { + return ( + + {title} + + + ); +} diff --git a/frontend/app/components/Header/bannerAlert.tsx b/frontend/app/components/Header/bannerAlert.tsx new file mode 100644 index 0000000..e69de29 diff --git a/frontend/app/components/Header/index.tsx b/frontend/app/components/Header/index.tsx index 4749896..e0a3ac0 100644 --- a/frontend/app/components/Header/index.tsx +++ b/frontend/app/components/Header/index.tsx @@ -3,20 +3,28 @@ import LoginX from "@/components/Authentication/LoginX"; import BackButton from "@/components/BackButton"; import { AppearanceToggle } from "@/components/ui/appearance-toggle"; + import { useAuthStatus } from "@/hooks/use-auth-status"; import { usePathname } from "next/navigation"; +import BannerComponent from "../Banner"; export default function Header() { const pathname = usePathname(); const { authData } = useAuthStatus(); return ( -
-
{pathname !== "/" && }
-
- - -
-
+ <> + +
+
{pathname !== "/" && }
+
+ + +
+
+ ); } diff --git a/frontend/app/components/ui/banner.tsx b/frontend/app/components/ui/banner.tsx new file mode 100644 index 0000000..61b3d68 --- /dev/null +++ b/frontend/app/components/ui/banner.tsx @@ -0,0 +1,139 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { cn } from "@/lib/constants/utils"; +import { useControllableState } from "@radix-ui/react-use-controllable-state"; +import { type LucideIcon, XIcon } from "lucide-react"; +import { + type ComponentProps, + createContext, + type HTMLAttributes, + type MouseEventHandler, + useContext, +} from "react"; + +type BannerContextProps = { + show: boolean; + setShow: (show: boolean) => void; +}; + +export const BannerContext = createContext({ + show: true, + setShow: () => {}, +}); + +export type BannerProps = HTMLAttributes & { + visible?: boolean; + defaultVisible?: boolean; + onClose?: () => void; + inset?: boolean; +}; + +export const Banner = ({ + children, + visible, + defaultVisible = true, + onClose, + className, + inset = false, + ...props +}: BannerProps) => { + const [show, setShow] = useControllableState({ + defaultProp: defaultVisible, + prop: visible, + onChange: onClose, + }); + + if (!show) { + return null; + } + + return ( + +
+ {children} +
+
+ ); +}; + +export type BannerIconProps = HTMLAttributes & { + icon: LucideIcon; +}; + +export const BannerIcon = ({ + icon: Icon, + className, + ...props +}: BannerIconProps) => ( +
+ +
+); + +export type BannerTitleProps = HTMLAttributes; + +export const BannerTitle = ({ className, ...props }: BannerTitleProps) => ( +

+); + +export type BannerActionProps = ComponentProps; + +export const BannerAction = ({ + variant = "ghost", + size = "sm", + className, + ...props +}: BannerActionProps) => ( + + ); +}; diff --git a/frontend/app/components/ui/button.tsx b/frontend/app/components/ui/button.tsx index 04e6e88..fa3dedc 100644 --- a/frontend/app/components/ui/button.tsx +++ b/frontend/app/components/ui/button.tsx @@ -19,6 +19,7 @@ const buttonVariants = cva( ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", link: "text-primary underline-offset-4 hover:underline", + transparent: "bg-transparent hover:bg-transparent hover:text-inherit", }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", diff --git a/frontend/bun.lockb b/frontend/bun.lockb index 0f1202f6fb91256022fdd84e0e573a397afa89d9..76f83d50ebeb3fa90260cdd838ddcd9d275abd98 100755 GIT binary patch delta 15949 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 OxEZa2vj)X|KK~!l%IH@B delta 15764 zcmeI3dz_AC{>Sh8o*5AmVhl3P#K>tFLy?4PsTGk;jPo%*&{yfij>_hYFwXc5rGQU6OGVkYeUEk|`-Pe6^ zKi}t1J1QOhq|&VP)GcG1Cp>&jy<=V9{2*t}y@x+}zsa++-tVyM!;7A{Keu+<8`^$; zaCWzDp~mr^m*#od=O=hx3i>taOVIMD(j&`wUMhM6D*Ki=&#R3-izcB{e9yZGZ9%#! z`ie|flEnPfjV+@Q<~e|C6(nN6*WX7mwFX@+H~r;!$oxM)U2D`PXrPRu)U zUZ_rkQPb~>r^e}UcA7y)Lfi0@Y3=;c;q82`&r7P`xnXe94}UhXVR%+r*}NyZpBxop z9-dH;vMgRxV2!*Ez@hPe18TApDF3&>Vt73)-4j)QFVifPL+lLzl^+ZWQk5GD=fNn? z3wa!CZ#*bt0w_HRR3IBPfN7u*t7ZPYNR@sJl>aBtI)y<&s(v0fb>0xqt4Lz5 z8FEcuL{;%6P>`y@mq86I0Oh|58t7tBC{F$G&gF?At;gG-bz1|fy%rRtYW-a$2(hZ( z-j7(%RMlS((hZ<#Z-xr66J*~7vVX31mf;IfkSe_wD#I~Q!Q&wN52hzj4d6%9pU?}T zk_wq>;8jSges$BDrgc!|r}*Wg4X0x8!iPSrAL69)GD*qM!nCClgyK}&q7C_4zw4}= zRKx3NX{n-}EG^Y~^gvba7PF%vl2L;WUti0JRaNM3_FqyBY$)YabeNToRhfqKq4q{t z{s=$Xf5f1S+sV*Ejj;m7smhHdpX-D--OBxHtxW@5BE6@rp;-098wwMBFTAtxR;{)- zS7pK#wMGJ5c5CG`m#MU6w9RReq1f^mG5Max^dBFY`j ztA(m!9aG)e6r{4(MP*7eyHtJFN7a5~vrDUzZWpj=m2n*g&S&o?RGV=as*C8Is5Z>K zs5-b0Rf8c^^`@a(!ADWuUjB;esOF+N3tvH1f3c;Pp{l05%(o#SC)+UB4tScKiTiRHStE@(Qt07fO9V{)?9_eW5 zU!!WT6ZLr%^ajUyS4KJ*Vht9jn!;`5YctX)B9SM}@RSvZRTX^3>{2!Syrq9h{qV9K$&qs@ z*Gd{Vb^r#TfS7&UTA5l@)ucJs(SgBMxzfTdd^iSPL;LP@?%vEEi=1R zmy~rV|1>eB zk4&^FMqSG;N7c?1DirSbUSdd*tN74S>VT@&b*7zA{=Ck7XnI{tZ!+zUsfW0pRSs&&mx(<-Amo~61K*1)cMNvQg%ZRv{>I8ijLWHVfXDx5owZk%E})QD4T zV5v5+Sk=Jmnq8{$^-$fDGf=HeD^!<`4yejsiz-M}{5Z?SwS$8}@$0@$0Bj>`bkVOC12R)(A2hAL~cK1}r=p~<9my!78Y zmCv?(srJJ(OBbWjbuA_%^04KosNp|}>dekX)zM3)FQW=lb^MB@rRw-~R0AwTHNkZ# zf8Kgaf0)1{ohoj@ApM7O!~HfTMs5rrlak?6K6JG9De)gt4d<}67poff(W3qSy%mU6 z-KKvs`+r(#I`aCXvHj1mB;JKY4%B$<3my3hprtx@??R$Gt>0W5K(1-&yO78UQu;20 z{Xi&v7gG8zr1V`#>AR59cOlUSr_y&JdM+jC9f=-TO5cT)z6&XR7gG8zr1V`#>AMi! z7fRoSXcdZohw}gQUC60Qr}R$9%e(!HMs3= zW9ygqdL_C15s#A+IPFfaLgan-IXvG_cWl?0P{}U8-Yb{n@<-llm*Dbyp%UHw@_;MR z<=6U`*OcKKQV5?%fsp%Q!YiCzhVjrsYz-}VR1@snMLTZ5`?cj{Xv zLRVDxW_=6$rP<`#C7XOJJ~Uf5v*~NNZEm)j$T3q7RA0>Lo5~iT(981Viqi8Nxua`17j4 zcV-)G#pS1Vm)VAxP5zH_+*CC&*uGYjE1PQN%+?6oNLM+FCgeh>!OIg+i{1o^zBig|wsdSa*%6sywx-xVa)W51!5DhfK=pOB zO36n~&QBU>w%M8!pYEQ?3JwJGV_Jf%ZoLn*(=E-ykg{??ibvPKOyV6SUG= z*}FhIi)5X7>x4 zrpPN|5a{fXhnC#HUVsc}4lUeg{er5)t|WRHGywS()`fbI43~gB8!JN5gvkv;ZfJSe~=uKpVzza9_U=$3|nCvY=_Yl9Sh@NJlqKr;4YX1 z_keslG9eA>LnByD-4##(I+0hxD$oYj7x4GMWR8g6O0pb$2~CU_0rfIL_T^I$&6 z=TiQ3@bF8_I|CYG?wS|Yyzd65o=_8`ajB=jOU00-eP?1iu3B>V`cz-OKT#6ejo2l@?A1-J;R zL3OABHK7*NhKu2ncy6ng5~&AiaG6^+IH(npPu@IunRUuT|42U%!b8v*TX(n_7CarVMK*bfKbAbbl)_1s;Jj^qcq5jMdrcm!HQ z8;~PcPv`;qwLo9c4@G=-?2HgQW~wZn5iOKlKiP9M>O%Fgy+pCeY4M=nQ%c z(j!h5aiRNkoNizVAh-P-s0*zbo$l1SGwas+PZ}Rd{1PatEY)L%?xjVx>&d?kbaT|r za5_wY8)NEqq)xKIx_gbHr|&>)mQdRXvsqMzoHrUW{Pz5I4lf)>H~ ze*cX0=IPw5W;+)OGW}flekkZtOLre05VKD$UiIeY{~q>4;P=m@95=IdE;BpGtXcHS zx7FVM9!DR!tq}#9rMGO>D!rM@&JJqw3pw|6c5q|M12lwVTJ}3%mT%cUFZW2`w@S}w zmd@?{gmrOmjW$1w%=z7LTF7Xf-YmVD7w;~f8YI=ya`NPq-Ecv#@%wVWJ|0Bp!`M?? z_o@%dgBSWmIf*Xi{vgRub z5_F3m=VmVsBihlA#5{u2)ehpQarP8+1%i zq{6)5g81lA8n{^tgSvinz1;l^f||uGT9-2yZSzu=F*;j!-&<5EcFEk~SA(w6b;~?^ z-KgDtQE(fBiOkL2H-lE}Xv8jKru*yLY}#nCIab15lozx(YY8XkMOOR276$uN`s;%G<{_J?3K6c$#2AS@vWs#%d3YJ9=M`Zo&ER42NbSN)e!E&$}RqJ$ z3xwC)4M}kw+^nRy_T~1N?UVfNNpWxb`AcfW%?aG>T5)OlH`j^l(Kcw-D*uH(aR+Aq EFV=zi@Bjb+ diff --git a/frontend/package.json b/frontend/package.json index a8d7442..28827c1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,7 +17,8 @@ "@radix-ui/react-label": "^2.1.6", "@radix-ui/react-popover": "^1.1.13", "@radix-ui/react-select": "^2.2.4", - "@radix-ui/react-slot": "^1.2.2", + "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-use-controllable-state": "^1.2.2", "@tanstack/react-query": "^5.75.5", "axios": "^1.9.0", "class-variance-authority": "^0.7.1", @@ -26,7 +27,7 @@ "dompurify": "^3.2.6", "framer-motion": "^12.12.1", "install": "^0.13.0", - "lucide-react": "^0.508.0", + "lucide-react": "^0.535.0", "next": "15.3.2", "next-themes": "^0.4.6", "postcss": "^8.5.3", From 8b85b97b84020be4ddd367b2cc2ec0a407bcca8d Mon Sep 17 00:00:00 2001 From: joshydavid Date: Fri, 1 Aug 2025 09:52:51 +0800 Subject: [PATCH 3/3] fix: use absolute path Signed-off-by: joshydavid --- frontend/app/components/Header/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/app/components/Header/index.tsx b/frontend/app/components/Header/index.tsx index e0a3ac0..23530ea 100644 --- a/frontend/app/components/Header/index.tsx +++ b/frontend/app/components/Header/index.tsx @@ -2,11 +2,10 @@ import LoginX from "@/components/Authentication/LoginX"; import BackButton from "@/components/BackButton"; +import BannerComponent from "@/components/Banner"; import { AppearanceToggle } from "@/components/ui/appearance-toggle"; - import { useAuthStatus } from "@/hooks/use-auth-status"; import { usePathname } from "next/navigation"; -import BannerComponent from "../Banner"; export default function Header() { const pathname = usePathname();