diff --git a/src/components/modal/submit-modal-step-justification.tsx b/src/components/modal/submit-modal-step-justification.tsx index 42d870ba9..2bfb81564 100644 --- a/src/components/modal/submit-modal-step-justification.tsx +++ b/src/components/modal/submit-modal-step-justification.tsx @@ -2,10 +2,14 @@ import { RmgFields, RmgFieldsField } from '@railmapgen/rmg-components'; import { Button, ModalBody, ModalFooter, Text } from '@chakra-ui/react'; import { useTranslation } from 'react-i18next'; import { MdChevronLeft, MdChevronRight } from 'react-icons/md'; +import useTranslatedName from '../hooks/use-translated-name'; +import { DATA_SOURCE_DISPLAY_TEXT, DataSource } from '../../util/constants'; const urlValidator = (url: string): boolean => !!url.match(/^https?:\/\//)?.[0]; interface SubmitModalStepJustificationProps { + dataSource: DataSource | ''; + onDataSourceChange: (value: DataSource | '') => void; refLink: string; onRefLinkChange: (value: string) => void; justification: string; @@ -15,11 +19,34 @@ interface SubmitModalStepJustificationProps { } export default function SubmitModalStepJustification(props: SubmitModalStepJustificationProps) { - const { refLink, onRefLinkChange, justification, onJustificationChange, onPrev, onNext } = props; + const { + dataSource, + onDataSourceChange, + refLink, + onRefLinkChange, + justification, + onJustificationChange, + onPrev, + onNext, + } = props; const { t } = useTranslation(); + const translateName = useTranslatedName(); + + const dataSourceOptions = Object.fromEntries([ + ['', t('Please select...')], + ...Object.entries(DATA_SOURCE_DISPLAY_TEXT).map(([key, translation]) => [key, translateName(translation)]), + ]); const fields: RmgFieldsField[] = [ + { + type: 'select', + label: t('Data source'), + options: dataSourceOptions, + disabledOptions: [''], + value: dataSource, + onChange: value => onDataSourceChange(value as DataSource), + }, { type: 'input', value: refLink, @@ -37,7 +64,7 @@ export default function SubmitModalStepJustification(props: SubmitModalStepJusti }, ]; - const isNextDisabled = !refLink || !justification || !urlValidator(refLink); + const isNextDisabled = !dataSource || !refLink || !justification || !urlValidator(refLink); return ( <> diff --git a/src/components/modal/submit-modal-step-submit.tsx b/src/components/modal/submit-modal-step-submit.tsx index a53b9acc7..a114b7e66 100644 --- a/src/components/modal/submit-modal-step-submit.tsx +++ b/src/components/modal/submit-modal-step-submit.tsx @@ -14,26 +14,35 @@ import { RmgDebouncedTextarea } from '@railmapgen/rmg-components'; import { useTranslation } from 'react-i18next'; import { CityEntry, CountryEntry, PaletteEntry } from '@railmapgen/rmg-palette-resources'; import { useRef } from 'react'; -import { getGitHubIssueDetailsBlock, GITHUB_ISSUE_PREAMBLE } from '../../util/constants'; +import { + DATA_SOURCE_DISPLAY_TEXT, + DataSource, + getGitHubIssueDetailsBlock, + GITHUB_ISSUE_PREAMBLE, +} from '../../util/constants'; +import useTranslatedName from '../hooks/use-translated-name'; interface SubmitModalStepSubmitProps { countryEntry: CountryEntry | null; cityEntry: CityEntry; paletteList: PaletteEntry[]; + dataSource: DataSource | ''; refLink: string; justification: string; onPrev: () => void; } export default function SubmitModalStepSubmit(props: SubmitModalStepSubmitProps) { - const { countryEntry, cityEntry, paletteList, refLink, justification, onPrev } = props; + const { countryEntry, cityEntry, paletteList, dataSource, refLink, justification, onPrev } = props; const { t } = useTranslation(); + const translateName = useTranslatedName(); const linkColour = useColorModeValue('primary.500', 'primary.300'); const textareaRef = useRef(null); const issueBody = [ + `**Data source:** ${dataSource ? translateName(DATA_SOURCE_DISPLAY_TEXT[dataSource]) : '(REPLACE ME)'}`, `**Reference link:** ${refLink || '(REPLACE ME)'}`, `**Justification:** ${justification || '(REPLACE ME)'}`, GITHUB_ISSUE_PREAMBLE, diff --git a/src/components/modal/submit-modal.tsx b/src/components/modal/submit-modal.tsx index 9cdeb67e2..eae0c971d 100644 --- a/src/components/modal/submit-modal.tsx +++ b/src/components/modal/submit-modal.tsx @@ -1,6 +1,6 @@ import { Modal, ModalCloseButton, ModalContent, ModalHeader, ModalOverlay } from '@chakra-ui/react'; import { useEffect, useState } from 'react'; -import { DRAFT_TICKET_KEY, InvalidReasonType } from '../../util/constants'; +import { DataSource, DRAFT_TICKET_KEY, InvalidReasonType } from '../../util/constants'; import { useRootSelector } from '../../redux'; import { ticketSelectors } from '../../redux/ticket/ticket-slice'; import { useTranslation } from 'react-i18next'; @@ -23,6 +23,7 @@ export default function SubmitModal(props: SubmitModalProps) { const [cityErrors, setCityErrors] = useState([]); const [lineErrors, setLineErrors] = useState>({}); + const [dataSource, setDataSource] = useState(''); const [refLink, setRefLink] = useState(''); const [justification, setJustification] = useState(''); @@ -43,6 +44,7 @@ export default function SubmitModal(props: SubmitModalProps) { } else { // reset modal setIsIgnoreErrors(false); + setDataSource(''); setRefLink(''); setJustification(''); setIsFinishJustification(false); @@ -80,6 +82,8 @@ export default function SubmitModal(props: SubmitModalProps) { {isShowStepJustification && ( setIsFinishJustification(false)} diff --git a/src/util/constants.ts b/src/util/constants.ts index 2bb49bc3f..c1b4293b6 100644 --- a/src/util/constants.ts +++ b/src/util/constants.ts @@ -12,7 +12,7 @@ export const getGitHubIssueDetailsBlock = (type: 'country' | 'city' | 'lines', d const details = document.createElement('details'); details.setAttribute('repo', 'rmg-palette'); details.setAttribute('type', type); - details.textContent = JSON.stringify(data, null, 4); + details.textContent = JSON.stringify(data); return details.outerHTML; } else { return ''; @@ -85,6 +85,67 @@ export const INVALID_REASON: Record = { }, }; +const DATA_SOURCES = [ + 'OFFICIAL_WEBSITE', + 'SOCIAL_MEDIA', + 'GOVERNMENT', + 'INTERNAL', + 'WEBSITE_SOURCE_CODE', + 'PDF', + 'LOSSY', + 'WIKIPEDIA', + 'OTHER', +] as const; +export type DataSource = (typeof DATA_SOURCES)[number]; + +export const DATA_SOURCE_DISPLAY_TEXT: Record = { + OFFICIAL_WEBSITE: { + en: '1. Design standard published in the official website', + 'zh-Hans': '1. 官方网站发布的设计标准', + 'zh-Hant': '1. 官方網站發佈的設計標準', + }, + SOCIAL_MEDIA: { + en: '2. Design standard published by the official social media', + 'zh-Hans': '2. 官方社交媒体发布的设计标准', + 'zh-Hant': '2. 官方社交媒體發佈的設計標準', + }, + GOVERNMENT: { + en: '3. Code of design standard published by the government or legislature', + 'zh-Hans': '3. 政府或立法机关公布的设计守则', + 'zh-Hant': '3. 政府或立法機關公佈的設計守則', + }, + INTERNAL: { + en: '4. Internal leaked source', + 'zh-Hans': '4. 内部流出的来源', + 'zh-Hant': '4. 內部流出的來源', + }, + WEBSITE_SOURCE_CODE: { + en: '5. Source code of the official website', + 'zh-Hans': '5. 官方网站的源代码', + 'zh-Hant': '5. 官方網站的源程式碼', + }, + PDF: { + en: '6. Colours extracted from a PDF file', + 'zh-Hans': '6. 从 PDF 文件提取的颜色', + 'zh-Hant': '6. 从 PDF 檔案擷取的顏色', + }, + LOSSY: { + en: '7. Colours extracted from a lossy image (e.g. JPG)', + 'zh-Hans': '7. 从有损压缩的图片(如 JPG)提取的颜色', + 'zh-Hant': '7. 从有損壓縮的圖像(如 JPG)擷取的顏色', + }, + WIKIPEDIA: { + en: '8. Wikipedia', + 'zh-Hans': '8. 维基百科', + 'zh-Hant': '8. 維基百科', + }, + OTHER: { + en: '9. Others (Please indicate below)', + 'zh-Hans': '9. 其他(请于下方注明)', + 'zh-Hant': '9. 其他(請於下方註明)', + }, +}; + export enum Events { APP_LOAD = 'APP_LOAD',