import React, { useState } from 'react';
import Icon from '../Icon.jsx';
import { categories } from '../seed.js';
import { documentInputIssues } from '../access.js';
import { useStudio, uid, bumpVersion, log } from '../store.jsx';
import { Badge, Button, Field, Modal, Note, UploadBox } from '../ui.jsx';
export default function CreateCr({ close }) {
const { state: s, workspace: w, mutate, notify } = useStudio();
const [id] = useState(() => uid('cr'));
const [reference, setReference] = useState(''), [name, setName] = useState('');
const [category, setCategory] = useState(0), [documents, setDocuments] = useState([]);
const duplicate = s.crs.some(c => c.ref === reference.trim() && c.team === w.team);
const canSave = reference.trim() && name.trim() && !duplicate && !documentInputIssues(documents).length;
function save(event) {
event.preventDefault(); if (!canSave) return;
mutate(d => {
d.crs.push({ id, ref: reference.trim(), name: name.trim(), team: w.team, revision: 1, requires: [], conflicts: [], changes: [] });
d.documents.push(...documents.map(doc => ({ ...doc, status: 'Ready' })));
const workspace = d.workspaces.find(item => item.id === w.id); workspace.crIds.push(id); bumpVersion(d, workspace);
log(d, `Created ${reference.trim()} with ${documents.length} document(s)`);
}); close(); notify('CR created with its supporting document(s). No separate approval is required.');
}
return <Modal title="Add a change request" close={close} wide><p className="modal-intro">One document from any category is enough to create a CR.</p><form onSubmit={save}>
<div className="form-grid"><Field label="CR / SDR reference"><input required value={reference} onChange={e => setReference(e.target.value)} placeholder="CR-1080" maxLength={60}/></Field><Field label="Change name"><input required value={name} onChange={e => setName(e.target.value)} maxLength={120}/></Field></div>
<div className="category-tabs document-category-picker" role="tablist" aria-label="CR upload categories">{categories.map((label, index) => <button type="button" role="tab" aria-selected={category === index} className={category === index ? 'active' : ''} key={label} onClick={() => setCategory(index)}>{label}<span>{documents.filter(d => d.category === index).length}</span></button>)}</div>
<UploadBox scope={{ team: w.team, workspaceId: w.id, crId: id, category }} onStaged={files => setDocuments(d => [...d, ...files])}/>
{documents.map(doc => <div className="selected-file" key={doc.id}><Icon name="file" size={16}/><span>{doc.name}<small>{categories[doc.category]}</small></span><Badge tone="green">Attached</Badge><Button onClick={() => setDocuments(files => files.filter(f => f.id !== doc.id))}>Remove</Button></div>)}
<Note>{documents.length ? 'The one-document minimum is met. Other categories can remain empty.' : 'Upload at least one Business, Technical, or Functional / Bug Information document. All three are not required.'}</Note>
{duplicate && <p className="form-error" role="alert">This CR reference already exists in your team.</p>}
<div className="modal-actions"><Button onClick={close}>Cancel</Button><Button type="submit" variant="primary" disabled={!canSave}>Create CR</Button></div>
</form></Modal>;
}
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)