first init
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Settings2, X, AlertTriangle, Clock } from 'lucide-react';
|
||||
import { Column } from '../types/index.js';
|
||||
import { soundFx } from '../utils/sound.js';
|
||||
import { useTranslation } from '../utils/i18n.js';
|
||||
|
||||
interface ColumnSettingsModalProps {
|
||||
column: Column;
|
||||
onClose: () => void;
|
||||
onSave: (columnId: string, updates: { title: string; maxWipLimit: number; autoStaleHours: number }) => void;
|
||||
}
|
||||
|
||||
export const ColumnSettingsModal: React.FC<ColumnSettingsModalProps> = ({ column, onClose, onSave }) => {
|
||||
const { t } = useTranslation();
|
||||
const [title, setTitle] = useState(column.title);
|
||||
const [maxWipLimit, setMaxWipLimit] = useState<number>(column.maxWipLimit || 0);
|
||||
const [autoStaleHours, setAutoStaleHours] = useState<number>(column.autoStaleHours || 0);
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
soundFx.playClick();
|
||||
onSave(column.id, {
|
||||
title: title.trim() || column.title,
|
||||
maxWipLimit: Number(maxWipLimit) || 0,
|
||||
autoStaleHours: Number(autoStaleHours) || 0,
|
||||
});
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-3 sm:p-4 bg-slate-950/70 backdrop-blur-md animate-fade-in">
|
||||
<div className="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl shadow-2xl max-w-md w-full p-4 sm:p-6 relative text-slate-900 dark:text-slate-100 max-h-[92vh] overflow-y-auto">
|
||||
<button
|
||||
onClick={() => {
|
||||
soundFx.playClick();
|
||||
onClose();
|
||||
}}
|
||||
className="absolute top-4 right-4 text-slate-400 hover:text-slate-700 dark:hover:text-slate-200 p-1 rounded-md"
|
||||
>
|
||||
<X size={18} />
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-3 mb-4 sm:mb-5">
|
||||
<div className="w-9 h-9 sm:w-10 sm:h-10 bg-indigo-50 dark:bg-emerald-500/10 border border-indigo-200 dark:border-emerald-500/30 rounded-xl flex items-center justify-center text-indigo-600 dark:text-emerald-400">
|
||||
<Settings2 size={18} />
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-sm sm:text-base font-bold text-slate-900 dark:text-slate-100">
|
||||
{t('editColSettings')}
|
||||
</h2>
|
||||
<p className="text-xs text-slate-500 dark:text-slate-400 truncate max-w-[200px]">
|
||||
{column.title}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-3.5 text-xs">
|
||||
{/* Column Title */}
|
||||
<div>
|
||||
<label className="block text-xs font-semibold text-slate-700 dark:text-slate-300 mb-1.5">
|
||||
{t('taskTitle')}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
className="w-full bg-slate-50 dark:bg-slate-950/70 border border-slate-300 dark:border-slate-800 rounded-lg p-2.5 text-slate-900 dark:text-slate-100 text-xs outline-none focus:border-indigo-500"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* WIP Limit Setting */}
|
||||
<div className="bg-amber-50/70 dark:bg-slate-950/70 border border-amber-200 dark:border-amber-500/30 p-3.5 rounded-xl">
|
||||
<label className="flex items-center gap-1.5 text-xs font-semibold text-amber-800 dark:text-amber-400 mb-1">
|
||||
<AlertTriangle size={14} className="text-amber-600 dark:text-amber-400 shrink-0" />
|
||||
<span>{t('wipLimitLabel')}</span>
|
||||
</label>
|
||||
<p className="text-[11px] text-slate-600 dark:text-slate-400 mb-2 leading-relaxed">
|
||||
Membatasi jumlah kartu aktif di kolom ini agar tim fokus menyelesaikan tugas sebelum mengambil yang baru.
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
min={0}
|
||||
max={50}
|
||||
value={maxWipLimit}
|
||||
onChange={(e) => setMaxWipLimit(parseInt(e.target.value, 10) || 0)}
|
||||
className="w-20 sm:w-24 bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 rounded-lg p-2 text-slate-900 dark:text-slate-100 text-xs text-center outline-none"
|
||||
/>
|
||||
<span className="text-[11px] sm:text-xs text-amber-800 dark:text-amber-300 font-medium">
|
||||
{maxWipLimit === 0 ? `(${t('wipUnlimited')})` : `(Maks. ${maxWipLimit} kartu)`}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Auto-Stale Hours Setting */}
|
||||
<div className="bg-cyan-50/70 dark:bg-slate-950/70 border border-cyan-200 dark:border-cyan-500/30 p-3.5 rounded-xl">
|
||||
<label className="flex items-center gap-1.5 text-xs font-semibold text-cyan-800 dark:text-cyan-400 mb-1">
|
||||
<Clock size={14} className="text-cyan-600 dark:text-cyan-400 shrink-0" />
|
||||
<span>{t('autoStaleHoursLabel')}</span>
|
||||
</label>
|
||||
<p className="text-[11px] text-slate-600 dark:text-slate-400 mb-2 leading-relaxed">
|
||||
Memberikan tanda peringatan jika kartu tidak bergerak di kolom ini melebihi durasi yang ditentukan.
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<select
|
||||
value={autoStaleHours}
|
||||
onChange={(e) => setAutoStaleHours(parseInt(e.target.value, 10) || 0)}
|
||||
className="bg-white dark:bg-slate-900 border border-slate-300 dark:border-slate-800 rounded-lg p-2 text-slate-900 dark:text-slate-100 text-xs outline-none flex-1"
|
||||
>
|
||||
<option value={0}>🚫 Nonaktif (0 Jam)</option>
|
||||
<option value={12}>⏳ 12 Jam</option>
|
||||
<option value={24}>⏳ 24 Jam (1 Hari) [Standar]</option>
|
||||
<option value={48}>⏳ 48 Jam (2 Hari)</option>
|
||||
<option value={72}>⏳ 72 Jam (3 Hari)</option>
|
||||
<option value={168}>⏳ 7 Hari</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end gap-2 pt-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
soundFx.playClick();
|
||||
onClose();
|
||||
}}
|
||||
className="btn-modern-secondary py-2 px-4"
|
||||
>
|
||||
{t('cancel')}
|
||||
</button>
|
||||
<button type="submit" className="btn-modern-primary py-2 px-5 font-bold">
|
||||
{t('save')}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user