Commit feb3ff57 authored by ThinhNC's avatar ThinhNC

Merge branch 'feat/update-brand-logo' into 'develop'

Feat/update brand logo

See merge request !23
parents 1dfd43b5 2871894d
Pipeline #53123 passed with stage
in 1 minute and 18 seconds
import React from "react"; import React from "react";
import Link from "next/link"; import Link from "next/link";
import { Bot } from "lucide-react"; import Image from "next/image";
import { ThemeToggle } from "@/components/common/theme-toggle"; import { ThemeToggle } from "@/components/common/theme-toggle";
import { LanguageToggle } from "@/components/common/language-toggle"; import { LanguageToggle } from "@/components/common/language-toggle";
...@@ -19,10 +19,17 @@ export default function AuthLayout({ ...@@ -19,10 +19,17 @@ export default function AuthLayout({
<header className="flex w-full items-center justify-between"> <header className="flex w-full items-center justify-between">
<Link <Link
href="/" href="/"
className="flex items-center gap-2.5 transition-opacity hover:opacity-90" className="flex items-center gap-2.5 transition-opacity hover:opacity-90 group"
> >
<div className="flex h-9 w-9 items-center justify-center rounded-2xl bg-gradient-to-br from-emerald-500 to-teal-700 shadow-md shadow-emerald-500/20 text-white"> <div className="relative flex h-9 w-9 items-center justify-center rounded-2xl overflow-hidden shadow-md shadow-emerald-500/20 bg-emerald-500/10 border border-emerald-500/20 group-hover:scale-105 transition-transform duration-200">
<Bot className="h-5 w-5" /> <Image
src="/logo.png"
alt="DataCrawler Logo"
width={36}
height={36}
className="h-full w-full object-contain p-0.5"
priority
/>
</div> </div>
<span className="font-bold text-base tracking-tight text-foreground"> <span className="font-bold text-base tracking-tight text-foreground">
DataCrawler DataCrawler
......
...@@ -585,11 +585,10 @@ export default function CrawlJobDetailPage({ params }: PageProps) { ...@@ -585,11 +585,10 @@ export default function CrawlJobDetailPage({ params }: PageProps) {
id: "pages", id: "pages",
label: t.jobDetail.pagesTab, label: t.jobDetail.pagesTab,
icon: FileText, icon: FileText,
count: (pagesData?.total && pagesData.total > 0) count:
? pagesData.total pagesData?.total !== undefined && pagesData.total > 0
: isJobRunning && job?.successPages ? pagesData.total
? job.successPages : (job?.successPages ?? 0),
: 0,
}, },
{ id: "diff", label: t.jobDetail.diffTab, icon: Sparkles, count: diffData?.summary?.changeRate ? `${Math.round(diffData.summary.changeRate * 100)}%` : undefined }, { id: "diff", label: t.jobDetail.diffTab, icon: Sparkles, count: diffData?.summary?.changeRate ? `${Math.round(diffData.summary.changeRate * 100)}%` : undefined },
].map((tabItem) => { ].map((tabItem) => {
...@@ -857,7 +856,7 @@ export default function CrawlJobDetailPage({ params }: PageProps) { ...@@ -857,7 +856,7 @@ export default function CrawlJobDetailPage({ params }: PageProps) {
<p className="text-xs text-muted-foreground">{t.jobDetail.pages.subtitle}</p> <p className="text-xs text-muted-foreground">{t.jobDetail.pages.subtitle}</p>
</div> </div>
<Badge variant="secondary" className="rounded-full"> <Badge variant="secondary" className="rounded-full">
{pagesData?.total || 0} {t.jobDetail.pages.pagesExtracted} {pagesData?.total ?? job?.successPages ?? 0} {t.jobDetail.pages.pagesExtracted}
</Badge> </Badge>
</div> </div>
......
src/app/favicon.ico

25.3 KB | W: | H:

src/app/favicon.ico

574 KB | W: | H:

src/app/favicon.ico
src/app/favicon.ico
src/app/favicon.ico
src/app/favicon.ico
  • 2-up
  • Swipe
  • Onion skin
...@@ -21,6 +21,13 @@ export const metadata: Metadata = { ...@@ -21,6 +21,13 @@ export const metadata: Metadata = {
}, },
description: description:
"Hệ thống quản lý và giám sát tác vụ cào dữ liệu web realtime, tích hợp Next.js, TanStack Query, React Hook Form và Tailwind CSS.", "Hệ thống quản lý và giám sát tác vụ cào dữ liệu web realtime, tích hợp Next.js, TanStack Query, React Hook Form và Tailwind CSS.",
icons: {
icon: [
{ url: "/logo.png", type: "image/png" },
],
shortcut: "/logo.png",
apple: "/logo.png",
},
}; };
export default function RootLayout({ export default function RootLayout({
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
import React from "react"; import React from "react";
import Link from "next/link"; import Link from "next/link";
import Image from "next/image";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { Activity, Bot, Calendar, Download, FileCode2, Globe } from "lucide-react"; import { Activity, Calendar, Download, FileCode2, Globe } from "lucide-react";
import { ThemeToggle } from "./theme-toggle"; import { ThemeToggle } from "./theme-toggle";
import { LanguageToggle } from "./language-toggle"; import { LanguageToggle } from "./language-toggle";
import { UserMenu } from "./user-menu"; import { UserMenu } from "./user-menu";
...@@ -23,9 +24,16 @@ export function Navbar() { ...@@ -23,9 +24,16 @@ export function Navbar() {
<header className="sticky top-0 z-40 w-full border-b border-border/70 bg-card/80 backdrop-blur-md transition-colors duration-200"> <header className="sticky top-0 z-40 w-full border-b border-border/70 bg-card/80 backdrop-blur-md transition-colors duration-200">
<div className="flex h-16 w-full items-center justify-between px-4 sm:px-6 lg:px-8"> <div className="flex h-16 w-full items-center justify-between px-4 sm:px-6 lg:px-8">
{/* Brand */} {/* Brand */}
<Link href="/" className="flex items-center gap-3 transition-opacity hover:opacity-90"> <Link href="/" className="flex items-center gap-2.5 transition-opacity hover:opacity-90 group">
<div className="flex h-10 w-10 items-center justify-center rounded-2xl bg-gradient-to-br from-emerald-500 to-teal-700 shadow-md shadow-emerald-500/20"> <div className="relative flex h-10 w-10 items-center justify-center rounded-2xl overflow-hidden shadow-md shadow-emerald-500/20 bg-emerald-500/10 border border-emerald-500/20 group-hover:scale-105 transition-transform duration-200">
<Bot className="h-6 w-6 text-white" /> <Image
src="/logo.png"
alt="DataCrawler Logo"
width={40}
height={40}
className="h-full w-full object-contain p-1"
priority
/>
</div> </div>
<span className="font-bold text-lg tracking-tight text-foreground">DataCrawler</span> <span className="font-bold text-lg tracking-tight text-foreground">DataCrawler</span>
</Link> </Link>
......
...@@ -2,8 +2,9 @@ ...@@ -2,8 +2,9 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import Link from "next/link"; import Link from "next/link";
import Image from "next/image";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { Compass, Home, Bot } from "lucide-react"; import { Compass, Home } from "lucide-react";
import { useLanguage } from "@/providers/language-provider"; import { useLanguage } from "@/providers/language-provider";
import { ThemeToggle } from "@/components/common/theme-toggle"; import { ThemeToggle } from "@/components/common/theme-toggle";
import { LanguageToggle } from "@/components/common/language-toggle"; import { LanguageToggle } from "@/components/common/language-toggle";
...@@ -81,10 +82,17 @@ export function NotFoundClient() { ...@@ -81,10 +82,17 @@ export function NotFoundClient() {
<header className="flex w-full items-center justify-between"> <header className="flex w-full items-center justify-between">
<Link <Link
href="/" href="/"
className="flex items-center gap-2.5 transition-opacity hover:opacity-90" className="flex items-center gap-2.5 transition-opacity hover:opacity-90 group"
> >
<div className="flex h-9 w-9 items-center justify-center rounded-2xl bg-gradient-to-br from-emerald-500 to-teal-700 shadow-md shadow-emerald-500/20 text-white"> <div className="relative flex h-9 w-9 items-center justify-center rounded-2xl overflow-hidden shadow-md shadow-emerald-500/20 bg-emerald-500/10 border border-emerald-500/20 group-hover:scale-105 transition-transform duration-200">
<Bot className="h-5 w-5" /> <Image
src="/logo.png"
alt="DataCrawler Logo"
width={36}
height={36}
className="h-full w-full object-contain p-0.5"
priority
/>
</div> </div>
<span className="font-bold text-base tracking-tight text-foreground"> <span className="font-bold text-base tracking-tight text-foreground">
DataCrawler DataCrawler
......
...@@ -90,7 +90,7 @@ export function notifyJobCompletion({ ...@@ -90,7 +90,7 @@ export function notifyJobCompletion({
const notification = new Notification(finalTitle, { const notification = new Notification(finalTitle, {
body: finalBody, body: finalBody,
icon: "/favicon.ico", icon: "/logo.png",
tag: `crawl-job-completed-${jobId}`, tag: `crawl-job-completed-${jobId}`,
}); });
......
...@@ -219,15 +219,39 @@ export const crawlJobService = { ...@@ -219,15 +219,39 @@ export const crawlJobService = {
const response = await apiClient.get< const response = await apiClient.get<
ApiResponse<{ ApiResponse<{
items: CrawlPagePreview[]; items: CrawlPagePreview[];
total: number; total?: number;
page: number; page?: number;
limit: number; limit?: number;
totalPages: number; totalPages?: number;
meta?: {
total?: number;
page?: number;
limit?: number;
totalPages?: number;
};
}> }>
>(`/crawl-jobs/${id}/pages/preview?${params.toString()}`); >(`/crawl-jobs/${id}/pages/preview?${params.toString()}`);
if (response.data?.data) { const raw = response.data?.data;
return response.data.data; if (raw) {
const total =
raw.total ??
raw.meta?.total ??
(Array.isArray(raw.items) ? raw.items.length : 0);
const totalPages =
raw.totalPages ??
raw.meta?.totalPages ??
Math.max(1, Math.ceil(total / limit));
const pageNum = raw.page ?? raw.meta?.page ?? page;
const limitNum = raw.limit ?? raw.meta?.limit ?? limit;
return {
items: raw.items || [],
total,
page: pageNum,
limit: limitNum,
totalPages,
};
} }
throw new Error("Invalid pages preview response"); throw new Error("Invalid pages preview response");
}, },
......
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