پرتوپرتو

انتخابگر تاریخ (Date Picker)

کامپوننت انتخاب بازه تاریخ با پشتیبانی از تقویم شمسی و میلادی

معرفی

کامپوننت Date Picker برای انتخاب بازه تاریخ (از تاریخ شروع تا تاریخ پایان) استفاده می‌شود. این کامپوننت از تقویم شمسی (جلالی) و میلادی پشتیبانی می‌کند و به طور کامل RTL است.

نصب

نصب وابستگی‌ها

pnpm add react-day-picker date-fns

کپی کردن کامپوننت‌ها

از shadcn CLI برای نصب کامپوننت‌های لازم استفاده کنید:

pnpm dlx shadcn@latest add calendar
pnpm dlx shadcn@latest add popover

یا به صورت دستی کامپوننت‌ها را کپی کنید.

ویرایش Calendar برای پشتیبانی تقویم شمسی

در فایل components/ui/calendar.tsx:

import { DayPicker } from "react-day-picker"
import { DayPicker as PersianDayPicker } from "react-day-picker/persian"

استفاده پایه

import { DatePicker } from '@parto-system-design/ui';
import { useState } from 'react';
import { DateRange } from 'react-day-picker';

export default function MyComponent() {
  const [dateRange, setDateRange] = useState<DateRange | undefined>();

  return (
    <DatePicker
      value={dateRange}
      onChange={setDateRange}
      placeholder="انتخاب بازه تاریخ"
    />
  );
}

تقویم شمسی

برای استفاده از تقویم شمسی، prop usePersianCalendar را true قرار دهید:

<DatePicker
  value={dateRange}
  onChange={setDateRange}
  placeholder="انتخاب بازه تاریخ"
  usePersianCalendar={true}
/>

انتخاب یک تاریخ (بدون بازه)

برای انتخاب فقط یک تاریخ (نه بازه تاریخی)، باید mode را 'single' قرار دهید:

const [date, setDate] = useState<DateRange | undefined>();

<DatePicker
  value={date}
  onChange={setDate}
  placeholder="انتخاب تاریخ"
  usePersianCalendar={true}
  mode="single"
  numberOfMonths={1}
/>

نکته: برای دریافت تاریخ انتخاب شده از date?.from استفاده کنید.

// دریافت تاریخ انتخاب شده
const selectedDate = date?.from;
console.log(selectedDate); // Date object یا undefined

تعداد ماه‌ها

می‌توانید تعداد ماه‌های نمایش داده شده را تغییر دهید:

<DatePicker
  value={dateRange}
  onChange={setDateRange}
  numberOfMonths={1}
/>

بازه‌های پیش‌فرض (Presets)

با فعال کردن showPresets، دکمه‌های بازه‌های پیش‌فرض نمایش داده می‌شود:

تقویم شمسی با Presets

<DatePicker
  value={dateRange}
  onChange={setDateRange}
  showPresets={true}
  usePersianCalendar={true}
/>

تقویم میلادی با Presets

<DatePicker
  value={dateRange}
  onChange={setDateRange}
  showPresets={true}
  usePersianCalendar={false}
/>

بازه‌های پیش‌فرض شامل:

  • امروز / Today
  • هفته اخیر / Last week
  • ماه اخیر / Last month
  • دو هفته اخیر / Last 2 weeks
  • شش ماه اخیر / Last 6 months
  • سال گذشته / Last year

غیرفعال کردن

<DatePicker
  value={dateRange}
  onChange={setDateRange}
  disabled={true}
/>

Props

Prop

Type

نکات مهم

نوع DateRange

نوع DateRange از کتابخانه react-day-picker می‌آید:

import { DateRange } from 'react-day-picker';

type DateRange = {
  from: Date | undefined;
  to: Date | undefined;
}

تقویم شمسی

هنگام استفاده از usePersianCalendar={true}:

  • ✅ نمایش ماه‌های شمسی (فروردین، اردیبهشت، ...)
  • ✅ نمایش اعداد فارسی (۱، ۲، ۳، ...)
  • ✅ نمایش روزهای هفته به فارسی (ش، ی، د، ...)
  • ✅ سال شمسی در عنوان
  • ⚠️ مقادیر Date همچنان میلادی هستند (فقط نمایش شمسی است)

انتخاب یک تاریخ

برای انتخاب یک تاریخ به جای بازه تاریخی:

  1. مقدار mode را 'single' قرار دهید (ضروری)
  2. توصیه می‌شود numberOfMonths را 1 قرار دهید
  3. از value?.from برای دسترسی به تاریخ انتخاب شده استفاده کنید
  4. در حالت single، دکمه‌های preset نمایش داده نمی‌شوند

مثال‌های کاربردی

فیلتر گزارش

const [reportRange, setReportRange] = useState<DateRange>();

<DatePicker
  value={reportRange}
  onChange={setReportRange}
  placeholder="بازه گزارش"
  usePersianCalendar={true}
/>

رزرو هتل

const [checkInOut, setCheckInOut] = useState<DateRange>();

<DatePicker
  value={checkInOut}
  onChange={setCheckInOut}
  placeholder="تاریخ ورود و خروج"
  numberOfMonths={2}
/>

با فرم

import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import * as z from "zod"

const formSchema = z.object({
  dateRange: z.object({
    from: z.date(),
    to: z.date(),
  }).optional(),
})

function MyForm() {
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
  })

  return (
    <Form {...form}>
      <FormField
        control={form.control}
        name="dateRange"
        render={({ field }) => (
          <FormItem>
            <FormLabel>بازه تاریخ</FormLabel>
            <FormControl>
              <DatePicker
                value={field.value}
                onChange={field.onChange}
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      />
    </Form>
  )
}

رابطه با کامپوننت‌های دیگر

  • Calendar: کامپوننت داخلی که برای نمایش تقویم استفاده می‌شود
  • Popover: برای نمایش تقویم در یک پاپاور
  • Button: برای دکمه باز کردن تقویم
  • DateRangePicker: کامپوننت مشابه با امکانات بیشتر