BoardForm.jsx 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. import React from "react";
  2. import { useTranslation } from "react-i18next";
  3. import { nanoid } from "nanoid";
  4. import { Field } from "react-final-form";
  5. import Hint from "../../components/ui/formUtils/Hint";
  6. import Label from "../../components/ui/formUtils/Label";
  7. import SliderRange from "../../components/ui/SliderRange";
  8. import { ImageField } from "../../components/mediaLibrary";
  9. const BoardConfigForm = ({ boardConfig, setBoardConfig }) => {
  10. const { t } = useTranslation();
  11. const [defaultPlayerCount] = React.useState([]);
  12. const addTranslation = React.useCallback(() => {
  13. setBoardConfig((prev) => ({
  14. ...prev,
  15. translations: [...(prev.translations || []), { id: nanoid() }],
  16. }));
  17. }, [setBoardConfig]);
  18. const removeTranslation = (idToRemove) => {
  19. setBoardConfig((prev) => ({
  20. ...prev,
  21. translations: prev.translations.filter(({ id }) => id !== idToRemove),
  22. }));
  23. };
  24. return (
  25. <>
  26. <Label>
  27. {t("Publish")}
  28. <Field
  29. name="published"
  30. component="input"
  31. type="checkbox"
  32. initialValue={boardConfig.published}
  33. />
  34. <Hint>{t("Check it to make your board publicly visible")}</Hint>
  35. </Label>
  36. <Label>
  37. {t("Number of players")}
  38. <Field
  39. name="playerCount"
  40. initialValue={boardConfig.playerCount || defaultPlayerCount}
  41. >
  42. {({ input: { onChange, value } }) => {
  43. return (
  44. <SliderRange
  45. defaultValue={[2, 4]}
  46. value={value}
  47. min={1}
  48. max={9}
  49. step={1}
  50. onChange={onChange}
  51. />
  52. );
  53. }}
  54. </Field>
  55. </Label>
  56. <Label>
  57. {t("Duration (mins)")}
  58. <Field
  59. name="duration"
  60. initialValue={
  61. Array.isArray(boardConfig.duration)
  62. ? boardConfig.duration
  63. : defaultPlayerCount
  64. }
  65. >
  66. {({ input: { onChange, value } }) => {
  67. return (
  68. <SliderRange
  69. defaultValue={[15, 90]}
  70. value={value}
  71. min={15}
  72. max={90}
  73. step={15}
  74. onChange={onChange}
  75. />
  76. );
  77. }}
  78. </Field>
  79. </Label>
  80. <Label>
  81. {t("Minimal age (years)")}
  82. <Field
  83. name="minAge"
  84. component="input"
  85. initialValue={boardConfig.minAge}
  86. style={{ width: "5em", textAlign: "right" }}
  87. />
  88. </Label>
  89. <Label>
  90. {t("Board size")}
  91. <Field
  92. name="size"
  93. component="input"
  94. initialValue={boardConfig.size}
  95. style={{ width: "5em", textAlign: "right" }}
  96. />
  97. </Label>
  98. <Label>
  99. {t("Magnetic Grid size")}
  100. <Field
  101. name="gridSize"
  102. component="input"
  103. initialValue={boardConfig.gridSize || 1}
  104. style={{ width: "5em", textAlign: "right" }}
  105. />
  106. </Label>
  107. <Label>
  108. {t("Image")}
  109. <Field name="imageUrl" initialValue={boardConfig.imageUrl}>
  110. {({ input: { value, onChange } }) => {
  111. return <ImageField value={value} onChange={onChange} />;
  112. }}
  113. </Field>
  114. </Label>
  115. <Label>
  116. {t("Material language")}
  117. <Field
  118. name="materialLanguage"
  119. component="select"
  120. initialValue={boardConfig.materialLanguage}
  121. style={{ width: "20em" }}
  122. >
  123. <option />
  124. <option value="Multi-lang">🌍 {t("Multi-lang")}</option>
  125. <option value="en">🇬🇧 {t("English")}</option>
  126. <option value="fr">🇫🇷 {t("French")}</option>
  127. </Field>
  128. </Label>
  129. <fieldset style={{ marginBottom: "2em", paddingBottom: "1em" }}>
  130. <legend>{t("Informations")}</legend>
  131. <Label>
  132. {t("Default language")}
  133. <Field
  134. name="defaultLanguage"
  135. component="select"
  136. initialValue={boardConfig.defaultLanguage}
  137. style={{ width: "15em" }}
  138. >
  139. <option />
  140. <option value="en">🇬🇧 {t("English")}</option>
  141. <option value="fr">🇫🇷 {t("French")}</option>
  142. </Field>
  143. </Label>
  144. <Label>
  145. {t("Game name")}
  146. <Field
  147. name="defaultName"
  148. component="input"
  149. initialValue={boardConfig.defaultName || boardConfig.name}
  150. style={{ width: "15em" }}
  151. />
  152. </Label>
  153. <Label>
  154. {t("Baseline")}
  155. <Field
  156. name="defaultBaseline"
  157. component="input"
  158. initialValue={boardConfig.defaultBaseline}
  159. style={{ width: "100%" }}
  160. />
  161. </Label>
  162. <Label>
  163. {t("Description")}
  164. <Field
  165. name="defaultDescription"
  166. component="textarea"
  167. initialValue={boardConfig.defaultDescription || boardConfig.info}
  168. style={{ minHeight: "10em" }}
  169. />
  170. </Label>
  171. </fieldset>
  172. <div>
  173. {(boardConfig.translations || []).map(({ id }, index) => {
  174. return (
  175. <fieldset
  176. style={{ marginBottom: "2em", paddingBottom: "1em" }}
  177. key={id}
  178. >
  179. <legend>
  180. {t("Translation")} {index}
  181. </legend>
  182. <button
  183. className="button clear icon-only trash"
  184. onClick={() => removeTranslation(id)}
  185. >
  186. <img
  187. src="https://icongr.am/feather/trash.svg?size=25&color=ffffff"
  188. alt={t("Remove")}
  189. />
  190. </button>
  191. <Label>
  192. {t("Language")}
  193. <Field
  194. name={`translations[${index}].language`}
  195. component="select"
  196. initialValue={boardConfig.translations[index].language}
  197. style={{ width: "15em" }}
  198. >
  199. <option />
  200. <option value="en">🇬🇧 {t("English")}</option>
  201. <option value="fr">🇫🇷 {t("French")}</option>
  202. </Field>
  203. </Label>
  204. <Label>
  205. {t("Game name")}
  206. <Field
  207. name={`translations[${index}].name`}
  208. component="input"
  209. initialValue={boardConfig.translations[index].name}
  210. style={{ width: "15em" }}
  211. />
  212. </Label>
  213. <Label>
  214. {t("Baseline")}
  215. <Field
  216. name={`translations[${index}].baseline`}
  217. component="input"
  218. initialValue={boardConfig.translations[index].baseline}
  219. style={{ width: "100%" }}
  220. />
  221. </Label>
  222. <Label>
  223. {t("Description")}
  224. <Field
  225. name={`translations[${index}].description`}
  226. component="textarea"
  227. initialValue={boardConfig.translations[index].description}
  228. style={{ minHeight: "10em" }}
  229. />
  230. </Label>
  231. </fieldset>
  232. );
  233. })}
  234. <button onClick={addTranslation}>{t("Add translation")}</button>
  235. </div>
  236. </>
  237. );
  238. };
  239. export default BoardConfigForm;