/* Clients: the Drive folder that publishing needs, and the monthly quota with
how much of it is actually done. One screen answers "who are we behind on". */
function ClientModal({ client, onClose, onSaved }) {
const [form, setForm] = React.useState({
name: client ? client.name : '',
color: (client && client.color) || '#2563eb',
drive_client_folder_url: (client && client.drive_client_folder_url) || '',
drive_main_folder_url: (client && client.drive_main_folder_url) || '',
drive_internal_folder_url: '',
monthly_videos: client ? client.monthly_videos : 0,
monthly_statics: client ? client.monthly_statics : 0,
retainer_note: (client && client.retainer_note) || '',
is_active: client ? client.is_active : true,
});
const [saving, setSaving] = React.useState(false);
const set = (k, v) => setForm((f) => ({ ...f, [k]: v }));
const save = () => {
if (!form.name.trim()) { toast('Name required', 'error'); return; }
setSaving(true);
const body = {
...form,
monthly_videos: Number(form.monthly_videos) || 0,
monthly_statics: Number(form.monthly_statics) || 0,
retainer_note: form.retainer_note || null,
};
const call = client ? api.patch(`/api/clients/${client.id}`, body) : api.post('/api/clients', body);
call.then(() => { toast('Saved'); onSaved(); onClose(); })
.catch((e) => toast(e.message, 'error'))
.finally(() => setSaving(false));
};
return (
The brand's top folder — everything about that client. Opened from the client
profile, never published into.
The client-facing folder, the one holding the month folders. Studio creates
the month and angle subfolders itself when an ad is confirmed.
| Client | Videos this month | Statics this month | Main folder | Publish to | |
|---|---|---|---|---|---|
|
{c.name}
{c.retainer_note &&
{c.retainer_note} }
|
{row ? |
{row ? |
{c.drive_main_folder_url ? e.stopPropagation()}>Open : —} | {c.drive_client_folder_url ? e.stopPropagation()}>Assets folder : not set — cannot publish} |
Counted by delivery month, not by the day a task was created. Done means confirmed or published.
{(creating || editing) && (