Session 2026-05-30: tasks/projects unification, code consolidation, file renames
- Unified Tasks page: 3 role render blocks → 1, normalized row shape, single renderRow/sort/tabs - Fixed role scoping: external = all tasks in member projects, client = all tasks in company projects - Fixed client bug: was scoped by submitted_by, now company→project→tasks - Aligned dashboard client scope to match tasks page - Hot tasks dashboard: now filters to active statuses only (not completed/invoiced/paid) - Removed Projects.jsx (dead), fixed /project/ → /projects/ links - Renamed all page files to match folder path (Team*, External*, Client* prefixes) - Renamed: RequestsPage→Tasks, Settings→Profile, CompaniesPage→Companies, ProjectDetailPage→ProjectDetail - Dropped dead fetches from Tasks page (invoices, invoice_items, subcontractor_invoice_items) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Layout from '../../components/Layout';
|
||||
import { supabase } from '../../lib/supabase';
|
||||
import { useAuth } from '../../context/AuthContext';
|
||||
|
||||
export default function NewProject() {
|
||||
const { currentUser } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const companyOptions = currentUser.companies?.length
|
||||
? currentUser.companies
|
||||
: (currentUser.company ? [currentUser.company] : []);
|
||||
|
||||
const [selectedCompanyId, setSelectedCompanyId] = useState(companyOptions[0]?.id || '');
|
||||
const [name, setName] = useState('');
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
if (!companyOptions.length) {
|
||||
return (
|
||||
<Layout>
|
||||
<div style={{ maxWidth: 480, margin: '0 auto', textAlign: 'center', paddingTop: 48 }}>
|
||||
<h2 style={{ fontSize: 20, fontWeight: 400, marginBottom: 8 }}>Account Not Yet Active</h2>
|
||||
<p style={{ color: 'var(--text-secondary)', fontSize: 14 }}>
|
||||
Your account hasn't been linked to a company yet. Please contact the Fourge team to get set up.
|
||||
</p>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
if (saving) return;
|
||||
const trimmedName = name.trim();
|
||||
if (!trimmedName) return;
|
||||
setSaving(true);
|
||||
setError(null);
|
||||
|
||||
const { data, error: insertError } = await supabase
|
||||
.from('projects')
|
||||
.insert({ company_id: selectedCompanyId, name: trimmedName })
|
||||
.select('id')
|
||||
.single();
|
||||
|
||||
if (insertError) {
|
||||
setError(insertError.message);
|
||||
setSaving(false);
|
||||
return;
|
||||
}
|
||||
|
||||
navigate(`/my-projects/${data.id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="page-header">
|
||||
<div>
|
||||
<div className="page-title">New Project</div>
|
||||
<div className="page-subtitle">Create a project to organise your work.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="card" style={{ maxWidth: 480 }}>
|
||||
<form onSubmit={handleSubmit}>
|
||||
{companyOptions.length > 1 && (
|
||||
<div className="form-group">
|
||||
<label>Company *</label>
|
||||
<select
|
||||
value={selectedCompanyId}
|
||||
onChange={e => setSelectedCompanyId(e.target.value)}
|
||||
required
|
||||
>
|
||||
{companyOptions.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="form-group">
|
||||
<label>Project Name *</label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="e.g. Brand Refresh 2026"
|
||||
value={name}
|
||||
onChange={e => setName(e.target.value)}
|
||||
autoFocus
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="notification notification-error" style={{ marginBottom: 16 }}>
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="action-buttons">
|
||||
<button type="submit" className="btn btn-primary btn-lg" disabled={saving || !name.trim()}>
|
||||
{saving ? 'Creating...' : 'Create Project'}
|
||||
</button>
|
||||
<button type="button" className="btn btn-outline" onClick={() => navigate('/my-projects')}>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user