feat: enhance date parsing to support month-only formats and normalize URLs to prevent duplicates
This commit is contained in:
31
src/App.jsx
31
src/App.jsx
@@ -31,10 +31,39 @@ const DATE_RANGE_OPTIONS = [
|
||||
|
||||
const parseDate = (value) => {
|
||||
if (!value) return null;
|
||||
const date = new Date(value);
|
||||
|
||||
const toDate = (input) => {
|
||||
const date = new Date(input);
|
||||
return Number.isNaN(date.getTime()) ? null : date;
|
||||
};
|
||||
|
||||
let date = value instanceof Date ? value : null;
|
||||
|
||||
if (!date && (typeof value === "number" || typeof value === "string")) {
|
||||
date = toDate(value);
|
||||
|
||||
if (!date && typeof value === "string") {
|
||||
const trimmed = value.trim();
|
||||
const dayMatch = trimmed.match(/^([0-9]{1,2})[\/\-]([0-9]{1,2})[\/\-]([0-9]{2,4})$/);
|
||||
|
||||
if (dayMatch) {
|
||||
const [, day, month, year] = dayMatch;
|
||||
const normalizedYear = year.length === 2 ? `20${year}` : year;
|
||||
date = toDate(`${normalizedYear.padStart(4, "0")}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`);
|
||||
} else {
|
||||
const monthMatch = trimmed.match(/^([0-9]{1,2})[\/\-]([0-9]{2,4})$/);
|
||||
if (monthMatch) {
|
||||
const [, month, year] = monthMatch;
|
||||
const normalizedYear = year.length === 2 ? `20${year}` : year;
|
||||
date = toDate(`${normalizedYear.padStart(4, "0")}-${month.padStart(2, "0")}-01`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return date;
|
||||
};
|
||||
|
||||
const matchesDateRange = (annonce, range) => {
|
||||
if (!range) return true;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { X, Plus, Loader2, Link } from "lucide-react";
|
||||
|
||||
export default function AddModal({ open, onClose, onSubmit, existingUrls }) {
|
||||
@@ -6,11 +6,29 @@ export default function AddModal({ open, onClose, onSubmit, existingUrls }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [urlError, setUrlError] = useState("");
|
||||
|
||||
const normalizeUrl = (raw) => {
|
||||
if (!raw) return "";
|
||||
try {
|
||||
const parsed = new URL(raw.trim());
|
||||
parsed.hash = "";
|
||||
parsed.search = "";
|
||||
return `${parsed.origin}${parsed.pathname}`;
|
||||
} catch (err) {
|
||||
return raw.trim().split(/[?#]/)[0];
|
||||
}
|
||||
};
|
||||
|
||||
const normalizedExisting = useMemo(
|
||||
() => existingUrls.map((item) => normalizeUrl(item)),
|
||||
[existingUrls]
|
||||
);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
const handleUrlChange = (val) => {
|
||||
setUrl(val);
|
||||
if (existingUrls.includes(val.trim())) {
|
||||
const normalized = normalizeUrl(val);
|
||||
if (normalized && normalizedExisting.includes(normalized)) {
|
||||
setUrlError("Cette URL existe deja dans la liste !");
|
||||
} else {
|
||||
setUrlError("");
|
||||
|
||||
@@ -65,12 +65,20 @@ const formatFrDate = (value) => {
|
||||
date = toDate(value);
|
||||
|
||||
if (!date && typeof value === "string") {
|
||||
const match = value.trim().match(/^([0-9]{1,2})[\/\-]([0-9]{1,2})[\/\-]([0-9]{2,4})$/);
|
||||
const trimmed = value.trim();
|
||||
const dayMatch = trimmed.match(/^([0-9]{1,2})[\/\-]([0-9]{1,2})[\/\-]([0-9]{2,4})$/);
|
||||
|
||||
if (match) {
|
||||
const [, day, month, year] = match;
|
||||
if (dayMatch) {
|
||||
const [, day, month, year] = dayMatch;
|
||||
const normalizedYear = year.length === 2 ? `20${year}` : year;
|
||||
date = toDate(`${normalizedYear.padStart(4, "0")}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`);
|
||||
} else {
|
||||
const monthMatch = trimmed.match(/^([0-9]{1,2})[\/\-]([0-9]{2,4})$/);
|
||||
if (monthMatch) {
|
||||
const [, month, year] = monthMatch;
|
||||
const normalizedYear = year.length === 2 ? `20${year}` : year;
|
||||
date = toDate(`${normalizedYear.padStart(4, "0")}-${month.padStart(2, "0")}-01`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user