fix(admin-schedule): 공용폼 토글 정렬·멤버 필터·날짜미정 연월 드롭다운
- 날짜미정 토글을 검증된 패턴(relative w-11 + absolute translate-x-5)으로 교체해 상하/좌우 여백 균일화 - 멤버 목록을 현재 활동 멤버만(is_former 제외)으로 필터 - 날짜미정일 때 달력 대신 연/월 드롭다운으로 입력(YYYY-MM-01 저장) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
72c65021fb
commit
71b678a90b
1 changed files with 64 additions and 24 deletions
|
|
@ -46,12 +46,14 @@ function ScheduleForm() {
|
|||
queryFn: categoriesApi.getCategories,
|
||||
staleTime: 10 * 60 * 1000,
|
||||
});
|
||||
const { data: members = [] } = useQuery({
|
||||
const { data: allMembers = [] } = useQuery({
|
||||
queryKey: ['members'],
|
||||
queryFn: getMembers,
|
||||
staleTime: 10 * 60 * 1000,
|
||||
});
|
||||
|
||||
// 현재 활동 멤버만 (탈퇴 멤버 제외)
|
||||
const members = useMemo(() => allMembers.filter((m) => !m.is_former), [allMembers]);
|
||||
const categories = useMemo(
|
||||
() => allCategories.filter((c) => SHARED_CATEGORIES.includes(c.name)),
|
||||
[allCategories]
|
||||
|
|
@ -101,7 +103,23 @@ function ScheduleForm() {
|
|||
}));
|
||||
|
||||
const setPrecision = (month) =>
|
||||
setFormData((p) => ({ ...p, datePrecision: month ? 'month' : 'day', time: month ? '' : p.time }));
|
||||
setFormData((p) => {
|
||||
if (!month) return { ...p, datePrecision: 'day' };
|
||||
// 월 모드: 날짜가 비었으면 이번 달 1일로 기본값
|
||||
const hasMonthDate = /^\d{4}-\d{2}-01$/.test(p.date);
|
||||
const now = new Date();
|
||||
const date = hasMonthDate
|
||||
? p.date
|
||||
: `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-01`;
|
||||
return { ...p, datePrecision: 'month', time: '', date };
|
||||
});
|
||||
|
||||
// 연/월 드롭다운용
|
||||
const yearNow = new Date().getFullYear();
|
||||
const YEAR_OPTIONS = [yearNow - 1, yearNow, yearNow + 1, yearNow + 2];
|
||||
const [selYear, selMonth] = (formData.date || '').split('-');
|
||||
const setMonthDate = (year, monthNum) =>
|
||||
setFormData((p) => ({ ...p, date: `${year}-${String(monthNum).padStart(2, '0')}-01` }));
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
|
|
@ -240,13 +258,13 @@ function ScheduleForm() {
|
|||
<button
|
||||
type="button"
|
||||
onClick={() => setPrecision(!isMonthPrecision)}
|
||||
className={`relative w-12 h-6 rounded-full transition-colors ${
|
||||
className={`relative flex-shrink-0 w-11 h-6 rounded-full transition-colors ${
|
||||
isMonthPrecision ? 'bg-primary' : 'bg-gray-300'
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
className={`absolute top-0.5 w-5 h-5 bg-white rounded-full shadow transition-all ${
|
||||
isMonthPrecision ? 'left-6' : 'left-0.5'
|
||||
className={`absolute top-0.5 left-0.5 w-5 h-5 bg-white rounded-full shadow transition-transform ${
|
||||
isMonthPrecision ? 'translate-x-5' : ''
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
|
|
@ -255,27 +273,49 @@ function ScheduleForm() {
|
|||
|
||||
{/* 날짜 + 시간 */}
|
||||
<div className="grid grid-cols-2 gap-6">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">
|
||||
{isMonthPrecision ? '월 *' : '날짜 *'}
|
||||
</label>
|
||||
<DatePicker
|
||||
value={formData.date}
|
||||
onChange={(date) => setFormData({ ...formData, date })}
|
||||
minYear={2017}
|
||||
/>
|
||||
{isMonthPrecision && (
|
||||
<p className="text-xs text-gray-400 mt-1">선택한 날짜의 "월"만 사용됩니다 (일자는 무시)</p>
|
||||
)}
|
||||
</div>
|
||||
{!isMonthPrecision && (
|
||||
{isMonthPrecision ? (
|
||||
// 날짜 미정: 연 + 월 드롭다운
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">시간</label>
|
||||
<TimePicker
|
||||
value={formData.time}
|
||||
onChange={(time) => setFormData({ ...formData, time })}
|
||||
/>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">연 / 월 *</label>
|
||||
<div className="flex gap-3">
|
||||
<select
|
||||
value={selYear || yearNow}
|
||||
onChange={(e) => setMonthDate(e.target.value, parseInt(selMonth, 10))}
|
||||
className="flex-1 px-4 py-3 border border-gray-200 rounded-xl bg-white focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
|
||||
>
|
||||
{YEAR_OPTIONS.map((y) => (
|
||||
<option key={y} value={y}>{y}년</option>
|
||||
))}
|
||||
</select>
|
||||
<select
|
||||
value={parseInt(selMonth, 10) || ''}
|
||||
onChange={(e) => setMonthDate(selYear || yearNow, e.target.value)}
|
||||
className="flex-1 px-4 py-3 border border-gray-200 rounded-xl bg-white focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
|
||||
>
|
||||
{Array.from({ length: 12 }, (_, i) => i + 1).map((m) => (
|
||||
<option key={m} value={m}>{m}월</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">날짜 *</label>
|
||||
<DatePicker
|
||||
value={formData.date}
|
||||
onChange={(date) => setFormData({ ...formData, date })}
|
||||
minYear={2017}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">시간</label>
|
||||
<TimePicker
|
||||
value={formData.time}
|
||||
onChange={(time) => setFormData({ ...formData, time })}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue