2026-04-14 12:13:34 +09:00
|
|
|
import { useState } from 'react'
|
2026-04-14 09:54:06 +09:00
|
|
|
import Select from '../../../components/Select'
|
|
|
|
|
import Tooltip from '../../../components/Tooltip'
|
2026-04-14 18:58:42 +09:00
|
|
|
import WeeklyScheduler from './WeeklyScheduler'
|
2026-04-14 09:54:06 +09:00
|
|
|
import { WEEKLY_BOSSES, MONTHLY_BOSSES, LIBERATION_BOSS_IMAGE_BASE, calcPoints } from '../data'
|
|
|
|
|
|
|
|
|
|
const PARTY_OPTIONS = [1, 2, 3, 4, 5, 6].map((n) => ({ value: n, label: `${n}인` }))
|
|
|
|
|
const NONE_DIFFICULTY = { key: 'none', label: '격파 불가', points: 0 }
|
|
|
|
|
|
|
|
|
|
function diffLabel(d, party) {
|
|
|
|
|
if (d.key === 'none') return <span className="text-gray-500">격파 불가</span>
|
|
|
|
|
const earned = calcPoints(d.points, party)
|
|
|
|
|
return (
|
|
|
|
|
<span>
|
|
|
|
|
{d.label} <span className="text-emerald-400">+{earned}</span>
|
|
|
|
|
</span>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-14 18:41:53 +09:00
|
|
|
export function BossRow({ boss, sel, onChange, monthly = false, showDone = true }) {
|
2026-04-14 09:54:06 +09:00
|
|
|
const disabled = sel.difficulty === 'none'
|
|
|
|
|
const difficultyOptions = [NONE_DIFFICULTY, ...boss.difficulties]
|
|
|
|
|
.map((d) => ({ value: d.key, label: diffLabel(d, sel.party) }))
|
|
|
|
|
|
|
|
|
|
return (
|
2026-04-14 14:22:20 +09:00
|
|
|
<div className="flex items-center gap-3 rounded-lg px-3 h-16 transition">
|
2026-04-14 09:54:06 +09:00
|
|
|
<Tooltip text={boss.name}>
|
2026-04-14 14:22:20 +09:00
|
|
|
<img src={`${LIBERATION_BOSS_IMAGE_BASE}/${boss.image}`} alt="" className="w-10 h-10 rounded-md object-cover shrink-0" />
|
2026-04-14 09:54:06 +09:00
|
|
|
</Tooltip>
|
2026-04-14 14:22:20 +09:00
|
|
|
<span className="text-base font-semibold flex-1 truncate">
|
2026-04-14 09:54:06 +09:00
|
|
|
{boss.name}
|
2026-04-14 14:22:20 +09:00
|
|
|
{monthly && <span className="ml-1.5 text-[11px] text-amber-400/80 font-medium">월간</span>}
|
2026-04-14 09:54:06 +09:00
|
|
|
</span>
|
|
|
|
|
|
|
|
|
|
<div className="w-36">
|
|
|
|
|
<Select
|
|
|
|
|
value={sel.difficulty}
|
|
|
|
|
onChange={(v) => {
|
|
|
|
|
if (v === 'none') onChange({ difficulty: 'none', done: false })
|
|
|
|
|
else onChange({ difficulty: v })
|
|
|
|
|
}}
|
|
|
|
|
options={difficultyOptions}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="w-20">
|
|
|
|
|
<Select
|
|
|
|
|
value={sel.party}
|
|
|
|
|
onChange={(v) => onChange({ party: v })}
|
|
|
|
|
options={PARTY_OPTIONS}
|
|
|
|
|
disabled={disabled}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2026-04-14 18:41:53 +09:00
|
|
|
{showDone && (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
disabled={disabled}
|
|
|
|
|
onClick={() => onChange({ done: !sel.done })}
|
|
|
|
|
className={`shrink-0 w-20 rounded-md h-8 text-xs font-semibold transition border ${
|
|
|
|
|
disabled
|
|
|
|
|
? 'border-white/5 text-gray-700 cursor-not-allowed'
|
|
|
|
|
: sel.done
|
|
|
|
|
? 'bg-emerald-500/20 border-emerald-500/50 text-emerald-300'
|
|
|
|
|
: 'border-white/10 text-gray-500 hover:border-white/20 hover:text-gray-300'
|
|
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
{sel.done ? '완료' : '미완료'}
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
2026-04-14 09:54:06 +09:00
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-14 18:58:42 +09:00
|
|
|
export default function WeeklyDefault({ weekly, onChange, totalWeekly, totalMonthly, mode = 'simple', startDate, weeks, onChangeWeeks }) {
|
2026-04-14 09:54:06 +09:00
|
|
|
const updateBoss = (key, patch) => {
|
|
|
|
|
onChange({ ...weekly, bosses: { ...weekly.bosses, [key]: { ...weekly.bosses[key], ...patch } } })
|
|
|
|
|
}
|
|
|
|
|
const updateBlackMage = (patch) => {
|
|
|
|
|
onChange({ ...weekly, blackMage: { ...weekly.blackMage, ...patch } })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2026-04-14 14:22:20 +09:00
|
|
|
<div className="max-w-3xl mx-auto rounded-2xl border border-white/10 bg-gray-900/60 p-6 space-y-4">
|
2026-04-14 12:13:34 +09:00
|
|
|
<div className="flex items-center justify-between">
|
2026-04-14 09:54:06 +09:00
|
|
|
<div className="text-lg font-semibold text-emerald-300">주간 보스 설정</div>
|
2026-04-14 18:41:53 +09:00
|
|
|
<div className="flex items-baseline text-sm text-gray-400 gap-3">
|
|
|
|
|
<span>
|
|
|
|
|
주간 획득 <span className="text-emerald-300 font-semibold tabular-nums">+{totalWeekly}</span>
|
|
|
|
|
</span>
|
|
|
|
|
<span>
|
|
|
|
|
월간 획득 <span className="text-amber-300 font-semibold tabular-nums">+{totalMonthly}</span>
|
|
|
|
|
</span>
|
2026-04-14 09:54:06 +09:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-04-14 12:13:34 +09:00
|
|
|
{mode === 'simple' ? (
|
2026-04-14 18:41:53 +09:00
|
|
|
<div className="divide-y divide-white/5">
|
|
|
|
|
{WEEKLY_BOSSES.map((boss) => (
|
|
|
|
|
<BossRow
|
|
|
|
|
key={boss.key}
|
|
|
|
|
boss={boss}
|
|
|
|
|
sel={weekly.bosses[boss.key]}
|
|
|
|
|
onChange={(patch) => updateBoss(boss.key, patch)}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
{MONTHLY_BOSSES.map((boss) => (
|
|
|
|
|
<BossRow
|
|
|
|
|
key={boss.key}
|
|
|
|
|
boss={boss}
|
|
|
|
|
sel={weekly.blackMage}
|
|
|
|
|
onChange={updateBlackMage}
|
|
|
|
|
monthly
|
|
|
|
|
/>
|
|
|
|
|
))}
|
2026-04-14 12:13:34 +09:00
|
|
|
</div>
|
2026-04-14 18:41:53 +09:00
|
|
|
) : (
|
2026-04-14 18:58:42 +09:00
|
|
|
<WeeklyScheduler
|
|
|
|
|
startDate={startDate}
|
|
|
|
|
weeks={weeks}
|
|
|
|
|
onChangeWeeks={onChangeWeeks}
|
|
|
|
|
/>
|
2026-04-14 12:13:34 +09:00
|
|
|
)}
|
2026-04-14 09:54:06 +09:00
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|