diff --git a/package-lock.json b/package-lock.json index 7125282..3f87c99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "react-dom": "^18", "react-hook-form": "^7.76.0", "react-konva": "^18.2.16", + "react-multi-date-picker": "^4.5.2", "react-rnd": "^10.5.3", "tailwind-merge": "^3.6.0", "use-image": "^1.1.4", @@ -7285,6 +7286,12 @@ "node": ">=0.10.0" } }, + "node_modules/react-date-object": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/react-date-object/-/react-date-object-2.1.9.tgz", + "integrity": "sha512-BHxD/quWOTo9fLKV/cfL/M31ePoj4a1JaJ/CnOf8Ndg3mrkh4x9wEMMkCfTrzduxDOgU8ZgR8uarhqI5G71sTg==", + "license": "MIT" + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -7312,6 +7319,16 @@ "react-dom": ">= 16.3.0" } }, + "node_modules/react-element-popper": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-element-popper/-/react-element-popper-2.1.7.tgz", + "integrity": "sha512-tuM2OxKlW32h+6uFSK6EENHPeZ2OGgOipHfOAl+VLWEv9/j3QkSGbD+ADX3A9uJlmq24i37n28RjJmAbGTfpEg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-hook-form": { "version": "7.76.0", "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.76.0.tgz", @@ -7365,6 +7382,20 @@ "react-dom": ">=18.0.0" } }, + "node_modules/react-multi-date-picker": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/react-multi-date-picker/-/react-multi-date-picker-4.5.2.tgz", + "integrity": "sha512-FgWjZB3Z6IA6XpcWiLPk85PwcRUhOiYhKK42o5k672gD/n2I6rzPfQ8bUrldOIiF/Z7FfOCdH7a6FeubzqteLg==", + "license": "MIT", + "dependencies": { + "react-date-object": "^2.1.8", + "react-element-popper": "^2.1.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-reconciler": { "version": "0.29.2", "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.2.tgz", diff --git a/package.json b/package.json index d06822e..bcfcde7 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "react-dom": "^18", "react-hook-form": "^7.76.0", "react-konva": "^18.2.16", + "react-multi-date-picker": "^4.5.2", "react-rnd": "^10.5.3", "tailwind-merge": "^3.6.0", "use-image": "^1.1.4", diff --git a/src/components/admin/CrmAdmin.tsx b/src/components/admin/CrmAdmin.tsx index 646d785..2dd9ecf 100644 --- a/src/components/admin/CrmAdmin.tsx +++ b/src/components/admin/CrmAdmin.tsx @@ -2,6 +2,8 @@ import { useCallback, useEffect, useState } from "react"; +import { PersianDateInput } from "@/components/admin/PersianDateInput"; + interface Daily { date: string; signups: number; buyers: number; revenue_minor: number } interface Analytics { total_signups: number; buyers: number; non_buyers: number; @@ -51,8 +53,8 @@ export function CrmAdmin() {

ثبت‌نام‌ها، خریداران، نرخ تبدیل و درآمد در بازهٔ زمانی انتخابی.

-
setStart(e.target.value)} />
-
setEnd(e.target.value)} />
+
+
diff --git a/src/components/admin/PersianDateInput.tsx b/src/components/admin/PersianDateInput.tsx new file mode 100644 index 0000000..fd88755 --- /dev/null +++ b/src/components/admin/PersianDateInput.tsx @@ -0,0 +1,48 @@ +"use client"; + +import DatePicker, { DateObject } from "react-multi-date-picker"; +import persian from "react-date-object/calendars/persian"; +import persian_fa from "react-date-object/locales/persian_fa"; +import gregorian from "react-date-object/calendars/gregorian"; + +/** + * Jalali (Persian) date picker for the admin. Displays a Persian calendar but keeps + * the value as a Gregorian ISO string ("YYYY-MM-DD"), so backends/DTOs stay unchanged. + */ +export function PersianDateInput({ + value, + onChange, + className, + placeholder, +}: { + value: string; // Gregorian ISO "YYYY-MM-DD" or "" + onChange: (iso: string) => void; + className?: string; + placeholder?: string; +}) { + const dateObj = value + ? new DateObject({ date: value, format: "YYYY-MM-DD", calendar: gregorian }).convert( + persian, + persian_fa + ) + : ""; + + return ( + { + if (!d || Array.isArray(d)) { + onChange(""); + return; + } + onChange((d as DateObject).convert(gregorian).format("YYYY-MM-DD")); + }} + inputClass={className} + placeholder={placeholder ?? "انتخاب تاریخ"} + editable={false} + /> + ); +} diff --git a/src/components/admin/UserProfileEdit.tsx b/src/components/admin/UserProfileEdit.tsx index 6404261..c41c09e 100644 --- a/src/components/admin/UserProfileEdit.tsx +++ b/src/components/admin/UserProfileEdit.tsx @@ -2,6 +2,8 @@ import { useState } from "react"; +import { PersianDateInput } from "@/components/admin/PersianDateInput"; + const inp = "w-full rounded-lg border border-[#262b40] bg-[#0c0e1a] px-3 py-2 text-sm text-gray-100 outline-none focus:border-indigo-500"; const lbl = "mb-1 block text-xs font-medium text-gray-400"; @@ -92,7 +94,7 @@ export function UserProfileEdit({ row }: { row: Record; reload?
set("website_name", e.target.value)} />
set("country_code", e.target.value)} />
set("national_code", e.target.value)} />
-
set("birth_date", e.target.value)} />
+
set("birth_date", v)} />