期日クイックピッカー
:LiTarget: 用途
「今日」「明日」「来週」などのクイック選択ボタン付き期日UI。
:LiSparkle: 特徴
- クイック選択
- カスタム日付
- 相対日付表示
:LiCode: 実コード(SCALE Base より自動抽出)
:LiInfo:
components/tasks/DueDateQuickPicker.tsxの中身そのもの。コピペ即可。
'use client';
// 期日のクイック選択UI
// プリセット: 今日 / 明日 / 2日後 / 3日後 / 1週間後 / カスタム
// 選択するとYYYY-MM-DD文字列をonChangeに返す
import { useMemo } from 'react';
export interface DueDateQuickPickerProps {
value: string; // YYYY-MM-DD
onChange: (v: string) => void;
compact?: boolean; // 小さいUI
className?: string;
}
function addDays(base: Date, d: number): string {
const x = new Date(base);
x.setDate(x.getDate() + d);
return x.toISOString().slice(0, 10);
}
export function DueDateQuickPicker({ value, onChange, compact = false, className = '' }: DueDateQuickPickerProps) {
const today = useMemo(() => new Date(), []);
const presets = useMemo(() => [
{ label: '今日', value: addDays(today, 0) },
{ label: '明日', value: addDays(today, 1) },
{ label: '2日後', value: addDays(today, 2) },
{ label: '3日後', value: addDays(today, 3) },
{ label: '1週間後', value: addDays(today, 7) },
], [today]);
const selectedPreset = presets.find(p => p.value === value);
const isCustom = value && !selectedPreset;
const baseCls = compact
? 'px-2 py-0.5 text-[11px] rounded-md'
: 'px-2.5 py-1 text-xs rounded-md';
return (
<div className={`flex flex-wrap items-center gap-1 ${className}`}>
{presets.map(p => {
const active = value === p.value;
return (
<button
key={p.label}
type="button"
onClick={() => onChange(p.value)}
className={`${baseCls} border transition-colors ${
active
? 'bg-blue-500 border-blue-500 text-white'
: 'bg-bg3 border-border text-text2 hover:text-text hover:border-blue-500/50'
}`}
>
{p.label}
</button>
);
})}
{/* カスタム日付 */}
<input
type="date"
value={value || ''}
onChange={(e) => onChange(e.target.value)}
className={`${baseCls} border bg-bg3 text-text placeholder:text-text3 focus:outline-none focus:border-blue-500 ${
isCustom ? 'border-blue-500' : 'border-border'
}`}
/>
{isCustom && value && (
<span className="text-[10px] text-blue-300 ml-1">カスタム</span>
)}
{value && (
<button
type="button"
onClick={() => onChange('')}
className={`${baseCls} border border-border bg-bg3 text-text3 hover:text-red-400`}
title="期日をクリア"
>
✕
</button>
)}
</div>
);
}
:LiFolder: ソースファイルのパス
/Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base/components/tasks/DueDateQuickPicker.tsx
:LiHandPointer: 使い方
対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。
:LiAlertCircle: 注意事項
- 依存パッケージを忘れず追加