diff --git a/resources/js/Components/UtilityFee/UtilityFeeDialog.tsx b/resources/js/Components/UtilityFee/UtilityFeeDialog.tsx
index 90de36f..d888899 100644
--- a/resources/js/Components/UtilityFee/UtilityFeeDialog.tsx
+++ b/resources/js/Components/UtilityFee/UtilityFeeDialog.tsx
@@ -15,6 +15,7 @@ import { SearchableSelect } from "@/Components/ui/searchable-select";
import { useForm } from "@inertiajs/react";
import { toast } from "sonner";
import { Calendar } from "lucide-react";
+import { getCurrentDate } from "@/utils/format";
export interface UtilityFee {
id: number;
@@ -51,7 +52,7 @@ export default function UtilityFeeDialog({
availableCategories,
}: UtilityFeeDialogProps) {
const { data, setData, post, put, processing, errors, reset, clearErrors } = useForm({
- transaction_date: new Date().toISOString().split("T")[0],
+ transaction_date: getCurrentDate(),
category: "",
amount: "",
invoice_number: "",
@@ -74,7 +75,7 @@ export default function UtilityFeeDialog({
});
} else {
reset();
- setData("transaction_date", new Date().toISOString().split("T")[0]);
+ setData("transaction_date", getCurrentDate());
}
}
}, [open, fee]);
@@ -83,6 +84,12 @@ export default function UtilityFeeDialog({
e.preventDefault();
if (fee) {
+ // Validate invoice number format if present
+ if (data.invoice_number && !/^[A-Z]{2}-\d{8}$/.test(data.invoice_number)) {
+ toast.error("發票號碼格式錯誤,應為:AB-12345678");
+ return;
+ }
+
put(route("utility-fees.update", fee.id), {
onSuccess: () => {
toast.success("紀錄已更新");
@@ -94,6 +101,12 @@ export default function UtilityFeeDialog({
}
});
} else {
+ // Validate invoice number format if present
+ if (data.invoice_number && !/^[A-Z]{2}-\d{8}$/.test(data.invoice_number)) {
+ toast.error("發票號碼格式錯誤,應為:AB-12345678");
+ return;
+ }
+
post(route("utility-fees.store"), {
onSuccess: () => {
toast.success("公共事業費已記錄");
@@ -124,13 +137,13 @@ export default function UtilityFeeDialog({
費用日期 *
-
+
setData("transaction_date", e.target.value)}
- className={`pl-9 ${errors.transaction_date ? "border-red-500" : ""}`}
+ className={`pl-9 block w-full ${errors.transaction_date ? "border-red-500" : ""}`}
required
/>
@@ -176,26 +189,10 @@ export default function UtilityFeeDialog({
{
- let value = e.target.value.toUpperCase();
- // Remove non-alphanumeric chars
- const raw = value.replace(/[^A-Z0-9]/g, '');
-
- // Auto-insert hyphen after 2 chars if we have length > 2
- if (raw.length > 2) {
- value = `${raw.slice(0, 2)}-${raw.slice(2)}`;
- } else {
- value = raw;
- }
-
- // Limit max length (2 letters + 8 digits + 1 hyphen = 11 chars)
- if (value.length > 11) value = value.slice(0, 11);
-
- setData("invoice_number", value);
- }}
+ onChange={(e) => setData("invoice_number", e.target.value)}
placeholder="例:AB-12345678"
/>
- 格式:AB-12345678 (系統自動格式化)
+ 格式範例:AB-12345678
{errors.invoice_number && {errors.invoice_number}
}
diff --git a/resources/js/Pages/UtilityFee/Index.tsx b/resources/js/Pages/UtilityFee/Index.tsx
index 5c874e8..3439f12 100644
--- a/resources/js/Pages/UtilityFee/Index.tsx
+++ b/resources/js/Pages/UtilityFee/Index.tsx
@@ -232,7 +232,7 @@ export default function UtilityFeeIndex({ fees, availableCategories, filters }:
{/* Date Range Start */}
-
+
-
+
{
*/
export const formatDate = (date: string): string => {
if (!date) return "-";
- return new Date(date).toLocaleDateString("zh-TW");
+ const datePart = date.split("T")[0].split(" ")[0];
+ const parts = datePart.split("-").map(Number);
+ if (parts.length < 3 || parts.some(isNaN)) return date;
+
+ const [y, m, d] = parts;
+ const dt = new Date(y, m - 1, d, 12, 0, 0);
+ const year = dt.getFullYear();
+ const month = String(dt.getMonth() + 1).padStart(2, '0');
+ const day = String(dt.getDate()).padStart(2, '0');
+
+ return `${year}/${month}/${day}`;
};
/**
@@ -29,12 +39,19 @@ export const formatDate = (date: string): string => {
*/
export const formatDateWithDayOfWeek = (date: string): string => {
if (!date) return "-";
- return new Date(date).toLocaleDateString("zh-TW", {
- year: "numeric",
- month: "2-digit",
- day: "2-digit",
- weekday: "short",
- });
+ const datePart = date.split("T")[0].split(" ")[0];
+ const parts = datePart.split("-").map(Number);
+ if (parts.length < 3 || parts.some(isNaN)) return date;
+
+ const [y, m, d] = parts;
+ const dt = new Date(y, m - 1, d, 12, 0, 0);
+
+ const year = dt.getFullYear();
+ const month = String(dt.getMonth() + 1).padStart(2, '0');
+ const day = String(dt.getDate()).padStart(2, '0');
+ const weekDay = dt.toLocaleDateString("zh-TW", { weekday: "short" });
+
+ return `${year}/${month}/${day} (${weekDay})`;
};
/**
@@ -54,7 +71,11 @@ export const formatInvoiceNumber = (invoice: string | null | undefined): string
* 獲取當前日期(YYYY-MM-DD 格式)
*/
export const getCurrentDate = (): string => {
- return new Date().toISOString().split("T")[0];
+ const now = new Date();
+ const year = now.getFullYear();
+ const month = String(now.getMonth() + 1).padStart(2, "0");
+ const day = String(now.getDate()).padStart(2, "0");
+ return `${year}-${month}-${day}`;
};
/**