日付範囲ピッカー
:LiTarget: 用途
開始日 + 終了日を選ぶピッカー。プリセット(今週/今月/先月/先週)対応。
:LiSparkle: 特徴
- 開始/終了2フィールド
- プリセット
- バリデーション
- 相対日付
:LiCode: コード(コピペ用)
'use client';
import { useState } from 'react';
const PRESETS = [
{ label: '今日', from: () => { const d = new Date(); return d; }, to: () => new Date() },
{ label: '今週', from: () => { const d = new Date(); d.setDate(d.getDate() - d.getDay()); return d; }, to: () => new Date() },
{ label: '今月', from: () => { const d = new Date(); return new Date(d.getFullYear(), d.getMonth(), 1); }, to: () => new Date() },
{ label: '先月', from: () => { const d = new Date(); return new Date(d.getFullYear(), d.getMonth() - 1, 1); }, to: () => { const d = new Date(); return new Date(d.getFullYear(), d.getMonth(), 0); } },
{ label: '今四半期', from: () => { const d = new Date(); const q = Math.floor(d.getMonth() / 3) * 3; return new Date(d.getFullYear(), q, 1); }, to: () => new Date() },
];
export function DateRangePicker({ from, to, onChange }: {
from: string; to: string; onChange: (from: string, to: string) => void;
}) {
const setPreset = (p: typeof PRESETS[0]) => {
const fmt = (d: Date) => d.toISOString().slice(0, 10);
onChange(fmt(p.from()), fmt(p.to()));
};
return (
<div style={{ display: 'flex', gap: '.5rem', alignItems: 'center', flexWrap: 'wrap' }}>
<input type="date" value={from} onChange={e => onChange(e.target.value, to)} />
<span style={{ color: 'rgba(255,255,255,.55)' }}>〜</span>
<input type="date" value={to} onChange={e => onChange(from, e.target.value)} />
<div style={{ display: 'flex', gap: '.25rem', marginLeft: '.5rem' }}>
{PRESETS.map(p => (
<button key={p.label} onClick={() => setPreset(p)} style={{
fontSize: '.7rem', padding: '.25rem .65rem', background: 'transparent',
border: '1px solid rgba(255,255,255,.07)', color: 'rgba(255,255,255,.55)',
cursor: 'pointer', borderRadius: 3,
}}>{p.label}</button>
))}
</div>
</div>
);
}
:LiHandPointer: 使い方
対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。
:LiAlertCircle: 注意事項
- 依存パッケージを忘れず追加