Link project titles to detail page, add inline project name edit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -82,7 +82,7 @@ export default function ClientDashboard() {
|
||||
const pendingReview = projectTasks.filter(t => t.status === 'client_review').length;
|
||||
const active = projectTasks.filter(t => ['in_progress', 'on_hold', 'not_started'].includes(t.status)).length;
|
||||
return (
|
||||
<Link key={project.id} to="/my-projects" style={{ textDecoration: 'none' }}>
|
||||
<Link key={project.id} to={`/my-projects/${project.id}`} style={{ textDecoration: 'none' }}>
|
||||
<div style={{
|
||||
padding: '12px 16px',
|
||||
border: `1px solid ${pendingReview > 0 ? 'var(--accent)' : 'var(--border)'}`,
|
||||
|
||||
@@ -16,7 +16,10 @@ export default function MyProjectDetail() {
|
||||
const [tasks, setTasks] = useState([]);
|
||||
const [submissions, setSubmissions] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [filter, setFilter] = useState('all'); // 'all' | 'mine'
|
||||
const [filter, setFilter] = useState('all');
|
||||
const [editingName, setEditingName] = useState(false);
|
||||
const [nameVal, setNameVal] = useState('');
|
||||
const [savingName, setSavingName] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
async function load() {
|
||||
@@ -42,6 +45,16 @@ export default function MyProjectDetail() {
|
||||
load();
|
||||
}, [id]);
|
||||
|
||||
const handleSaveName = async (e) => {
|
||||
e.preventDefault();
|
||||
if (!nameVal.trim()) return;
|
||||
setSavingName(true);
|
||||
await supabase.from('projects').update({ name: nameVal.trim() }).eq('id', id);
|
||||
setProject(p => ({ ...p, name: nameVal.trim() }));
|
||||
setEditingName(false);
|
||||
setSavingName(false);
|
||||
};
|
||||
|
||||
if (loading) return <Layout><p style={{ padding: 24, color: 'var(--text-muted)' }}>Loading...</p></Layout>;
|
||||
if (!project) return <Layout><p>Project not found.</p></Layout>;
|
||||
|
||||
@@ -58,16 +71,37 @@ export default function MyProjectDetail() {
|
||||
|
||||
<div className="page-header">
|
||||
<div>
|
||||
<div className="page-title">{project.name}</div>
|
||||
{editingName ? (
|
||||
<form onSubmit={handleSaveName} style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<input
|
||||
type="text"
|
||||
value={nameVal}
|
||||
onChange={e => setNameVal(e.target.value)}
|
||||
autoFocus
|
||||
required
|
||||
style={{ fontSize: 22, fontWeight: 700, padding: '4px 10px', margin: 0, width: 260 }}
|
||||
/>
|
||||
<button type="submit" className="btn btn-primary btn-sm" disabled={savingName}>{savingName ? '...' : 'Save'}</button>
|
||||
<button type="button" className="btn btn-outline btn-sm" onClick={() => setEditingName(false)}>Cancel</button>
|
||||
</form>
|
||||
) : (
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
||||
<div className="page-title">{project.name}</div>
|
||||
<button
|
||||
className="btn btn-outline btn-sm"
|
||||
onClick={() => { setNameVal(project.name); setEditingName(true); }}
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="page-subtitle">
|
||||
{tasks.length} request{tasks.length !== 1 ? 's' : ''} · Started {new Date(project.created_at).toLocaleDateString()}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: 8 }}>
|
||||
<Link to={`/new-request?project=${encodeURIComponent(project.name)}`} className="btn btn-primary">
|
||||
+ Add Request
|
||||
</Link>
|
||||
</div>
|
||||
<Link to={`/new-request?project=${encodeURIComponent(project.name)}`} className="btn btn-primary">
|
||||
+ Add Request
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Filter toggle */}
|
||||
|
||||
@@ -33,9 +33,13 @@ function ProjectGroup({ project, tasks, submissions, currentUserId, filter }) {
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
||||
<span style={{ fontSize: 14, fontWeight: 700, color: 'var(--text-primary)' }}>
|
||||
<Link
|
||||
to={`/my-projects/${project.id}`}
|
||||
onClick={e => e.stopPropagation()}
|
||||
style={{ fontSize: 14, fontWeight: 700, color: 'var(--text-primary)', textDecoration: 'none' }}
|
||||
>
|
||||
{project.name}
|
||||
</span>
|
||||
</Link>
|
||||
<span style={{ fontSize: 11, fontWeight: 600, padding: '2px 8px', borderRadius: 4, background: 'rgba(245,165,35,0.15)', color: 'var(--accent)' }}>
|
||||
{filteredTasks.length} request{filteredTasks.length !== 1 ? 's' : ''}
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user