redesign: rename Project→Client, finance single-card + filters, mobile tasks, sticky headers
- Rename "Project" → "Client" across UI (labels + /projects→/clients routes with redirect); normalize company-meaning labels to "Company" - Finance tabs: merge dual cards into one per tab, add header column filters (expenses/subs/invoices), overview as 3-section card, move +Expense/+Invoice to card right edge - Tasks: responsive mobile stats grid, progressive column hiding (min Status+Name+Assigned), sidebar mobile footer (profile/theme/signout) - Hide Company column for single-company users; +Task shows disabled Company field instead of hiding - Sticky table headers site-wide with opaque card background - Pin dev server to port 5173 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -85,6 +85,13 @@ export default function RequestForm({
|
||||
|
||||
const companyId = form.companyId || initialCompanyId;
|
||||
|
||||
// Single-company user: lock selection to their one company.
|
||||
useEffect(() => {
|
||||
if (companies.length === 1 && !form.companyId) {
|
||||
setForm(f => ({ ...f, companyId: companies[0].id }));
|
||||
}
|
||||
}, [companies, form.companyId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!companyId) { setExistingProjects([]); setCompanyUsers([]); return; }
|
||||
Promise.all([
|
||||
@@ -228,14 +235,19 @@ export default function RequestForm({
|
||||
{companies.map(co => <option key={co.id} value={co.id}>{co.name}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
) : companies.length === 1 ? (
|
||||
<div className="form-group">
|
||||
<label style={modalLabelStyle}>Company</label>
|
||||
<input value={companies[0].name} disabled style={{ ...modalInputStyle, opacity: 0.5, cursor: 'not-allowed' }} />
|
||||
</div>
|
||||
) : <div />}
|
||||
<div className="form-group">
|
||||
<label style={modalLabelStyle}>Project {!lockedFields.includes('project') && '*'}</label>
|
||||
<label style={modalLabelStyle}>Client {!lockedFields.includes('project') && '*'}</label>
|
||||
{lockedFields.includes('project') ? (
|
||||
<input value={form.project} disabled style={{ ...modalInputStyle, opacity: 0.5, cursor: 'not-allowed' }} />
|
||||
) : isTypingProject ? (
|
||||
<div style={{ display: 'flex', gap: 8 }}>
|
||||
<input type="text" placeholder="Enter project name..." value={newProjectName} onChange={e => setNewProjectName(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); handleAddProject(); } }} autoFocus style={{ ...modalInputStyle, flex: 1 }} />
|
||||
<input type="text" placeholder="Enter client name..." value={newProjectName} onChange={e => setNewProjectName(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); handleAddProject(); } }} autoFocus style={{ ...modalInputStyle, flex: 1 }} />
|
||||
<button type="button" className="btn btn-outline" onClick={handleAddProject} disabled={!newProjectName.trim()}>Add</button>
|
||||
<button type="button" className="btn btn-outline" onClick={() => { setIsTypingProject(false); setNewProjectName(''); }}>Cancel</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user