daddy/client/src/components/DecisionSupportFilePage/OptionsSection.tsx

150 lines
5.8 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { FunctionComponent, useState, useEffect, ChangeEvent, MouseEvent } from 'react';
import { DecisionSupportFileUpdaterProps } from './DecisionSupportFileUpdaterProps';
import { base58UUID } from "../../util/uuid";
export interface OptionsSectionProps extends DecisionSupportFileUpdaterProps {};
const OptionsSectionName = 'options';
export const OptionsSection: FunctionComponent<OptionsSectionProps> = ({ dsf, updateDSF }) => {
interface OptionsSectionState {
changed: boolean
section: OptionsSection
}
interface OptionsSection {
options: Option[]
}
interface Option {
id: string
label: string
pros: string
cons: string
}
const [ state, setState ] = useState<OptionsSectionState>({
changed: false,
section: {
options: [],
}
});
useEffect(() => {
if (!state.changed) return;
updateDSF({ ...dsf, sections: { ...dsf.sections, [OptionsSectionName]: { ...state.section }} })
setState(state => ({ ...state, changed: false }));
}, [state.changed]);
useEffect(() => {
if (!dsf.sections[OptionsSectionName]) return;
setState(state => ({ ...state, changed: false, section: {...state.section, ...dsf.sections[OptionsSectionName] }}));
}, [dsf.sections[OptionsSectionName]]);
function newOption(label: string, pros: string, cons: string): Option {
return {
id: base58UUID(),
label,
pros,
cons
};
}
const onAddOptionClick = (evt: MouseEvent) => {
var options = JSON.parse(JSON.stringify(state.section.options))
var option = newOption("Décision", "", "");
options.push(option);
setState(state => ({ ...state, changed: true, section: { ...state.section, options }}));
};
const onOptionChange = (id: string, attrName: string, evt: ChangeEvent<HTMLInputElement>) => {
const target = evt.currentTarget;
const value = target.hasOwnProperty('checked') ? target.checked : target.value;
var options = JSON.parse(JSON.stringify(state.section.options))
options[id][attrName] = value;
setState(state => ({ ...state, changed: true, section: { ...state.section, options }}));
};
return (
<section>
<h4 id="options-section" className="is-size-4 title is-spaced"><a href="#options-section">Explorer les options</a></h4>
<div className="box">
<div className="table-container">
<table className={`table is-bordered is-striped is-hoverable is-fullwidth`}>
<thead>
<tr>
<th></th>
<th>Décision</th>
<th>Pours</th>
<th>Contres</th>
</tr>
</thead>
<tbody>
{
state.section.options.map((o, index) => {
return (
<tr key={`option-${o.id}`}>
<td>
<button
className="button is-danger is-small is-outlined">
🗑
</button>
</td>
<td>
<textarea className="textarea"
value={o.label}
onChange={onOptionChange.bind(null, index, 'label')}
placeholder="Décrire cette décision."
rows={10}>
</textarea>
</td>
<td>
<textarea className="textarea"
value={o.pros}
onChange={onOptionChange.bind(null, index, 'pros')}
placeholder="Décrire les avantages de cette décision."
rows={10}>
</textarea>
</td>
<td>
<textarea className="textarea"
value={o.cons}
onChange={onOptionChange.bind(null, index, 'cons')}
placeholder="Décrire les désavantages de cette décision."
rows={10}>
</textarea>
</td>
</tr>
)
})
}
{
state.section.options.length === 0 ?
<tr>
<td className={`noPrint`}></td>
<td colSpan={4}>Aucune option pour l'instant.</td>
</tr> :
null
}
</tbody>
<tfoot>
<tr>
<td className={`noPrint`} colSpan={3}></td>
<td colSpan={2}>
<div className="field has-addons noPrint">
<p className="control">
<a className="button is-primary" onClick={onAddOptionClick}>
Ajouter
</a>
</p>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</section>
);
};