Commit a8fa6aeb authored by ThinhNC's avatar ThinhNC

Merge branch 'feat/app-logo-branding-and-layout-fixes' into 'develop'

feat(branding): integrate official logo and resolve auth/home layout scrolling issues

See merge request !35
parents 4f565cd8 d0d6f326
# FinWise Frontend - Zalo Mini App Client # FinWise Frontend - Zalo Mini App Client
<p align="center"> <p align="center">
<img src="./src/static/icons/app-icon.png" alt="FinWise Logo" width="96" height="96" onerror="this.style.display='none'"/> <img src="./src/static/logo.png" alt="FinWise Logo" width="96" height="96" />
</p> </p>
<p align="center"> <p align="center">
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
<meta name="format-detection" content="telephone=no" /> <meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" /> <meta name="msapplication-tap-highlight" content="no" />
<title>Sổ tay Chi tiêu & Báo cáo Tài chính</title> <title>Sổ tay Chi tiêu & Báo cáo Tài chính</title>
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/logo.png" />
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@600;700;800&family=Nunito:wght@400;500;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Baloo+2:wght@600;700;800&family=Nunito:wght@400;500;600;700&display=swap" rel="stylesheet">
......
import { SVGProps } from "react"; import React, { ImgHTMLAttributes } from "react";
import finwiseLogo from "@/static/logo.png";
export interface LogoProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src"> {
size?: number | string;
className?: string;
alt?: string;
}
export const Logo: React.FC<LogoProps> = ({
size = 40,
className = "",
alt = "FinWise Logo",
style,
...props
}) => {
const dimensionStyle =
typeof size === "number"
? { width: `${size}px`, height: `${size}px` }
: { width: size, height: size };
function Logo(props: SVGProps<SVGSVGElement>) {
return ( return (
<svg <img
width="88" src={finwiseLogo}
height="40" alt={alt}
viewBox="0 0 88 40" className={`object-contain select-none shrink-0 ${className}`}
fill="none" style={{ ...dimensionStyle, ...style }}
xmlns="http://www.w3.org/2000/svg" draggable={false}
{...props} {...props}
>
<g opacity="0.2">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10.3332 24.25C11.1156 24.25 11.7498 24.8842 11.7498 25.6666C11.7498 26.4491 11.1156 27.0833 10.3332 27.0833C9.55077 27.0833 8.9165 26.4491 8.9165 25.6666C8.9165 24.8842 9.55077 24.25 10.3332 24.25ZM15.9998 24.25C16.7823 24.25 17.4165 24.8842 17.4165 25.6666C17.4165 26.4491 16.7823 27.0833 15.9998 27.0833C15.2174 27.0833 14.5832 26.4491 14.5832 25.6666C14.5832 24.8842 15.2174 24.25 15.9998 24.25ZM21.6665 24.25C22.4489 24.25 23.0832 24.8842 23.0832 25.6666C23.0832 26.4491 22.4489 27.0833 21.6665 27.0833C20.8841 27.0833 20.2498 26.4491 20.2498 25.6666C20.2498 24.8842 20.8841 24.25 21.6665 24.25ZM10.3332 18.5833C11.1156 18.5833 11.7498 19.2175 11.7498 20C11.7498 20.7824 11.1156 21.4166 10.3332 21.4166C9.55077 21.4166 8.9165 20.7824 8.9165 20C8.9165 19.2175 9.55077 18.5833 10.3332 18.5833ZM15.9998 18.5833C16.7823 18.5833 17.4165 19.2175 17.4165 20C17.4165 20.7824 16.7823 21.4166 15.9998 21.4166C15.2174 21.4166 14.5832 20.7824 14.5832 20C14.5832 19.2175 15.2174 18.5833 15.9998 18.5833ZM21.6665 18.5833C22.4489 18.5833 23.0832 19.2175 23.0832 20C23.0832 20.7824 22.4489 21.4166 21.6665 21.4166C20.8841 21.4166 20.2498 20.7824 20.2498 20C20.2498 19.2175 20.8841 18.5833 21.6665 18.5833ZM10.3332 12.9166C11.1156 12.9166 11.7498 13.5509 11.7498 14.3333C11.7498 15.1157 11.1156 15.75 10.3332 15.75C9.55077 15.75 8.9165 15.1157 8.9165 14.3333C8.9165 13.5509 9.55077 12.9166 10.3332 12.9166ZM15.9998 12.9166C16.7823 12.9166 17.4165 13.5509 17.4165 14.3333C17.4165 15.1157 16.7823 15.75 15.9998 15.75C15.2174 15.75 14.5832 15.1157 14.5832 14.3333C14.5832 13.5509 15.2174 12.9166 15.9998 12.9166ZM21.6665 12.9166C22.4489 12.9166 23.0832 13.5509 23.0832 14.3333C23.0832 15.1157 22.4489 15.75 21.6665 15.75C20.8841 15.75 20.2498 15.1157 20.2498 14.3333C20.2498 13.5509 20.8841 12.9166 21.6665 12.9166Z"
fill="currentcolor"
/>
</g>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10.286 24.2856C11.075 24.2856 11.7146 24.9252 11.7146 25.7142C11.7146 26.5032 11.075 27.1428 10.286 27.1428C9.49701 27.1428 8.85742 26.5032 8.85742 25.7142C8.85742 24.9252 9.49701 24.2856 10.286 24.2856ZM21.7146 24.2856C22.5036 24.2856 23.1431 24.9252 23.1431 25.7142C23.1431 26.5032 22.5036 27.1428 21.7146 27.1428C20.9256 27.1428 20.286 26.5032 20.286 25.7142C20.286 24.9252 20.9256 24.2856 21.7146 24.2856ZM10.286 18.5713C11.075 18.5713 11.7146 19.2109 11.7146 19.9999C11.7146 20.7889 11.075 21.4285 10.286 21.4285C9.49701 21.4285 8.85742 20.7889 8.85742 19.9999C8.85742 19.2109 9.49701 18.5713 10.286 18.5713ZM16.0003 18.5713C16.7893 18.5713 17.4289 19.2109 17.4289 19.9999C17.4289 20.7889 16.7893 21.4285 16.0003 21.4285C15.2113 21.4285 14.5717 20.7889 14.5717 19.9999C14.5717 19.2109 15.2113 18.5713 16.0003 18.5713ZM21.7146 18.5713C22.5036 18.5713 23.1431 19.2109 23.1431 19.9999C23.1431 20.7889 22.5036 21.4285 21.7146 21.4285C20.9256 21.4285 20.286 20.7889 20.286 19.9999C20.286 19.2109 20.9256 18.5713 21.7146 18.5713ZM10.286 12.8571C11.075 12.8571 11.7146 13.4966 11.7146 14.2856C11.7146 15.0746 11.075 15.7142 10.286 15.7142C9.49701 15.7142 8.85742 15.0746 8.85742 14.2856C8.85742 13.4966 9.49701 12.8571 10.286 12.8571ZM16.0003 12.8571C16.7893 12.8571 17.4289 13.4966 17.4289 14.2856C17.4289 15.0746 16.7893 15.7142 16.0003 15.7142C15.2113 15.7142 14.5717 15.0746 14.5717 14.2856C14.5717 13.4966 15.2113 12.8571 16.0003 12.8571Z"
fill="currentcolor"
/>
<path
d="M18 19.9999C18 18.8953 17.1046 17.9999 16 17.9999C14.8954 17.9999 14 18.8953 14 19.9999C14 21.1045 14.8954 21.9999 16 21.9999C17.1046 21.9999 18 21.1045 18 19.9999Z"
fill="currentcolor"
/> />
<path
d="M14 18.9999C14 18.4476 14.4477 17.9999 15 17.9999H17C17.5523 17.9999 18 18.4476 18 18.9999V20.9999C18 21.5522 17.5523 21.9999 17 21.9999H15C14.4477 21.9999 14 21.5522 14 20.9999V18.9999Z"
fill="currentcolor"
/>
<path
d="M8.75 13.7499C8.75 13.1976 9.19772 12.7499 9.75 12.7499H10.75C11.3023 12.7499 11.75 13.1976 11.75 13.7499V14.7499C11.75 15.3022 11.3023 15.7499 10.75 15.7499H9.75C9.19772 15.7499 8.75 15.3022 8.75 14.7499V13.7499Z"
fill="currentcolor"
/>
<path
d="M33.8789 14.7578H35.0659L38.0938 22.2925L41.1152 14.7578H42.3086L38.5508 24H37.624L33.8789 14.7578ZM33.4917 14.7578H34.5391L34.7104 20.3945V24H33.4917V14.7578ZM41.6421 14.7578H42.6895V24H41.4707V20.3945L41.6421 14.7578ZM45.9395 17.1318V24H44.7588V17.1318H45.9395ZM44.6699 15.3101C44.6699 15.1196 44.7271 14.9588 44.8413 14.8276C44.9598 14.6965 45.1333 14.6309 45.3618 14.6309C45.5861 14.6309 45.7575 14.6965 45.876 14.8276C45.9987 14.9588 46.0601 15.1196 46.0601 15.3101C46.0601 15.492 45.9987 15.6486 45.876 15.7798C45.7575 15.9067 45.5861 15.9702 45.3618 15.9702C45.1333 15.9702 44.9598 15.9067 44.8413 15.7798C44.7271 15.6486 44.6699 15.492 44.6699 15.3101ZM48.999 18.5981V24H47.8247V17.1318H48.9355L48.999 18.5981ZM48.7197 20.3057L48.231 20.2866C48.2352 19.8169 48.305 19.3831 48.4404 18.9854C48.5758 18.5833 48.7663 18.2342 49.0117 17.938C49.2572 17.6418 49.5492 17.4132 49.8877 17.2524C50.2305 17.0874 50.6092 17.0049 51.0239 17.0049C51.3625 17.0049 51.6672 17.0514 51.938 17.1445C52.2088 17.2334 52.4395 17.3773 52.6299 17.5762C52.8245 17.7751 52.9727 18.0332 53.0742 18.3506C53.1758 18.6637 53.2266 19.0467 53.2266 19.4995V24H52.0459V19.4868C52.0459 19.1271 51.993 18.8394 51.8872 18.6235C51.7814 18.4035 51.627 18.2448 51.4238 18.1475C51.2207 18.0459 50.971 17.9951 50.6748 17.9951C50.3828 17.9951 50.1162 18.0565 49.875 18.1792C49.638 18.3019 49.4328 18.4712 49.2593 18.687C49.09 18.9028 48.9567 19.1504 48.8594 19.4297C48.7663 19.7048 48.7197 19.9967 48.7197 20.3057ZM56.2861 17.1318V24H55.1055V17.1318H56.2861ZM55.0166 15.3101C55.0166 15.1196 55.0737 14.9588 55.188 14.8276C55.3065 14.6965 55.48 14.6309 55.7085 14.6309C55.9328 14.6309 56.1042 14.6965 56.2227 14.8276C56.3454 14.9588 56.4067 15.1196 56.4067 15.3101C56.4067 15.492 56.3454 15.6486 56.2227 15.7798C56.1042 15.9067 55.9328 15.9702 55.7085 15.9702C55.48 15.9702 55.3065 15.9067 55.188 15.7798C55.0737 15.6486 55.0166 15.492 55.0166 15.3101ZM64.9951 15.5767L61.9355 24H60.6851L64.208 14.7578H65.0142L64.9951 15.5767ZM67.5596 24L64.4937 15.5767L64.4746 14.7578H65.2808L68.8164 24H67.5596ZM67.4009 20.5786V21.5815H62.2085V20.5786H67.4009ZM71.0508 18.4521V26.6406H69.8701V17.1318H70.9492L71.0508 18.4521ZM75.6782 20.5088V20.6421C75.6782 21.1414 75.619 21.6048 75.5005 22.0322C75.382 22.4554 75.2085 22.8236 74.98 23.1367C74.7557 23.4499 74.4785 23.6932 74.1484 23.8667C73.8184 24.0402 73.4396 24.127 73.0122 24.127C72.5763 24.127 72.1912 24.055 71.8569 23.9111C71.5226 23.7673 71.2391 23.5578 71.0063 23.2827C70.7736 23.0076 70.5874 22.6776 70.4478 22.2925C70.3123 21.9074 70.2192 21.4736 70.1685 20.9912V20.2803C70.2192 19.7725 70.3145 19.3175 70.4541 18.9155C70.5938 18.5135 70.7778 18.1707 71.0063 17.8872C71.2391 17.5994 71.5205 17.3815 71.8506 17.2334C72.1807 17.0811 72.5615 17.0049 72.9932 17.0049C73.4248 17.0049 73.8078 17.0895 74.1421 17.2588C74.4764 17.4238 74.7578 17.6608 74.9863 17.9697C75.2148 18.2786 75.3862 18.6489 75.5005 19.0806C75.619 19.508 75.6782 19.984 75.6782 20.5088ZM74.4976 20.6421V20.5088C74.4976 20.166 74.4616 19.8444 74.3896 19.5439C74.3177 19.2393 74.2056 18.9727 74.0532 18.7441C73.9051 18.5114 73.7147 18.3294 73.4819 18.1982C73.2492 18.0628 72.972 17.9951 72.6504 17.9951C72.3542 17.9951 72.096 18.0459 71.876 18.1475C71.6602 18.249 71.4761 18.3866 71.3237 18.5601C71.1714 18.7293 71.0465 18.924 70.9492 19.144C70.8561 19.3599 70.7863 19.5841 70.7397 19.8169V21.4609C70.8244 21.7572 70.9429 22.0365 71.0952 22.2988C71.2476 22.557 71.4507 22.7664 71.7046 22.9272C71.9585 23.0838 72.278 23.1621 72.6631 23.1621C72.9805 23.1621 73.2534 23.0965 73.4819 22.9653C73.7147 22.8299 73.9051 22.6458 74.0532 22.4131C74.2056 22.1803 74.3177 21.9137 74.3896 21.6133C74.4616 21.3086 74.4976 20.9849 74.4976 20.6421ZM78.3506 18.4521V26.6406H77.1699V17.1318H78.249L78.3506 18.4521ZM82.978 20.5088V20.6421C82.978 21.1414 82.9188 21.6048 82.8003 22.0322C82.6818 22.4554 82.5083 22.8236 82.2798 23.1367C82.0555 23.4499 81.7783 23.6932 81.4482 23.8667C81.1182 24.0402 80.7394 24.127 80.312 24.127C79.8761 24.127 79.491 24.055 79.1567 23.9111C78.8224 23.7673 78.5389 23.5578 78.3062 23.2827C78.0734 23.0076 77.8872 22.6776 77.7476 22.2925C77.6121 21.9074 77.519 21.4736 77.4683 20.9912V20.2803C77.519 19.7725 77.6143 19.3175 77.7539 18.9155C77.8936 18.5135 78.0776 18.1707 78.3062 17.8872C78.5389 17.5994 78.8203 17.3815 79.1504 17.2334C79.4805 17.0811 79.8613 17.0049 80.293 17.0049C80.7246 17.0049 81.1076 17.0895 81.4419 17.2588C81.7762 17.4238 82.0576 17.6608 82.2861 17.9697C82.5146 18.2786 82.686 18.6489 82.8003 19.0806C82.9188 19.508 82.978 19.984 82.978 20.5088ZM81.7974 20.6421V20.5088C81.7974 20.166 81.7614 19.8444 81.6895 19.5439C81.6175 19.2393 81.5054 18.9727 81.353 18.7441C81.2049 18.5114 81.0145 18.3294 80.7817 18.1982C80.549 18.0628 80.2718 17.9951 79.9502 17.9951C79.654 17.9951 79.3958 18.0459 79.1758 18.1475C78.96 18.249 78.7759 18.3866 78.6235 18.5601C78.4712 18.7293 78.3464 18.924 78.249 19.144C78.1559 19.3599 78.0861 19.5841 78.0396 19.8169V21.4609C78.1242 21.7572 78.2427 22.0365 78.395 22.2988C78.5474 22.557 78.7505 22.7664 79.0044 22.9272C79.2583 23.0838 79.5778 23.1621 79.9629 23.1621C80.2803 23.1621 80.5532 23.0965 80.7817 22.9653C81.0145 22.8299 81.2049 22.6458 81.353 22.4131C81.5054 22.1803 81.6175 21.9137 81.6895 21.6133C81.7614 21.3086 81.7974 20.9849 81.7974 20.6421Z"
fill="currentcolor"
/>
</svg>
); );
} };
export default Logo; export default Logo;
...@@ -2,6 +2,7 @@ import React, { useEffect } from "react"; ...@@ -2,6 +2,7 @@ import React, { useEffect } from "react";
import { useNavigate } from "zmp-ui"; import { useNavigate } from "zmp-ui";
import { useAuthStore } from "@/stores/auth-store"; import { useAuthStore } from "@/stores/auth-store";
import { useI18n } from "@/i18n"; import { useI18n } from "@/i18n";
import { Logo } from "@/components/logo";
export const AuthGuard: React.FC<{ children: React.ReactNode }> = ({ children }) => { export const AuthGuard: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { isAuthenticated, isInitialized } = useAuthStore(); const { isAuthenticated, isInitialized } = useAuthStore();
...@@ -16,9 +17,9 @@ export const AuthGuard: React.FC<{ children: React.ReactNode }> = ({ children }) ...@@ -16,9 +17,9 @@ export const AuthGuard: React.FC<{ children: React.ReactNode }> = ({ children })
if (!isInitialized) { if (!isInitialized) {
return ( return (
<div className="page flex flex-col items-center justify-center min-h-screen"> <div className="page flex flex-col items-center justify-center min-h-screen gap-4">
<div className="w-16 h-16 border-4 border-clay-primary border-t-transparent rounded-full animate-spin shadow-clay-raised"></div> <Logo size={72} className="animate-pulse" alt="FinWise" />
<p className="clay-caption mt-4 animate-pulse text-clay-primary">{t("common.loading")}</p> <p className="clay-caption animate-pulse text-clay-primary font-medium">{t("common.loading")}</p>
</div> </div>
); );
} }
......
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useLocation } from "zmp-ui"; import { useLocation } from "zmp-ui";
import { useI18n } from "@/i18n"; import { useI18n } from "@/i18n";
import finwiseLogo from "@/static/logo.png";
const APP_NAME = "FinWise"; const APP_NAME = "FinWise";
...@@ -49,6 +50,23 @@ export const DocumentTitle: React.FC = () => { ...@@ -49,6 +50,23 @@ export const DocumentTitle: React.FC = () => {
const { pathname } = useLocation(); const { pathname } = useLocation();
const { t } = useI18n(); const { t } = useI18n();
useEffect(() => {
// Dynamically set / update favicon to guarantee browser tab displays FinWise logo
const iconRels = ["icon", "shortcut icon", "apple-touch-icon"];
iconRels.forEach((rel) => {
let link: HTMLLinkElement | null = document.querySelector(`link[rel='${rel}']`);
if (!link) {
link = document.createElement("link");
link.rel = rel;
document.head.appendChild(link);
}
if (rel !== "apple-touch-icon") {
link.type = "image/png";
}
link.href = finwiseLogo;
});
}, []);
useEffect(() => { useEffect(() => {
const key = PAGE_TITLES.find((page) => page.matches(pathname))?.key; const key = PAGE_TITLES.find((page) => page.matches(pathname))?.key;
document.title = `${key ? t(key) : t("document.default")} | ${APP_NAME}`; document.title = `${key ? t(key) : t("document.default")} | ${APP_NAME}`;
......
...@@ -8,6 +8,7 @@ import { Card } from "@/components/ui/Card"; ...@@ -8,6 +8,7 @@ import { Card } from "@/components/ui/Card";
import { Input } from "@/components/ui/Input"; import { Input } from "@/components/ui/Input";
import { authService } from "@/services/auth.service"; import { authService } from "@/services/auth.service";
import { IconGradients } from "@/components/ui/icons"; import { IconGradients } from "@/components/ui/icons";
import { Logo } from "@/components/logo";
import { TranslationFunction, useI18n } from "@/i18n"; import { TranslationFunction, useI18n } from "@/i18n";
import { getErrorMessage } from "@/lib/error-message"; import { getErrorMessage } from "@/lib/error-message";
...@@ -60,15 +61,18 @@ const ForgotPasswordPage: React.FC = () => { ...@@ -60,15 +61,18 @@ const ForgotPasswordPage: React.FC = () => {
}; };
return ( return (
<Page className="page flex flex-col justify-center py-12"> <Page className="page flex flex-col justify-start overflow-y-auto">
<Header title={t("auth.forgot.header")} showBackIcon={true} onBackClick={() => navigate("/login")} /> <Header title={t("auth.forgot.header")} showBackIcon={true} onBackClick={() => navigate("/login")} />
<IconGradients /> <IconGradients />
<div className="w-full max-w-sm mx-auto flex flex-col gap-6 px-2"> <div className="w-full max-w-sm mx-auto flex flex-col gap-6 px-2 pt-2">
<div className="text-center space-y-2"> <div className="flex flex-col items-center gap-2.5 text-center">
<Logo size={64} alt="FinWise" />
<div className="space-y-1">
<h1 className="clay-title-h1 text-clay-primary">{t("auth.forgot.title")}</h1> <h1 className="clay-title-h1 text-clay-primary">{t("auth.forgot.title")}</h1>
<p className="clay-caption">{t("auth.forgot.subtitle")}</p> <p className="clay-caption">{t("auth.forgot.subtitle")}</p>
</div> </div>
</div>
{isSent ? ( {isSent ? (
<Card className="text-center space-y-4"> <Card className="text-center space-y-4">
......
...@@ -8,10 +8,10 @@ import { Card } from "@/components/ui/Card"; ...@@ -8,10 +8,10 @@ import { Card } from "@/components/ui/Card";
import { Input } from "@/components/ui/Input"; import { Input } from "@/components/ui/Input";
import { import {
IconGradients, IconGradients,
WalletIcon,
EyeIcon, EyeIcon,
EyeOffIcon, EyeOffIcon,
} from "@/components/ui/icons"; } from "@/components/ui/icons";
import { Logo } from "@/components/logo";
import { useZaloLogin } from "@/hooks/use-zalo-login"; import { useZaloLogin } from "@/hooks/use-zalo-login";
import { useAuthStore } from "@/stores/auth-store"; import { useAuthStore } from "@/stores/auth-store";
import { authService } from "@/services/auth.service"; import { authService } from "@/services/auth.service";
...@@ -113,16 +113,14 @@ const LoginPage: React.FC = () => { ...@@ -113,16 +113,14 @@ const LoginPage: React.FC = () => {
const isBusy = isSubmitting || isZaloLoading; const isBusy = isSubmitting || isZaloLoading;
return ( return (
<Page className="page flex flex-col justify-start py-6 px-4"> <Page className="page flex flex-col justify-start overflow-y-auto">
<Header title={t("auth.login.header")} showBackIcon={false} /> <Header title={t("auth.login.header")} showBackIcon={false} />
<IconGradients /> <IconGradients />
<div className="w-full max-w-sm mx-auto flex flex-col gap-5 pt-1"> <div className="w-full max-w-sm mx-auto flex flex-col gap-5 pt-2">
{/* Top: Branding */} {/* Top: Branding */}
<div className="flex flex-col items-center gap-2.5 text-center"> <div className="flex flex-col items-center gap-2.5 text-center">
<div className="flex h-16 w-16 items-center justify-center rounded-clay-lg bg-clay-primary text-clay-on-primary shadow-clay-hover border border-clay-highlight/30"> <Logo size={72} alt="FinWise" />
<WalletIcon size={34} />
</div>
<div className="space-y-1"> <div className="space-y-1">
<h1 className="clay-title-h1 text-clay-primary">FinWise</h1> <h1 className="clay-title-h1 text-clay-primary">FinWise</h1>
<p className="clay-caption">{t("auth.login.subtitle")}</p> <p className="clay-caption">{t("auth.login.subtitle")}</p>
......
...@@ -8,6 +8,7 @@ import { Card } from "@/components/ui/Card"; ...@@ -8,6 +8,7 @@ import { Card } from "@/components/ui/Card";
import { Input } from "@/components/ui/Input"; import { Input } from "@/components/ui/Input";
import { authService } from "@/services/auth.service"; import { authService } from "@/services/auth.service";
import { IconGradients } from "@/components/ui/icons"; import { IconGradients } from "@/components/ui/icons";
import { Logo } from "@/components/logo";
import { TranslationFunction, useI18n } from "@/i18n"; import { TranslationFunction, useI18n } from "@/i18n";
import { getErrorMessage } from "@/lib/error-message"; import { getErrorMessage } from "@/lib/error-message";
...@@ -85,15 +86,18 @@ const RegisterPage: React.FC = () => { ...@@ -85,15 +86,18 @@ const RegisterPage: React.FC = () => {
}; };
return ( return (
<Page className="page flex flex-col justify-center py-12"> <Page className="page flex flex-col justify-start overflow-y-auto">
<Header title={t("auth.register.header")} showBackIcon={true} onBackClick={() => navigate("/login")} /> <Header title={t("auth.register.header")} showBackIcon={true} onBackClick={() => navigate("/login")} />
<IconGradients /> <IconGradients />
<div className="w-full max-w-sm mx-auto flex flex-col gap-6 px-2"> <div className="w-full max-w-sm mx-auto flex flex-col gap-6 px-2 pt-2">
<div className="text-center space-y-2"> <div className="flex flex-col items-center gap-2.5 text-center">
<Logo size={64} alt="FinWise" />
<div className="space-y-1">
<h1 className="clay-title-h1 text-clay-primary">{t("auth.register.title")}</h1> <h1 className="clay-title-h1 text-clay-primary">{t("auth.register.title")}</h1>
<p className="clay-caption">{t("auth.register.subtitle")}</p> <p className="clay-caption">{t("auth.register.subtitle")}</p>
</div> </div>
</div>
{isRegistered ? ( {isRegistered ? (
<Card className="text-center space-y-4"> <Card className="text-center space-y-4">
......
...@@ -8,6 +8,7 @@ import { Card } from "@/components/ui/Card"; ...@@ -8,6 +8,7 @@ import { Card } from "@/components/ui/Card";
import { Input } from "@/components/ui/Input"; import { Input } from "@/components/ui/Input";
import { authService } from "@/services/auth.service"; import { authService } from "@/services/auth.service";
import { IconGradients } from "@/components/ui/icons"; import { IconGradients } from "@/components/ui/icons";
import { Logo } from "@/components/logo";
import { TranslationFunction, useI18n } from "@/i18n"; import { TranslationFunction, useI18n } from "@/i18n";
import { getErrorMessage } from "@/lib/error-message"; import { getErrorMessage } from "@/lib/error-message";
...@@ -76,15 +77,18 @@ const ResetPasswordPage: React.FC = () => { ...@@ -76,15 +77,18 @@ const ResetPasswordPage: React.FC = () => {
}; };
return ( return (
<Page className="page flex flex-col justify-center py-12"> <Page className="page flex flex-col justify-start overflow-y-auto">
<Header title={t("auth.reset.header")} showBackIcon={true} onBackClick={() => navigate("/login")} /> <Header title={t("auth.reset.header")} showBackIcon={true} onBackClick={() => navigate("/login")} />
<IconGradients /> <IconGradients />
<div className="w-full max-w-sm mx-auto flex flex-col gap-6 px-2"> <div className="w-full max-w-sm mx-auto flex flex-col gap-6 px-2 pt-2">
<div className="text-center space-y-2"> <div className="flex flex-col items-center gap-2.5 text-center">
<Logo size={64} alt="FinWise" />
<div className="space-y-1">
<h1 className="clay-title-h1 text-clay-primary">{t("auth.reset.title")}</h1> <h1 className="clay-title-h1 text-clay-primary">{t("auth.reset.title")}</h1>
<p className="clay-caption">{t("auth.reset.subtitle")}</p> <p className="clay-caption">{t("auth.reset.subtitle")}</p>
</div> </div>
</div>
<Card> <Card>
<form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-4"> <form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-4">
......
import React from "react"; import React from "react";
import { Page, Header, useNavigate } from "zmp-ui"; import { Page, Header, useNavigate } from "zmp-ui";
import { Button } from "@/components/ui/Button"; import { Button } from "@/components/ui/Button";
import { Card } from "@/components/ui/Card";
import { Avatar } from "@/components/ui/Avatar"; import { Avatar } from "@/components/ui/Avatar";
import { useAuthStore } from "@/stores/auth-store"; import { useAuthStore } from "@/stores/auth-store";
import { import {
...@@ -26,11 +25,11 @@ function HomePage() { ...@@ -26,11 +25,11 @@ function HomePage() {
const showStyleGuide = user?.role.name !== SYSTEM_ROLES.USER; const showStyleGuide = user?.role.name !== SYSTEM_ROLES.USER;
return ( return (
<Page className="page flex flex-col justify-between py-8"> <Page className="page flex flex-col justify-start overflow-y-auto">
<Header title={t("home.header")} showBackIcon={false} /> <Header title={t("home.header")} showBackIcon={false} />
<IconGradients /> <IconGradients />
<div className="flex-1 flex flex-col items-center justify-center gap-6 px-4"> <div className="flex flex-col items-center justify-start gap-5 px-4 pt-2 pb-6">
{/* Logo/Avatar Area */} {/* Logo/Avatar Area */}
<div className="relative"> <div className="relative">
<Avatar <Avatar
...@@ -53,18 +52,10 @@ function HomePage() { ...@@ -53,18 +52,10 @@ function HomePage() {
{t("home.account")} <span className="font-semibold text-clay-primary">{user?.email}</span> {t("home.account")} <span className="font-semibold text-clay-primary">{user?.email}</span>
</p> </p>
</div> </div>
{/* Info Card */}
<Card className="w-full max-w-sm">
<h3 className="font-baloo font-bold text-clay-text text-base mb-1">{t("home.authTitle")}</h3>
<p className="text-xs text-clay-text-muted">
{t("home.authDescription")}
</p>
</Card>
</div> </div>
{/* Navigation CTA */} {/* Navigation CTA */}
<div className="px-4 w-full max-w-sm mx-auto flex flex-col gap-3"> <div className="px-4 w-full max-w-sm mx-auto flex flex-col gap-3 pb-12">
<PermissionGate permission={PERMISSIONS.USER_READ}> <PermissionGate permission={PERMISSIONS.USER_READ}>
<button <button
type="button" type="button"
......
...@@ -706,7 +706,7 @@ const ProfilePage: React.FC = () => { ...@@ -706,7 +706,7 @@ const ProfilePage: React.FC = () => {
)} )}
{/* Global Logout Button */} {/* Global Logout Button */}
<div className="px-4"> <div className="px-4 pb-6">
<Button variant="secondary" onClick={handleLogout} fullWidth className="text-clay-expense"> <Button variant="secondary" onClick={handleLogout} fullWidth className="text-clay-expense">
{t("profile.logout")} {t("profile.logout")}
</Button> </Button>
......
...@@ -26,6 +26,7 @@ import { ...@@ -26,6 +26,7 @@ import {
PlusIcon, PlusIcon,
FoodIcon, FoodIcon,
} from "@/components/ui/icons"; } from "@/components/ui/icons";
import { Logo } from "@/components/logo";
import { useI18n } from "@/i18n"; import { useI18n } from "@/i18n";
function getNumberSeparators(locale: string): { group: string; decimal: string } { function getNumberSeparators(locale: string): { group: string; decimal: string } {
...@@ -420,6 +421,25 @@ const StyleGuidePage: React.FC = () => { ...@@ -420,6 +421,25 @@ const StyleGuidePage: React.FC = () => {
</Modal> </Modal>
</Card> </Card>
{/* Section: App Logo & Brand Identity */}
<Card>
<h2 className="clay-title-h2 mb-4 border-b pb-2 text-clay-primary-dark">FinWise Brand Logo</h2>
<div className="flex items-center justify-around gap-4 p-4 bg-clay-bg rounded-clay-md border border-clay-text/5">
<div className="flex flex-col items-center gap-2">
<Logo size={40} alt="FinWise Logo Small" />
<span className="text-xs text-clay-text-muted font-semibold">Small (40px)</span>
</div>
<div className="flex flex-col items-center gap-2">
<Logo size={56} alt="FinWise Logo Medium" />
<span className="text-xs text-clay-text-muted font-semibold">Medium (56px)</span>
</div>
<div className="flex flex-col items-center gap-2">
<Logo size={72} alt="FinWise Logo Large" />
<span className="text-xs text-clay-text-muted font-semibold">Large (72px)</span>
</div>
</div>
</Card>
{/* Section: 3D Icons List */} {/* Section: 3D Icons List */}
<Card> <Card>
<h2 className="clay-title-h2 mb-4 border-b pb-2 text-clay-primary-dark">{t("styleGuide.icons")}</h2> <h2 className="clay-title-h2 mb-4 border-b pb-2 text-clay-primary-dark">{t("styleGuide.icons")}</h2>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment