chore: release [ci skip]

This commit is contained in:
gitea-actions
2026-05-05 14:49:39 +00:00
parent c2afb3d3b5
commit edbf675997
15 changed files with 452 additions and 316 deletions
+7 -2
View File
@@ -68,7 +68,10 @@ export default function LoginPasswordPage() {
setErrors({ password: "", general: msg }); setErrors({ password: "", general: msg });
} }
} catch { } catch {
setErrors({ password: "", general: "Unable to connect, please try again" }); setErrors({
password: "",
general: "Unable to connect, please try again",
});
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
@@ -134,7 +137,9 @@ export default function LoginPasswordPage() {
className="absolute top-1/2 right-4 -translate-y-1/2 text-(--color-text-muted) transition-colors hover:text-(--color-primary)" className="absolute top-1/2 right-4 -translate-y-1/2 text-(--color-text-muted) transition-colors hover:text-(--color-primary)"
aria-label={showPassword ? "Hide password" : "Show password"} aria-label={showPassword ? "Hide password" : "Show password"}
> >
<i className={`fa-solid ${showPassword ? "fa-eye-slash" : "fa-eye"}`}></i> <i
className={`fa-solid ${showPassword ? "fa-eye-slash" : "fa-eye"}`}
></i>
</button> </button>
</div> </div>
{errors.password && ( {errors.password && (
+133 -27
View File
@@ -14,13 +14,24 @@ export default function ManagerSignupPage() {
const [pageState, setPageState] = useState<PageState>("checking"); const [pageState, setPageState] = useState<PageState>("checking");
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [form, setForm] = useState({ name: "", phone: "", password: "", eateryName: "" }); const [form, setForm] = useState({
const [errors, setErrors] = useState({ name: "", phone: "", password: "", eateryName: "", submit: "" }); name: "",
phone: "",
password: "",
eateryName: "",
});
const [errors, setErrors] = useState({
name: "",
phone: "",
password: "",
eateryName: "",
submit: "",
});
useEffect(() => { useEffect(() => {
fetch("/api/manager/signup") fetch("/api/manager/signup")
.then((res) => { .then((res) => {
setPageState("available") setPageState("available");
// if (res.ok) ; // if (res.ok) ;
// else if (res.status === 403) setPageState("closed"); // else if (res.status === 403) setPageState("closed");
// else setPageState("error"); // else setPageState("error");
@@ -28,21 +39,32 @@ export default function ManagerSignupPage() {
.catch(() => setPageState("error")); .catch(() => setPageState("error"));
}, []); }, []);
const validatePhone = (phone: string) => /^(0[3|5|7|8|9])[0-9]{8}$/.test(phone); const validatePhone = (phone: string) =>
/^(0[3|5|7|8|9])[0-9]{8}$/.test(phone);
const handleChange = (field: keyof typeof form) => (e: React.ChangeEvent<HTMLInputElement>) => { const handleChange =
(field: keyof typeof form) => (e: React.ChangeEvent<HTMLInputElement>) => {
setForm({ ...form, [field]: e.target.value }); setForm({ ...form, [field]: e.target.value });
setErrors({ ...errors, [field]: "", submit: "" }); setErrors({ ...errors, [field]: "", submit: "" });
}; };
const validate = () => { const validate = () => {
const next = { name: "", phone: "", password: "", eateryName: "", submit: "" }; const next = {
name: "",
phone: "",
password: "",
eateryName: "",
submit: "",
};
if (!form.name.trim()) next.name = "Please enter your full name"; if (!form.name.trim()) next.name = "Please enter your full name";
if (!form.phone.trim()) next.phone = "Please enter your phone number"; if (!form.phone.trim()) next.phone = "Please enter your phone number";
else if (!validatePhone(form.phone)) next.phone = "Invalid phone number (e.g. 0987654321)"; else if (!validatePhone(form.phone))
next.phone = "Invalid phone number (e.g. 0987654321)";
if (!form.password.trim()) next.password = "Please enter your password"; if (!form.password.trim()) next.password = "Please enter your password";
else if (form.password.length < 6) next.password = "Password must be at least 6 characters"; else if (form.password.length < 6)
if (!form.eateryName.trim()) next.eateryName = "Please enter the restaurant name"; next.password = "Password must be at least 6 characters";
if (!form.eateryName.trim())
next.eateryName = "Please enter the restaurant name";
setErrors(next); setErrors(next);
return !next.name && !next.phone && !next.password && !next.eateryName; return !next.name && !next.phone && !next.password && !next.eateryName;
}; };
@@ -67,7 +89,10 @@ export default function ManagerSignupPage() {
ExistedUser: "Phone number already registered", ExistedUser: "Phone number already registered",
InvalidPhoneNumber: "Invalid phone number", InvalidPhoneNumber: "Invalid phone number",
}; };
setErrors({ ...errors, submit: errorMap[errorCode] ?? "An error occurred, please try again" }); setErrors({
...errors,
submit: errorMap[errorCode] ?? "An error occurred, please try again",
});
} }
} catch { } catch {
setErrors({ ...errors, submit: "Unable to connect, please try again" }); setErrors({ ...errors, submit: "Unable to connect, please try again" });
@@ -82,10 +107,21 @@ export default function ManagerSignupPage() {
{/* Logo */} {/* Logo */}
<div className="mb-8 flex flex-col items-center"> <div className="mb-8 flex flex-col items-center">
<div className="relative mb-4 h-20 w-20"> <div className="relative mb-4 h-20 w-20">
<Image src={SHOP_INFO.logo} alt={SHOP_INFO.name} fill className="object-contain" sizes="80px" priority /> <Image
src={SHOP_INFO.logo}
alt={SHOP_INFO.name}
fill
className="object-contain"
sizes="80px"
priority
/>
</div> </div>
<h1 className="mb-1 text-2xl font-bold text-(--color-primary-dark)">{SHOP_INFO.name}</h1> <h1 className="mb-1 text-2xl font-bold text-(--color-primary-dark)">
<p className="text-sm text-(--color-text-muted)">Create a manager account</p> {SHOP_INFO.name}
</h1>
<p className="text-sm text-(--color-text-muted)">
Create a manager account
</p>
</div> </div>
{/* Checking */} {/* Checking */}
@@ -103,8 +139,13 @@ export default function ManagerSignupPage() {
<i className="fa-solid fa-lock text-2xl text-red-500"></i> <i className="fa-solid fa-lock text-2xl text-red-500"></i>
</div> </div>
<div className="text-center"> <div className="text-center">
<h2 className="mb-2 text-lg font-semibold text-(--color-text-primary)">Registration closed</h2> <h2 className="mb-2 text-lg font-semibold text-(--color-text-primary)">
<p className="text-sm text-(--color-text-muted)">The system already has a restaurant. Registration is no longer available.</p> Registration closed
</h2>
<p className="text-sm text-(--color-text-muted)">
The system already has a restaurant. Registration is no longer
available.
</p>
</div> </div>
<Link <Link
href="/login" href="/login"
@@ -122,13 +163,36 @@ export default function ManagerSignupPage() {
<i className="fa-solid fa-triangle-exclamation text-2xl text-yellow-500"></i> <i className="fa-solid fa-triangle-exclamation text-2xl text-yellow-500"></i>
</div> </div>
<div className="text-center"> <div className="text-center">
<h2 className="mb-2 text-lg font-semibold text-(--color-text-primary)">Không thể kết nối</h2> <h2 className="mb-2 text-lg font-semibold text-(--color-text-primary)">
<p className="text-sm text-(--color-text-muted)">Không thể kiểm tra trạng thái đăng . Vui lòng thử lại.</p> Không thể kết nối
</h2>
<p className="text-sm text-(--color-text-muted)">
Không thể kiểm tra trạng thái đăng . Vui lòng thử lại.
</p>
</div> </div>
<Button variant="primaryNoBorder" style="login" size="lg" onClick={() => { setPageState("checking"); fetch("/api/manager/signup").then((r) => { if (r.ok) setPageState("available"); else if (r.status === 403) setPageState("closed"); else setPageState("error"); }).catch(() => setPageState("error")); }}> <Button
variant="primaryNoBorder"
style="login"
size="lg"
onClick={() => {
setPageState("checking");
fetch("/api/manager/signup")
.then((r) => {
if (r.ok) setPageState("available");
else if (r.status === 403) setPageState("closed");
else setPageState("error");
})
.catch(() => setPageState("error"));
}}
>
Thử lại Thử lại
</Button> </Button>
<Link href="/login" className="text-sm text-(--color-primary) underline">Quay lại đăng nhập</Link> <Link
href="/login"
className="text-sm text-(--color-primary) underline"
>
Quay lại đăng nhập
</Link>
</div> </div>
)} )}
@@ -136,17 +200,50 @@ export default function ManagerSignupPage() {
{pageState === "available" && ( {pageState === "available" && (
<form onSubmit={handleSubmit} className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4">
{[ {[
{ id: "name", label: "Họ tên", icon: "fa-user", placeholder: "Nguyễn Văn A", field: "name" as const, type: "text" }, {
{ id: "phone", label: "Số điện thoại", icon: "fa-phone", placeholder: "0987654321", field: "phone" as const, type: "tel" }, id: "name",
{ id: "password", label: "Mật khẩu", icon: "fa-lock", placeholder: "Ít nhất 6 ký tự", field: "password" as const, type: "password" }, label: "Họ tên",
{ id: "eateryName", label: "Tên nhà hàng", icon: "fa-store", placeholder: "Coffee & More", field: "eateryName" as const, type: "text" }, icon: "fa-user",
placeholder: "Nguyễn Văn A",
field: "name" as const,
type: "text",
},
{
id: "phone",
label: "Số điện thoại",
icon: "fa-phone",
placeholder: "0987654321",
field: "phone" as const,
type: "tel",
},
{
id: "password",
label: "Mật khẩu",
icon: "fa-lock",
placeholder: "Ít nhất 6 ký tự",
field: "password" as const,
type: "password",
},
{
id: "eateryName",
label: "Tên nhà hàng",
icon: "fa-store",
placeholder: "Coffee & More",
field: "eateryName" as const,
type: "text",
},
].map(({ id, label, icon, placeholder, field, type }) => ( ].map(({ id, label, icon, placeholder, field, type }) => (
<div key={id}> <div key={id}>
<label htmlFor={id} className="mb-2 block text-sm font-medium text-(--color-text-secondary)"> <label
htmlFor={id}
className="mb-2 block text-sm font-medium text-(--color-text-secondary)"
>
{label} {label}
</label> </label>
<div className="relative"> <div className="relative">
<i className={`fa-solid ${icon} absolute top-1/2 left-4 hidden -translate-y-1/2 text-(--color-text-muted) lg:block`}></i> <i
className={`fa-solid ${icon} absolute top-1/2 left-4 hidden -translate-y-1/2 text-(--color-text-muted) lg:block`}
></i>
<input <input
id={id} id={id}
type={type} type={type}
@@ -174,9 +271,18 @@ export default function ManagerSignupPage() {
)} )}
<div className="space-y-3 pt-2"> <div className="space-y-3 pt-2">
<Button variant="primaryNoBorder" type="submit" style="login" size="lg" disabled={isLoading}> <Button
variant="primaryNoBorder"
type="submit"
style="login"
size="lg"
disabled={isLoading}
>
{isLoading ? ( {isLoading ? (
<><i className="fa-solid fa-spinner fa-spin mr-2"></i>Đang xử ...</> <>
<i className="fa-solid fa-spinner fa-spin mr-2"></i>Đang xử
...
</>
) : ( ) : (
"Đăng ký" "Đăng ký"
)} )}
+3 -2
View File
@@ -91,7 +91,8 @@ export default function RegisterPage() {
ExistedUser: "Phone number already registered", ExistedUser: "Phone number already registered",
InvalidPhoneNumber: "Invalid phone number", InvalidPhoneNumber: "Invalid phone number",
}; };
const msg = phoneErrorMap[errorCode] ?? "An error occurred, please try again"; const msg =
phoneErrorMap[errorCode] ?? "An error occurred, please try again";
setErrors({ phone: msg, otp: "" }); setErrors({ phone: msg, otp: "" });
} }
} catch { } catch {
@@ -364,7 +365,7 @@ export default function RegisterPage() {
type="button" type="button"
onClick={sendOtp} onClick={sendOtp}
disabled={otpSending || isLoading} disabled={otpSending || isLoading}
className="text-sm text-(--color-primary) underline disabled:cursor-not-allowed disabled:opacity-50 disabled:no-underline" className="text-sm text-(--color-primary) underline disabled:cursor-not-allowed disabled:no-underline disabled:opacity-50"
> >
{otpSending ? ( {otpSending ? (
<> <>
+5 -10
View File
@@ -306,7 +306,8 @@ export default function AnalyticsPage() {
{activeChart === "bar" && ( {activeChart === "bar" && (
<> <>
<p className="mb-3 text-xs text-(--color-text-muted)"> <p className="mb-3 text-xs text-(--color-text-muted)">
Comparing revenue of the first and second half of the current period Comparing revenue of the first and second half of the current
period
</p> </p>
<BarChart <BarChart
current={barCurrent} current={barCurrent}
@@ -394,25 +395,19 @@ export default function AnalyticsPage() {
{/* Summary row */} {/* Summary row */}
<div className="bg-background mt-4 flex flex-wrap gap-4 rounded-xl p-4 text-sm"> <div className="bg-background mt-4 flex flex-wrap gap-4 rounded-xl p-4 text-sm">
<div> <div>
<span className="text-(--color-text-muted)"> <span className="text-(--color-text-muted)">Total revenue: </span>
Total revenue:{" "}
</span>
<span className="font-semibold text-(--color-primary)"> <span className="font-semibold text-(--color-primary)">
{formatCurrencyFull(filteredRevenue)} {formatCurrencyFull(filteredRevenue)}
</span> </span>
</div> </div>
<div> <div>
<span className="text-(--color-text-muted)"> <span className="text-(--color-text-muted)">Total profit: </span>
Total profit:{" "}
</span>
<span className="font-semibold text-green-600"> <span className="font-semibold text-green-600">
{formatCurrencyFull(filteredProfit)} {formatCurrencyFull(filteredProfit)}
</span> </span>
</div> </div>
<div> <div>
<span className="text-(--color-text-muted)"> <span className="text-(--color-text-muted)">Total units: </span>
Total units:{" "}
</span>
<span className="text-foreground font-semibold"> <span className="text-foreground font-semibold">
{filteredUnits.toLocaleString()} cups {filteredUnits.toLocaleString()} cups
</span> </span>
+8 -2
View File
@@ -21,7 +21,10 @@ export default function LoginForm() {
return false; return false;
} }
if (!PHONE_REGEX.test(phone)) { if (!PHONE_REGEX.test(phone)) {
setErrors({ phone: "Invalid phone number (e.g. 0987654321)", general: "" }); setErrors({
phone: "Invalid phone number (e.g. 0987654321)",
general: "",
});
return false; return false;
} }
return true; return true;
@@ -50,7 +53,10 @@ export default function LoginForm() {
} else if (res.status === 404) { } else if (res.status === 404) {
setErrors({ phone: "", general: "Phone number not registered" }); setErrors({ phone: "", general: "Phone number not registered" });
} else { } else {
setErrors({ phone: "", general: "An error occurred, please try again" }); setErrors({
phone: "",
general: "An error occurred, please try again",
});
} }
} catch { } catch {
setErrors({ phone: "", general: "Unable to connect, please try again" }); setErrors({ phone: "", general: "Unable to connect, please try again" });
@@ -50,7 +50,9 @@ export default function CategoriesTab() {
<p className="text-foreground truncate font-semibold"> <p className="text-foreground truncate font-semibold">
{cat.name} {cat.name}
</p> </p>
<p className="text-xs text-(--color-text-muted)">{count} items</p> <p className="text-xs text-(--color-text-muted)">
{count} items
</p>
</div> </div>
<div className="flex flex-col gap-1 opacity-0 transition-opacity group-hover:opacity-100"> <div className="flex flex-col gap-1 opacity-0 transition-opacity group-hover:opacity-100">
<button <button
+12 -6
View File
@@ -76,7 +76,10 @@ export default function MenuItemsTab() {
setSubmitting(true); setSubmitting(true);
setSubmitError(null); setSubmitError(null);
try { try {
const added = await addManagerMenuItem(newName.trim(), parseFloat(newPrice)); const added = await addManagerMenuItem(
newName.trim(),
parseFloat(newPrice),
);
if (added) setMenuItems((prev) => [...prev, added]); if (added) setMenuItems((prev) => [...prev, added]);
setNewName(""); setNewName("");
setNewPrice(""); setNewPrice("");
@@ -117,7 +120,9 @@ export default function MenuItemsTab() {
return ( return (
<div className="flex flex-col items-center justify-center py-16 text-(--color-text-muted)"> <div className="flex flex-col items-center justify-center py-16 text-(--color-text-muted)">
<i className="fa-solid fa-store mb-2 block text-3xl opacity-30"></i> <i className="fa-solid fa-store mb-2 block text-3xl opacity-30"></i>
<p className="text-sm">Quán của bạn chưa đưc khởi tạo trong hệ thống.</p> <p className="text-sm">
Quán của bạn chưa đưc khởi tạo trong hệ thống.
</p>
</div> </div>
); );
} }
@@ -127,7 +132,8 @@ export default function MenuItemsTab() {
{/* Toolbar */} {/* Toolbar */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className="text-sm text-(--color-text-muted)"> <p className="text-sm text-(--color-text-muted)">
<strong className="text-foreground">{menuItems.length}</strong> món trong menu <strong className="text-foreground">{menuItems.length}</strong> món
trong menu
</p> </p>
<button <button
onClick={() => setShowForm(true)} onClick={() => setShowForm(true)}
@@ -206,7 +212,7 @@ export default function MenuItemsTab() {
onChange={(e) => setNewName(e.target.value)} onChange={(e) => setNewName(e.target.value)}
placeholder="Nhập tên món..." placeholder="Nhập tên món..."
required required
className="text-foreground w-full rounded-xl border border-(--color-border) bg-white px-3 py-2 text-sm outline-none transition focus:border-(--color-primary) focus:ring-2 focus:ring-(--color-primary)/20" className="text-foreground w-full rounded-xl border border-(--color-border) bg-white px-3 py-2 text-sm transition outline-none focus:border-(--color-primary) focus:ring-2 focus:ring-(--color-primary)/20"
/> />
</div> </div>
@@ -222,7 +228,7 @@ export default function MenuItemsTab() {
required required
min={0} min={0}
step={500} step={500}
className="text-foreground w-full rounded-xl border border-(--color-border) bg-white px-3 py-2 text-sm outline-none transition focus:border-(--color-primary) focus:ring-2 focus:ring-(--color-primary)/20" className="text-foreground w-full rounded-xl border border-(--color-border) bg-white px-3 py-2 text-sm transition outline-none focus:border-(--color-primary) focus:ring-2 focus:ring-(--color-primary)/20"
/> />
</div> </div>
@@ -237,7 +243,7 @@ export default function MenuItemsTab() {
<button <button
type="button" type="button"
onClick={closeForm} onClick={closeForm}
className="flex-1 cursor-pointer rounded-xl border border-(--color-border-light) bg-transparent py-2 text-sm font-medium text-(--color-text-secondary) transition hover:bg-background" className="hover:bg-background flex-1 cursor-pointer rounded-xl border border-(--color-border-light) bg-transparent py-2 text-sm font-medium text-(--color-text-secondary) transition"
> >
Hủy Hủy
</button> </button>
@@ -178,7 +178,9 @@ export default function MobileShiftView({
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="h-2 w-2 rounded-full bg-green-500"></span> <span className="h-2 w-2 rounded-full bg-green-500"></span>
<span className="text-[10px] text-(--color-text-muted)">Registered</span> <span className="text-[10px] text-(--color-text-muted)">
Registered
</span>
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="h-2 w-2 rounded-full bg-purple-400"></span> <span className="h-2 w-2 rounded-full bg-purple-400"></span>
@@ -188,7 +190,9 @@ export default function MobileShiftView({
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<span className="h-2 w-2 rounded-full bg-red-400"></span> <span className="h-2 w-2 rounded-full bg-red-400"></span>
<span className="text-[10px] text-(--color-text-muted)">Absent</span> <span className="text-[10px] text-(--color-text-muted)">
Absent
</span>
</div> </div>
</div> </div>
</div> </div>
@@ -199,7 +203,8 @@ export default function MobileShiftView({
{dayOfWeek}, {selectedDateObj.getDate()}/ {dayOfWeek}, {selectedDateObj.getDate()}/
{selectedDateObj.getMonth() + 1}/{selectedDateObj.getFullYear()} {selectedDateObj.getMonth() + 1}/{selectedDateObj.getFullYear()}
<span className="ml-2 text-xs font-normal text-(--color-text-muted)"> <span className="ml-2 text-xs font-normal text-(--color-text-muted)">
({selectedShifts.length} shift{selectedShifts.length !== 1 ? "s" : ""}) ({selectedShifts.length} shift
{selectedShifts.length !== 1 ? "s" : ""})
</span> </span>
</h3> </h3>
+3 -1
View File
@@ -23,7 +23,9 @@ export default function ShopGrid({
return ( return (
<div className="flex flex-col items-center justify-center gap-4 py-24 text-(--color-text-muted)"> <div className="flex flex-col items-center justify-center gap-4 py-24 text-(--color-text-muted)">
<i className="fa-solid fa-store text-5xl opacity-30"></i> <i className="fa-solid fa-store text-5xl opacity-30"></i>
<p className="text-base font-medium">No shops found matching your search</p> <p className="text-base font-medium">
No shops found matching your search
</p>
</div> </div>
); );
} }
+1 -1
View File
@@ -16,7 +16,7 @@ spec:
spec: spec:
containers: containers:
- name: frontend-container - name: frontend-container
image: git.demonkernel.io.vn/foodsurf/frontend:1.2.3 image: git.demonkernel.io.vn/foodsurf/frontend:1.2.4
ports: ports:
- containerPort: 3000 - containerPort: 3000
resources: resources:
+8 -2
View File
@@ -14,7 +14,10 @@ interface AuthContextType {
user: User | null; user: User | null;
setUser: (user: User | null) => void; setUser: (user: User | null) => void;
isInitialized: boolean; isInitialized: boolean;
login: (username: string, password: string) => Promise<{ ok: boolean; status?: number }>; login: (
username: string,
password: string,
) => Promise<{ ok: boolean; status?: number }>;
logout: () => void; logout: () => void;
} }
@@ -36,7 +39,10 @@ export function AuthProvider({ children }: { children: ReactNode }) {
setIsInitialized(true); setIsInitialized(true);
}, []); }, []);
const login = async (username: string, password: string): Promise<{ ok: boolean; status?: number }> => { const login = async (
username: string,
password: string,
): Promise<{ ok: boolean; status?: number }> => {
const isPhone = /^0\d{9}$/.test(username.trim()); const isPhone = /^0\d{9}$/.test(username.trim());
const role = isPhone ? "customer" : "manager"; const role = isPhone ? "customer" : "manager";
+4 -2
View File
@@ -254,7 +254,8 @@ export const MOCK_COMBOS: Combo[] = [
{ {
id: 2, id: 2,
name: "Group Tea Combo", name: "Group Tea Combo",
description: "2 peach orange lemongrass teas + 2 matcha green teas, perfect for a group.", description:
"2 peach orange lemongrass teas + 2 matcha green teas, perfect for a group.",
price: 130000, price: 130000,
image: "/imgs/products/placeholder.jpg", image: "/imgs/products/placeholder.jpg",
items: [ items: [
@@ -266,7 +267,8 @@ export const MOCK_COMBOS: Combo[] = [
{ {
id: 3, id: 3,
name: "Morning Combo", name: "Morning Combo",
description: "1 milk coffee + 1 caramel flan — start your day on a sweet note.", description:
"1 milk coffee + 1 caramel flan — start your day on a sweet note.",
price: 48000, price: 48000,
image: "/imgs/products/placeholder.jpg", image: "/imgs/products/placeholder.jpg",
items: [ items: [
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "temp", "name": "temp",
"version": "1.2.3", "version": "1.2.4",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "temp", "name": "temp",
"version": "1.2.3", "version": "1.2.4",
"dependencies": { "dependencies": {
"@tailwindcss/postcss": "^4.2.2", "@tailwindcss/postcss": "^4.2.2",
"@types/node": "^20.19.37", "@types/node": "^20.19.37",
+4 -4
View File
@@ -1,6 +1,6 @@
{ {
"name": "temp", "name": "temp",
"version": "1.2.3", "version": "1.2.4",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -11,14 +11,14 @@
"release": "semantic-release" "release": "semantic-release"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/postcss": "^4.2.2", "@tailwindcss/postcss": "^4.2.4",
"@types/node": "^20.19.39", "@types/node": "^20.19.39",
"@types/react": "^19.2.14", "@types/react": "^19.2.14",
"next": "16.1.7", "next": "16.1.7",
"react": "19.2.3", "react": "19.2.3",
"react-dom": "19.2.3", "react-dom": "19.2.3",
"tailwind": "^4.0.0", "tailwind": "^4.0.0",
"tailwindcss": "^4.2.2", "tailwindcss": "^4.2.4",
"typescript": "^5.9.3" "typescript": "^5.9.3"
}, },
"devDependencies": { "devDependencies": {
@@ -32,7 +32,7 @@
"prettier": "^3.8.3", "prettier": "^3.8.3",
"prettier-plugin-embed": "^0.5.1", "prettier-plugin-embed": "^0.5.1",
"prettier-plugin-groovy": "^0.2.1", "prettier-plugin-groovy": "^0.2.1",
"prettier-plugin-tailwindcss": "^0.7.2", "prettier-plugin-tailwindcss": "^0.7.4",
"semantic-release": "^25.0.3" "semantic-release": "^25.0.3"
} }
} }
+248 -248
View File
File diff suppressed because it is too large Load Diff