From 759052a71f305b07e1a0050128741b4893f42059 Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Sat, 11 Apr 2026 01:39:59 +0700 Subject: [PATCH] fix(web): update dashboard pages, layouts, and listing forms Update 12 page/layout files across auth, dashboard, listings, and search routes to improve type safety, fix component imports, and align with latest API changes. Co-Authored-By: Paperclip --- apps/web/app/[locale]/(auth)/layout.tsx | 2 +- .../(dashboard)/dashboard/kyc/page.tsx | 4 +- .../[locale]/(dashboard)/dashboard/page.tsx | 3 + .../(dashboard)/dashboard/profile/page.tsx | 4 +- .../dashboard/subscription/page.tsx | 10 +- .../(dashboard)/dashboard/valuation/page.tsx | 2 +- apps/web/app/[locale]/(dashboard)/layout.tsx | 90 ++++++++++++- .../(dashboard)/listings/[id]/edit/page.tsx | 8 +- .../(dashboard)/listings/new/page.tsx | 6 +- .../[locale]/(dashboard)/listings/page.tsx | 5 + .../web/app/[locale]/(public)/search/page.tsx | 119 +++++++++++++++++- apps/web/app/[locale]/layout.tsx | 11 +- 12 files changed, 234 insertions(+), 30 deletions(-) diff --git a/apps/web/app/[locale]/(auth)/layout.tsx b/apps/web/app/[locale]/(auth)/layout.tsx index 9f3af02..4057b3e 100644 --- a/apps/web/app/[locale]/(auth)/layout.tsx +++ b/apps/web/app/[locale]/(auth)/layout.tsx @@ -1,6 +1,6 @@ export default function AuthLayout({ children }: { children: React.ReactNode }) { return ( -
+
{children}
); diff --git a/apps/web/app/[locale]/(dashboard)/dashboard/kyc/page.tsx b/apps/web/app/[locale]/(dashboard)/dashboard/kyc/page.tsx index 364021e..3f5b409 100644 --- a/apps/web/app/[locale]/(dashboard)/dashboard/kyc/page.tsx +++ b/apps/web/app/[locale]/(dashboard)/dashboard/kyc/page.tsx @@ -79,7 +79,7 @@ export default function KycPage() { return (
-

Xác minh danh tính (KYC)

+

Xác minh danh tính (KYC)

Xác minh danh tính để sử dụng đầy đủ tính năng của GoodGo

@@ -131,7 +131,7 @@ export default function KycPage() {
{s.title} {i < KYC_STEPS.length - 1 && ( -
+
)}
))} diff --git a/apps/web/app/[locale]/(dashboard)/dashboard/page.tsx b/apps/web/app/[locale]/(dashboard)/dashboard/page.tsx index a31b46f..04105e5 100644 --- a/apps/web/app/[locale]/(dashboard)/dashboard/page.tsx +++ b/apps/web/app/[locale]/(dashboard)/dashboard/page.tsx @@ -9,6 +9,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com import { formatPrice, formatPricePerM2 } from '@/lib/currency'; import { useMarketReport, useHeatmap } from '@/lib/hooks/use-analytics'; import { useListingsSearch } from '@/lib/hooks/use-listings'; +import { staticBlurDataURL } from '@/lib/image-blur'; const DistrictBarChart = dynamic( () => import('@/components/charts/district-bar-chart').then((mod) => mod.DistrictBarChart), @@ -244,6 +245,8 @@ export default function DashboardPage() { fill sizes="64px" className="object-cover" + placeholder="blur" + blurDataURL={staticBlurDataURL()} /> ) : (
diff --git a/apps/web/app/[locale]/(dashboard)/dashboard/profile/page.tsx b/apps/web/app/[locale]/(dashboard)/dashboard/profile/page.tsx index f1227bc..18c00cb 100644 --- a/apps/web/app/[locale]/(dashboard)/dashboard/profile/page.tsx +++ b/apps/web/app/[locale]/(dashboard)/dashboard/profile/page.tsx @@ -74,7 +74,7 @@ export default function ProfilePage() { return (
-

Hồ sơ cá nhân

+

Hồ sơ cá nhân

Quản lý thông tin tài khoản của bạn

@@ -99,7 +99,7 @@ export default function ProfilePage() {
{/* Profile info */} - +
Thông tin cá nhân Thông tin cơ bản trên hồ sơ của bạn diff --git a/apps/web/app/[locale]/(dashboard)/dashboard/subscription/page.tsx b/apps/web/app/[locale]/(dashboard)/dashboard/subscription/page.tsx index e491282..9e9b7f2 100644 --- a/apps/web/app/[locale]/(dashboard)/dashboard/subscription/page.tsx +++ b/apps/web/app/[locale]/(dashboard)/dashboard/subscription/page.tsx @@ -91,7 +91,7 @@ export default function SubscriptionPage() { return (
-

Gói dịch vụ

+

Gói dịch vụ

Quản lý gói đăng ký và theo dõi hạn mức sử dụng

@@ -112,10 +112,10 @@ export default function SubscriptionPage() {
) : ( - - Gói hiện tại - So sánh gói - Lịch sử thanh toán + + Gói hiện tại + So sánh gói + Lịch sử thanh toán {/* Current plan tab */} diff --git a/apps/web/app/[locale]/(dashboard)/dashboard/valuation/page.tsx b/apps/web/app/[locale]/(dashboard)/dashboard/valuation/page.tsx index 8fee1cb..fe6ec6d 100644 --- a/apps/web/app/[locale]/(dashboard)/dashboard/valuation/page.tsx +++ b/apps/web/app/[locale]/(dashboard)/dashboard/valuation/page.tsx @@ -34,7 +34,7 @@ export default function ValuationPage() { return (
-

Dinh gia AI

+

Dinh gia AI

Su dung AI de uoc tinh gia tri bat dong san dua tren du lieu thi truong

diff --git a/apps/web/app/[locale]/(dashboard)/layout.tsx b/apps/web/app/[locale]/(dashboard)/layout.tsx index 60a409c..517911f 100644 --- a/apps/web/app/[locale]/(dashboard)/layout.tsx +++ b/apps/web/app/[locale]/(dashboard)/layout.tsx @@ -1,7 +1,9 @@ 'use client'; +import { LogOut, Menu, X } from 'lucide-react'; import { usePathname } from 'next/navigation'; import { useTranslations } from 'next-intl'; +import { useState } from 'react'; import { useTheme } from '@/components/providers/theme-provider'; import { Button } from '@/components/ui/button'; import { LanguageSwitcher } from '@/components/ui/language-switcher'; @@ -14,12 +16,14 @@ export default function DashboardLayout({ children }: { children: React.ReactNod const { user, logout } = useAuthStore(); const { theme, toggleTheme } = useTheme(); const t = useTranslations(); + const [sidebarOpen, setSidebarOpen] = useState(false); const navItems = [ { href: '/dashboard' as const, label: t('dashboard.title'), icon: '🏠' }, { href: '/listings' as const, label: t('dashboard.listings'), icon: '📋' }, { href: '/listings/new' as const, label: t('dashboard.createListing'), icon: '➕' }, { href: '/analytics' as const, label: t('dashboard.analytics'), icon: '📊' }, + { href: '/dashboard/saved-searches' as const, label: t('dashboard.savedSearches'), icon: '🔖' }, { href: '/dashboard/valuation' as const, label: t('dashboard.aiValuation'), icon: '🤖' }, { href: '/dashboard/profile' as const, label: t('dashboard.profile'), icon: '👤' }, { href: '/dashboard/subscription' as const, label: t('dashboard.subscription'), icon: '💎' }, @@ -28,30 +32,106 @@ export default function DashboardLayout({ children }: { children: React.ReactNod return (
+ {/* Mobile overlay */} + {sidebarOpen && ( +
setSidebarOpen(false)} + aria-hidden="true" + /> + )} + + {/* Mobile sidebar */} + +
+ {/* Mobile hamburger */} + + {t('common.goodgo')} -
diff --git a/apps/web/app/[locale]/(dashboard)/listings/[id]/edit/page.tsx b/apps/web/app/[locale]/(dashboard)/listings/[id]/edit/page.tsx index 591a287..4a76eda 100644 --- a/apps/web/app/[locale]/(dashboard)/listings/[id]/edit/page.tsx +++ b/apps/web/app/[locale]/(dashboard)/listings/[id]/edit/page.tsx @@ -88,9 +88,9 @@ export default function EditListingPage() { } return ( -
-
-

Chỉnh sửa tin đăng

+
+
+

Chỉnh sửa tin đăng

@@ -102,7 +102,7 @@ export default function EditListingPage() {

- + Cơ bản Vị trí Chi tiết diff --git a/apps/web/app/[locale]/(dashboard)/listings/new/page.tsx b/apps/web/app/[locale]/(dashboard)/listings/new/page.tsx index 0b79277..46994c2 100644 --- a/apps/web/app/[locale]/(dashboard)/listings/new/page.tsx +++ b/apps/web/app/[locale]/(dashboard)/listings/new/page.tsx @@ -130,10 +130,10 @@ export default function CreateListingPage() { return (
-

Đăng tin mới

+

Đăng tin mới

{/* Step indicators */} -
+
{STEPS.map((step, index) => (
+ + {/* Save search dialog */} + {showSaveDialog && ( +
+ {saveSuccess ? ( +
+ + + + Đã lưu tìm kiếm! +
+ ) : ( + <> +

Lưu bộ lọc tìm kiếm

+ + setSaveName(e.target.value)} + placeholder="Tên tìm kiếm (VD: Chung cư Q7 dưới 3 tỷ)" + className="mb-3 w-full rounded-md border bg-background px-3 py-2 text-sm outline-none focus:ring-2 focus:ring-primary" + maxLength={100} + onKeyDown={(e) => e.key === 'Enter' && handleSaveSearch()} + aria-describedby="save-search-heading" + /> +
+ setSaveAlertEnabled(e.target.checked)} + className="rounded" + /> + +
+
+ + +
+ {createSavedSearch.isError && ( +

+ Không thể lưu tìm kiếm. Vui lòng thử lại. +

+ )} + + )} +
+ )} +
+ )}
{/* View Mode Toggle + Mobile Filter Button */} diff --git a/apps/web/app/[locale]/layout.tsx b/apps/web/app/[locale]/layout.tsx index 42de710..88d462a 100644 --- a/apps/web/app/[locale]/layout.tsx +++ b/apps/web/app/[locale]/layout.tsx @@ -1,4 +1,5 @@ import type { Metadata, Viewport } from 'next'; +import { Inter } from 'next/font/google'; import { notFound } from 'next/navigation'; import { NextIntlClientProvider } from 'next-intl'; import { getMessages, getTranslations } from 'next-intl/server'; @@ -11,6 +12,12 @@ import type { Locale } from '@/i18n/config'; import { routing } from '@/i18n/routing'; import '../globals.css'; +const inter = Inter({ + subsets: ['latin', 'vietnamese'], + display: 'swap', + variable: '--font-inter', +}); + const siteUrl = process.env['NEXT_PUBLIC_SITE_URL'] || 'https://goodgo.vn'; export const viewport: Viewport = { @@ -99,8 +106,8 @@ export default async function LocaleLayout({ const t = await getTranslations({ locale, namespace: 'common' }); return ( - - + +