fix: Resolve merge conflicts and clean up imports in multiple components
Release package / release (pull_request) Failing after 14s

This commit is contained in:
Thanh Quy - wolf
2026-04-13 20:41:24 +07:00
parent e326e11bb4
commit 460e8a4ac1
6 changed files with 0 additions and 243 deletions
-8
View File
@@ -1,9 +1,5 @@
"use client";
<<<<<<< HEAD
=======
import LoginForm from "@/components/organisms/forms/LoginForm";
>>>>>>> main
import { SHOP_INFO } from "@/lib/constants";
import LoginForm from "@/components/organisms/forms/LoginForm";
import Image from "next/image";
@@ -32,11 +28,7 @@ export default function LoginPage() {
Đăng nhập vào hệ thống
</p>
</div>
<<<<<<< HEAD
=======
>>>>>>> main
{/* Login Form */}
<LoginForm />
-11
View File
@@ -1,15 +1,8 @@
"use client";
<<<<<<< HEAD
import { CategorySidebar } from "@/components/organisms/navigation";
import { ProductGrid } from "@/components/organisms/product-grid";
import { SearchBar } from "@/components/molecules/search-bar";
=======
import { SearchBar } from "@/components/molecules/search-bar";
import { CategorySidebar } from "@/components/organisms/navigation";
import { ProductGrid } from "@/components/organisms/product-grid";
import { MENU_CATEGORIES } from "@/lib/constants";
>>>>>>> main
import { useMenu } from "@/lib/menu-context";
import { MENU_CATEGORIES } from "@/lib/constants";
import { useEffect, useState } from "react";
@@ -79,14 +72,10 @@ export default function Home() {
</div>
{/* ── Product grid (organism handles mobile category menu + grid) ── */}
<<<<<<< HEAD
<ProductGrid
searchQuery={searchQuery}
isSidebarOpen={isSidebarOpen}
/>
=======
<ProductGrid searchQuery={searchQuery} isSidebarOpen={isSidebarOpen} />
>>>>>>> main
</main>
</div>
);
-8
View File
@@ -75,11 +75,7 @@ export default function PaymentPage() {
<div className="flex items-center gap-2">
<button
onClick={() => decreaseQty(item.id)}
<<<<<<< HEAD
className="inline-flex items-center justify-center h-8 w-8 rounded-lg border border-(--color-border) hover:bg-(--color-border-light)"
=======
className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-(--color-border) hover:bg-(--color-border-light)"
>>>>>>> main
aria-label={`Giảm số lượng ${item.name}`}
>
-
@@ -96,11 +92,7 @@ export default function PaymentPage() {
/>
<button
onClick={() => increaseQty(item.id)}
<<<<<<< HEAD
className="inline-flex items-center justify-center h-8 w-8 rounded-lg border border-(--color-border) hover:bg-(--color-border-light)"
=======
className="inline-flex h-8 w-8 items-center justify-center rounded-lg border border-(--color-border) hover:bg-(--color-border-light)"
>>>>>>> main
aria-label={`Tăng số lượng ${item.name}`}
>
+
-13
View File
@@ -7,7 +7,6 @@ import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { FormEvent, useState } from "react";
import Button from "@/components/atoms/buttons/Button";
// Static OTP for demo (in production, this would be sent via SMS)
const DEMO_OTP = "123456";
@@ -162,16 +161,12 @@ export default function RegisterPage() {
{/* Buttons */}
<div className="space-y-3 pt-2">
{/* Submit Button */}
<<<<<<< HEAD
<Button variant="primaryNoBorder" type="submit" style="login" size="lg">
=======
<Button
variant="primaryNoBorder"
type="submit"
style="login"
size="lg"
>
>>>>>>> main
Tiếp tục
</Button>
@@ -237,30 +232,22 @@ export default function RegisterPage() {
{/* Buttons */}
<div className="space-y-3 pt-2">
{/* Submit Button */}
<<<<<<< HEAD
<Button variant="primaryNoBorder" type="submit" style="login" size="lg">
=======
<Button
variant="primaryNoBorder"
type="submit"
style="login"
size="lg"
>
>>>>>>> main
Hoàn tất đăng
</Button>
{/* Back Button */}
<<<<<<< HEAD
<Button variant="bgWhite" onClick={handleBackToPhone} size="lg" style="login">
=======
<Button
variant="bgWhite"
onClick={handleBackToPhone}
size="lg"
style="login"
>
>>>>>>> main
Thay đi số điện thoại
</Button>
</div>
-126
View File
@@ -8,15 +8,11 @@ import {
SummaryCard,
} from "@/components/organisms/analytics";
import type { PieSlice } from "@/components/organisms/analytics";
<<<<<<< HEAD
import { calcChange, formatCurrency, formatCurrencyFull } from "@/lib/analytics-utils";
=======
import {
calcChange,
formatCurrency,
formatCurrencyFull,
} from "@/lib/analytics-utils";
>>>>>>> main
import {
MENU_CATEGORIES,
MOCK_PRODUCT_SALES,
@@ -39,10 +35,6 @@ const PERIOD_LABELS: Record<AnalyticsPeriod, string> = {
};
const CATEGORY_COLORS = [
<<<<<<< HEAD
"#6F4E37", "#C8973A", "#A0785A", "#8B6914", "#D4A96A",
"#4A3728", "#F0D9A8", "#A08060", "#3D2B1F",
=======
"#6F4E37",
"#C8973A",
"#A0785A",
@@ -52,7 +44,6 @@ const CATEGORY_COLORS = [
"#F0D9A8",
"#A08060",
"#3D2B1F",
>>>>>>> main
];
const REVENUE_MAP: Record<AnalyticsPeriod, RevenueDataPoint[]> = {
@@ -67,13 +58,8 @@ type ChartType = (typeof CHART_TYPES)[number];
const CHART_META: Record<ChartType, { icon: string; label: string }> = {
line: { icon: "fa-chart-line", label: "Line" },
<<<<<<< HEAD
bar: { icon: "fa-chart-bar", label: "Bar" },
pie: { icon: "fa-chart-pie", label: "Pie" },
=======
bar: { icon: "fa-chart-bar", label: "Bar" },
pie: { icon: "fa-chart-pie", label: "Pie" },
>>>>>>> main
};
// ─── Category filter select ───────────────────────────────────────────────────
@@ -99,13 +85,9 @@ function CategorySelect({
>
<option value="all">Tất cả</option>
{categories.map((c) => (
<<<<<<< HEAD
<option key={c.id} value={c.id}>{c.name}</option>
=======
<option key={c.id} value={c.id}>
{c.name}
</option>
>>>>>>> main
))}
</select>
</div>
@@ -124,47 +106,28 @@ export default function AnalyticsPage() {
// Split into halves for bar comparison
const half = Math.floor(revenueData.length / 2);
<<<<<<< HEAD
const barCurrent = revenueData.slice(half);
=======
const barCurrent = revenueData.slice(half);
>>>>>>> main
const barPrevious = revenueData.slice(0, half).slice(0, barCurrent.length);
// Filtered product sales
const filteredSales = useMemo(
<<<<<<< HEAD
() => categoryFilter === "all"
? MOCK_PRODUCT_SALES
: MOCK_PRODUCT_SALES.filter((p) => p.category === categoryFilter),
=======
() =>
categoryFilter === "all"
? MOCK_PRODUCT_SALES
: MOCK_PRODUCT_SALES.filter((p) => p.category === categoryFilter),
>>>>>>> main
[categoryFilter],
);
// Summary stats
const totalRevenue = revenueData.reduce((s, d) => s + d.revenue, 0);
<<<<<<< HEAD
const totalOrders = revenueData.reduce((s, d) => s + d.orders, 0);
const totalProfit = filteredSales.reduce((s, d) => s + d.profit, 0);
=======
const totalOrders = revenueData.reduce((s, d) => s + d.orders, 0);
const totalProfit = filteredSales.reduce((s, d) => s + d.profit, 0);
>>>>>>> main
const avgOrderValue = totalOrders > 0 ? totalRevenue / totalOrders : 0;
// Period-over-period comparisons
const curRevenue = barCurrent.reduce((s, d) => s + d.revenue, 0);
const prevRevenue = barPrevious.reduce((s, d) => s + d.revenue, 0);
<<<<<<< HEAD
const curOrders = barCurrent.reduce((s, d) => s + d.orders, 0);
=======
const curOrders = barCurrent.reduce((s, d) => s + d.orders, 0);
>>>>>>> main
const prevOrders = barPrevious.reduce((s, d) => s + d.orders, 0);
const revComp = calcChange(curRevenue, prevRevenue);
const ordComp = calcChange(curOrders, prevOrders);
@@ -193,13 +156,6 @@ export default function AnalyticsPage() {
// Totals for summary row
const filteredRevenue = filteredSales.reduce((s, d) => s + d.revenue, 0);
<<<<<<< HEAD
const filteredProfit = filteredSales.reduce((s, d) => s + d.profit, 0);
const filteredUnits = filteredSales.reduce((s, d) => s + d.unitsSold, 0);
const avgMargin = filteredSales.length > 0
? filteredSales.reduce((s, d) => s + d.profitMargin, 0) / filteredSales.length
: 0;
=======
const filteredProfit = filteredSales.reduce((s, d) => s + d.profit, 0);
const filteredUnits = filteredSales.reduce((s, d) => s + d.unitsSold, 0);
const avgMargin =
@@ -207,7 +163,6 @@ export default function AnalyticsPage() {
? filteredSales.reduce((s, d) => s + d.profitMargin, 0) /
filteredSales.length
: 0;
>>>>>>> main
return (
<div className="bg-background min-h-screen">
@@ -228,13 +183,9 @@ export default function AnalyticsPage() {
<h1 className="text-foreground text-lg leading-tight font-bold">
Thống & Phân tích tài chính
</h1>
<<<<<<< HEAD
<p className="text-xs text-(--color-text-muted)">Financial Analytics Dashboard</p>
=======
<p className="text-xs text-(--color-text-muted)">
Financial Analytics Dashboard
</p>
>>>>>>> main
</div>
</div>
@@ -259,17 +210,12 @@ export default function AnalyticsPage() {
onChange={(e) => setPeriod(e.target.value as AnalyticsPeriod)}
className="text-foreground block rounded-lg border border-(--color-border) bg-(--color-bg-card) px-2 py-1.5 text-xs sm:hidden"
>
<<<<<<< HEAD
{(Object.entries(PERIOD_LABELS) as [AnalyticsPeriod, string][]).map(([k, v]) => (
<option key={k} value={k}>{v}</option>
=======
{(
Object.entries(PERIOD_LABELS) as [AnalyticsPeriod, string][]
).map(([k, v]) => (
<option key={k} value={k}>
{v}
</option>
>>>>>>> main
))}
</select>
</div>
@@ -283,20 +229,6 @@ export default function AnalyticsPage() {
Tổng quan
</h2>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4">
<<<<<<< HEAD
<SummaryCard icon="fa-solid fa-sack-dollar" title="Tổng doanh thu"
value={formatCurrency(totalRevenue)} subtitle={PERIOD_LABELS[period]}
change={revComp.change} changePercent={revComp.changePercent} isPositive={revComp.isPositive} />
<SummaryCard icon="fa-solid fa-receipt" title="Số đơn hàng"
value={totalOrders.toLocaleString()} subtitle="Tổng đơn trong kỳ"
change={ordComp.change} changePercent={ordComp.changePercent} isPositive={ordComp.isPositive} />
<SummaryCard icon="fa-solid fa-circle-dollar-to-slot" title="Tổng lợi nhuận"
value={formatCurrency(totalProfit)} subtitle="Ước tính từ dữ liệu bán hàng"
change={proComp.change} changePercent={proComp.changePercent} isPositive={proComp.isPositive} />
<SummaryCard icon="fa-solid fa-basket-shopping" title="Giá trị đơn TB"
value={formatCurrency(avgOrderValue)} subtitle="Doanh thu / số đơn hàng"
change={0} changePercent={0} isPositive={true} />
=======
<SummaryCard
icon="fa-solid fa-sack-dollar"
title="Tổng doanh thu"
@@ -333,7 +265,6 @@ export default function AnalyticsPage() {
changePercent={0}
isPositive={true}
/>
>>>>>>> main
</div>
</section>
@@ -356,13 +287,9 @@ export default function AnalyticsPage() {
}`}
>
<i className={`fa-solid text-xs ${CHART_META[t].icon}`}></i>
<<<<<<< HEAD
<span className="hidden sm:inline">{CHART_META[t].label}</span>
=======
<span className="hidden sm:inline">
{CHART_META[t].label}
</span>
>>>>>>> main
</button>
))}
</div>
@@ -370,22 +297,14 @@ export default function AnalyticsPage() {
{activeChart === "line" && (
<>
<<<<<<< HEAD
<p className="mb-3 text-xs text-(--color-text-muted)">Doanh thu theo thời gian {PERIOD_LABELS[period]}</p>
=======
<p className="mb-3 text-xs text-(--color-text-muted)">
Doanh thu theo thời gian {PERIOD_LABELS[period]}
</p>
>>>>>>> main
<LineChart data={revenueData} height={220} />
</>
)}
{activeChart === "bar" && (
<>
<<<<<<< HEAD
<p className="mb-3 text-xs text-(--color-text-muted)">So sánh doanh thu nửa đu nửa sau kỳ hiện tại</p>
<BarChart current={barCurrent} previous={barPrevious} height={220} />
=======
<p className="mb-3 text-xs text-(--color-text-muted)">
So sánh doanh thu nửa đu nửa sau kỳ hiện tại
</p>
@@ -394,18 +313,13 @@ export default function AnalyticsPage() {
previous={barPrevious}
height={220}
/>
>>>>>>> main
</>
)}
{activeChart === "pie" && (
<>
<<<<<<< HEAD
<p className="mb-3 text-xs text-(--color-text-muted)">Tỷ trọng doanh thu theo danh mục sản phẩm</p>
=======
<p className="mb-3 text-xs text-(--color-text-muted)">
Tỷ trọng doanh thu theo danh mục sản phẩm
</p>
>>>>>>> main
<PieChart data={pieData} />
</>
)}
@@ -418,14 +332,10 @@ export default function AnalyticsPage() {
<i className="fa-solid fa-fire mr-2 text-orange-500"></i>
Top sản phẩm bán chạy
</h2>
<<<<<<< HEAD
<CategorySelect value={categoryFilter} onChange={setCategoryFilter} />
=======
<CategorySelect
value={categoryFilter}
onChange={setCategoryFilter}
/>
>>>>>>> main
</div>
<div className="space-y-3">
{top5.map((p, i) => {
@@ -437,17 +347,6 @@ export default function AnalyticsPage() {
<span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-(--color-accent-light) text-xs font-bold text-(--color-primary)">
{i + 1}
</span>
<<<<<<< HEAD
<span className="text-foreground truncate text-sm font-medium">{p.name}</span>
</div>
<div className="flex shrink-0 items-center gap-3 text-xs">
<span className="text-(--color-text-muted) tabular-nums">{p.unitsSold} ly</span>
<span className="font-semibold text-(--color-primary) tabular-nums">{formatCurrency(p.revenue)}</span>
</div>
</div>
<div className="bg-background h-2 overflow-hidden rounded-full">
<div className="h-full rounded-full bg-(--color-primary) transition-all duration-500" style={{ width: `${pct}%` }} />
=======
<span className="text-foreground truncate text-sm font-medium">
{p.name}
</span>
@@ -466,7 +365,6 @@ export default function AnalyticsPage() {
className="h-full rounded-full bg-(--color-primary) transition-all duration-500"
style={{ width: `${pct}%` }}
/>
>>>>>>> main
</div>
</div>
);
@@ -481,12 +379,6 @@ export default function AnalyticsPage() {
<i className="fa-solid fa-table text-foreground mr-2"></i>
Phân tích chi tiết sản phẩm
</h2>
<<<<<<< HEAD
<CategorySelect value={categoryFilter} onChange={setCategoryFilter} label="Lọc danh mục:" />
</div>
<p className="mb-3 text-xs text-(--color-text-muted)">
Click vào tiêu đ cột đ sắp xếp. Hiển thị {filteredSales.length} sản phẩm.
=======
<CategorySelect
value={categoryFilter}
onChange={setCategoryFilter}
@@ -496,29 +388,12 @@ export default function AnalyticsPage() {
<p className="mb-3 text-xs text-(--color-text-muted)">
Click vào tiêu đ cột đ sắp xếp. Hiển thị {filteredSales.length}{" "}
sản phẩm.
>>>>>>> main
</p>
<ProductTable data={filteredSales} />
{/* Summary row */}
<div className="bg-background mt-4 flex flex-wrap gap-4 rounded-xl p-4 text-sm">
<div>
<<<<<<< HEAD
<span className="text-(--color-text-muted)">Tổng doanh thu: </span>
<span className="font-semibold text-(--color-primary)">{formatCurrencyFull(filteredRevenue)}</span>
</div>
<div>
<span className="text-(--color-text-muted)">Tổng lợi nhuận: </span>
<span className="font-semibold text-green-600">{formatCurrencyFull(filteredProfit)}</span>
</div>
<div>
<span className="text-(--color-text-muted)">Tổng sản lượng: </span>
<span className="text-foreground font-semibold">{filteredUnits.toLocaleString()} ly</span>
</div>
<div>
<span className="text-(--color-text-muted)">Biên LN trung bình: </span>
<span className="font-semibold text-yellow-700">{avgMargin.toFixed(1)}%</span>
=======
<span className="text-(--color-text-muted)">
Tổng doanh thu:{" "}
</span>
@@ -549,7 +424,6 @@ export default function AnalyticsPage() {
<span className="font-semibold text-yellow-700">
{avgMargin.toFixed(1)}%
</span>
>>>>>>> main
</div>
</div>
</section>
-77
View File
@@ -8,19 +8,11 @@ import {
import { useAuth } from "@/lib/auth-context";
import { useManager } from "@/lib/manager-context";
import Link from "next/link";
<<<<<<< HEAD
import { useState } from "react";
=======
>>>>>>> main
export default function ManagerPage() {
const { user, logout } = useAuth();
const { activeTab, setActiveTab, products, combos, categories } =
useManager();
<<<<<<< HEAD
const [mobileNavOpen, setMobileNavOpen] = useState(false);
=======
>>>>>>> main
const tabs = [
{
@@ -98,7 +90,6 @@ export default function ManagerPage() {
Mới
</span>
</Link>
<<<<<<< HEAD
<Link
href="/staff/schedule"
className="hover:bg-background flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-sm font-medium text-(--color-text-secondary) no-underline transition-all hover:text-(--color-primary-dark)"
@@ -109,8 +100,6 @@ export default function ManagerPage() {
Mới
</span>
</Link>
=======
>>>>>>> main
</div>
</nav>
@@ -163,71 +152,6 @@ export default function ManagerPage() {
</p>
</div>
<<<<<<< HEAD
{/* Mobile dropdown navigation */}
<div className="relative lg:hidden">
<button
type="button"
onClick={() => setMobileNavOpen((prev) => !prev)}
className="flex cursor-pointer items-center gap-2 rounded-xl border border-(--color-border-light) bg-white px-3 py-2 text-xs font-medium text-(--color-text-secondary) transition hover:bg-gray-50"
>
<i className="fa-solid fa-bars"></i>
Tác vụ
<i
className={`fa-solid fa-chevron-${mobileNavOpen ? "up" : "down"} text-[10px]`}
></i>
</button>
{mobileNavOpen && (
<div className="absolute right-0 top-11 z-50 w-56 rounded-xl border border-(--color-border-light) bg-white p-2 shadow-lg">
{tabs.map((tab) => (
<button
key={tab.id}
type="button"
onClick={() => {
setActiveTab(tab.id);
setMobileNavOpen(false);
}}
className={`mb-1 flex w-full cursor-pointer items-center gap-2 rounded-lg border-none px-3 py-2 text-left text-xs font-medium transition ${
activeTab === tab.id
? "bg-(--color-primary) text-white"
: "bg-transparent text-(--color-text-secondary) hover:bg-gray-50"
}`}
>
<i className={`${tab.icon} w-4 text-center`}></i>
<span className="flex-1">{tab.label}</span>
<span
className={`rounded-full px-1.5 py-0.5 text-[10px] ${
activeTab === tab.id
? "bg-white/20 text-white"
: "bg-(--color-border-light) text-(--color-text-muted)"
}`}
>
{tab.count}
</span>
</button>
))}
<Link
href="/manager/analytics"
onClick={() => setMobileNavOpen(false)}
className="mb-1 flex items-center gap-2 rounded-lg px-3 py-2 text-xs font-medium text-(--color-primary) no-underline transition hover:bg-(--color-accent-light)/70"
>
<i className="fa-solid fa-chart-line w-4 text-center"></i>
<span className="flex-1">Tài chính</span>
</Link>
<Link
href="/staff/schedule"
onClick={() => setMobileNavOpen(false)}
className="flex items-center gap-2 rounded-lg px-3 py-2 text-xs font-medium text-(--color-primary) no-underline transition hover:bg-(--color-accent-light)/70"
>
<i className="fa-solid fa-calendar-days w-4 text-center"></i>
<span className="flex-1">Ca làm</span>
</Link>
</div>
)}
=======
{/* Mobile tabs */}
<div className="flex items-center gap-1 lg:hidden">
{tabs.map((tab) => (
@@ -251,7 +175,6 @@ export default function ManagerPage() {
<i className="fa-solid fa-chart-line"></i>
<span className="hidden sm:inline">Tài chính</span>
</Link>
>>>>>>> main
</div>
{/* Desktop actions */}