@@ -2,10 +2,11 @@ | |||||
import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; | import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; | ||||
import { BASE_API_URL } from "@/config/api"; | import { BASE_API_URL } from "@/config/api"; | ||||
import { MailSetting } from "."; | |||||
import { MailSetting, MailTemplate } from "."; | |||||
export interface MailSave { | export interface MailSave { | ||||
settings: MailSetting[]; | settings: MailSetting[]; | ||||
templates: MailTemplate[]; | |||||
// template: MailTemplate; | // template: MailTemplate; | ||||
} | } | ||||
@@ -1,6 +1,7 @@ | |||||
import { serverFetchJson } from "@/app/utils/fetchUtil"; | import { serverFetchJson } from "@/app/utils/fetchUtil"; | ||||
import { BASE_API_URL } from "@/config/api"; | import { BASE_API_URL } from "@/config/api"; | ||||
import { cache } from "react"; | import { cache } from "react"; | ||||
import "server-only"; | |||||
export interface MailSMTP { | export interface MailSMTP { | ||||
host: string; | host: string; | ||||
@@ -17,6 +18,20 @@ export interface MailSetting { | |||||
type: string; | type: string; | ||||
} | } | ||||
export interface MailTemplate { | |||||
id: number; | |||||
to: string; | |||||
cc: string; | |||||
code: string; | |||||
description: string; | |||||
type: string; | |||||
params: string; | |||||
subjectCht: string; | |||||
subjectEng: string; | |||||
contentCht: string; | |||||
contentEng: string; | |||||
} | |||||
// export interface MailTemplate { | // export interface MailTemplate { | ||||
// cc?: string; | // cc?: string; | ||||
// bcc?: string; | // bcc?: string; | ||||
@@ -26,6 +41,7 @@ export interface MailSetting { | |||||
export const preloadMails = () => { | export const preloadMails = () => { | ||||
fetchMailSetting(); | fetchMailSetting(); | ||||
fetchMailTemplates(); | |||||
// fetchMailTimesheetTemplate(); | // fetchMailTimesheetTemplate(); | ||||
}; | }; | ||||
@@ -35,6 +51,12 @@ export const fetchMailSetting = cache(async () => { | |||||
}); | }); | ||||
}); | }); | ||||
export const fetchMailTemplates = cache(async () => { | |||||
return serverFetchJson<MailTemplate[]>(`${BASE_API_URL}/mailTemplates`, { | |||||
next: { tags: ["mailTemplates"] }, | |||||
}); | |||||
}); | |||||
// export const fetchMailTimesheetTemplate = cache(async () => { | // export const fetchMailTimesheetTemplate = cache(async () => { | ||||
// return serverFetchJson<MailSetting[]>(`${BASE_API_URL}/mails/timesheet-template`, { | // return serverFetchJson<MailSetting[]>(`${BASE_API_URL}/mails/timesheet-template`, { | ||||
// next: { tags: ["mailTimesheetTemplate"] }, | // next: { tags: ["mailTimesheetTemplate"] }, | ||||
@@ -21,7 +21,7 @@ | |||||
overflow: hidden; | overflow: hidden; | ||||
/* palette.neutral[200] */ | /* palette.neutral[200] */ | ||||
transition: border-color 0.3s, box-shadow 0.3s; | transition: border-color 0.3s, box-shadow 0.3s; | ||||
border-color: #F04438; | border-color: #F04438; | ||||
/* palette.primary.main */ | /* palette.primary.main */ | ||||
box-shadow: #F04438 0 0 0 2px; | box-shadow: #F04438 0 0 0 2px; | ||||
@@ -41,7 +41,7 @@ | |||||
display: none; | display: none; | ||||
} | } | ||||
:not(.tiptap-error) > .tiptap:focus { | |||||
:not(.tiptap-error)>.tiptap:focus { | |||||
background-color: transparent; | background-color: transparent; | ||||
border-color: #8dba00; | border-color: #8dba00; | ||||
/* palette.primary.main */ | /* palette.primary.main */ | ||||
@@ -53,6 +53,74 @@ | |||||
outline: none; | outline: none; | ||||
} | } | ||||
/* Basic editor styles */ | |||||
.tiptap { | |||||
:first-child { | |||||
margin-top: 0; | |||||
} | |||||
/* Table-specific styling */ | |||||
table { | |||||
border-collapse: collapse; | |||||
margin: 0; | |||||
overflow: hidden; | |||||
table-layout: fixed; | |||||
width: 100%; | |||||
td, | |||||
th { | |||||
border: 1px solid #000000; | |||||
box-sizing: border-box; | |||||
min-width: 1em; | |||||
padding: 6px 8px; | |||||
position: relative; | |||||
vertical-align: top; | |||||
>* { | |||||
margin-bottom: 0; | |||||
} | |||||
} | |||||
th { | |||||
background-color: #939393; | |||||
font-weight: bold; | |||||
text-align: left; | |||||
} | |||||
.selectedCell:after { | |||||
background: rgba(180, 180, 180, 0.467); | |||||
content: ""; | |||||
left: 0; | |||||
right: 0; | |||||
top: 0; | |||||
bottom: 0; | |||||
pointer-events: none; | |||||
position: absolute; | |||||
z-index: 2; | |||||
} | |||||
.column-resize-handle { | |||||
background-color: #d000ff; | |||||
bottom: -2px; | |||||
pointer-events: none; | |||||
position: absolute; | |||||
right: -2px; | |||||
top: 0; | |||||
width: 4px; | |||||
} | |||||
} | |||||
.tableWrapper { | |||||
margin: 1.5rem 0; | |||||
overflow-x: auto; | |||||
} | |||||
&.resize-cursor { | |||||
cursor: ew-resize; | |||||
cursor: col-resize; | |||||
} | |||||
} | |||||
/* Input styles */ | /* Input styles */ | ||||
/* .tiptap-input { | /* .tiptap-input { | ||||
font-size: 14px; | font-size: 14px; | ||||
@@ -14,6 +14,11 @@ import { Color } from '@tiptap/extension-color' | |||||
import ListItem from "@tiptap/extension-list-item"; | import ListItem from "@tiptap/extension-list-item"; | ||||
import TextStyle from "@tiptap/extension-text-style"; | import TextStyle from "@tiptap/extension-text-style"; | ||||
import TextAlign from '@tiptap/extension-text-align' | import TextAlign from '@tiptap/extension-text-align' | ||||
import Table from '@tiptap/extension-table' | |||||
import TableCell from '@tiptap/extension-table-cell' | |||||
import TableHeader from '@tiptap/extension-table-header' | |||||
import TableRow from '@tiptap/extension-table-row' | |||||
import Gapcursor from '@tiptap/extension-gapcursor' | |||||
interface Props { | interface Props { | ||||
content?: string, | content?: string, | ||||
@@ -64,7 +69,14 @@ const MailField: React.FC<Props> = ({ | |||||
Highlight.configure({ multicolor: true }), | Highlight.configure({ multicolor: true }), | ||||
Color, | Color, | ||||
ListItem, | ListItem, | ||||
TabHandler | |||||
TabHandler, | |||||
Gapcursor, | |||||
Table.configure({ | |||||
resizable: true, | |||||
}), | |||||
TableRow, | |||||
TableHeader, | |||||
TableCell, | |||||
], | ], | ||||
content: content, | content: content, | ||||
onUpdate({ editor }) { | onUpdate({ editor }) { | ||||
@@ -73,15 +85,15 @@ const MailField: React.FC<Props> = ({ | |||||
} | } | ||||
console.log(editor.getHTML()) | console.log(editor.getHTML()) | ||||
}, | }, | ||||
}) | |||||
}, []) | |||||
return ( | return ( | ||||
<Grid container rowSpacing={1}> | <Grid container rowSpacing={1}> | ||||
<Grid item xs={12}> | |||||
<MailToolbar editor={editor} /> | |||||
</Grid> | |||||
{/* <Grid item xs={12}> | |||||
{editor && <MailToolbar editor={editor} />} | |||||
</Grid> */} | |||||
<Grid item xs={12} > | <Grid item xs={12} > | ||||
<EditorContent className={error === true ? "tiptap-error" : ""} label="Template" editor={editor}/> | |||||
<EditorContent className={error === true ? "tiptap-error" : ""} label="Template" editor={editor} /> | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
); | ); | ||||
@@ -13,6 +13,8 @@ import FormatColorTextIcon from '@mui/icons-material/FormatColorText'; | |||||
import FormatAlignLeftIcon from '@mui/icons-material/FormatAlignLeft'; | import FormatAlignLeftIcon from '@mui/icons-material/FormatAlignLeft'; | ||||
import FormatAlignJustifyIcon from '@mui/icons-material/FormatAlignJustify'; | import FormatAlignJustifyIcon from '@mui/icons-material/FormatAlignJustify'; | ||||
import FormatAlignRightIcon from '@mui/icons-material/FormatAlignRight'; | import FormatAlignRightIcon from '@mui/icons-material/FormatAlignRight'; | ||||
import { useTranslation } from "react-i18next"; | |||||
import GridOnIcon from '@mui/icons-material/GridOn'; | |||||
interface Props { | interface Props { | ||||
editor: Editor | null; | editor: Editor | null; | ||||
@@ -58,7 +60,7 @@ const fontFamily = [ | |||||
value: 'Georgia', | value: 'Georgia', | ||||
}, | }, | ||||
{ | { | ||||
} | } | ||||
] | ] | ||||
@@ -66,11 +68,12 @@ const MailToolbar: React.FC<Props> = ({ | |||||
editor | editor | ||||
}) => { | }) => { | ||||
const { t } = useTranslation() | |||||
if (editor == null) { | if (editor == null) { | ||||
return null | return null | ||||
} | } | ||||
const [fontStyle, setFontStyle] = React.useState<string[]>(() => ["alignLeft"]); | |||||
const [fontStyle, setFontStyle] = React.useState<string[]>(["alignLeft"]); | |||||
const [colorHighlightValue, setColorHighlightValue] = React.useState<MuiColorInputValue>("red"); | const [colorHighlightValue, setColorHighlightValue] = React.useState<MuiColorInputValue>("red"); | ||||
const [colorTextValue, setColorTextValue] = React.useState<MuiColorInputValue>("black"); | const [colorTextValue, setColorTextValue] = React.useState<MuiColorInputValue>("black"); | ||||
const colorHighlightValueInputRef = React.useRef<any>(null); | const colorHighlightValueInputRef = React.useRef<any>(null); | ||||
@@ -189,6 +192,10 @@ const MailToolbar: React.FC<Props> = ({ | |||||
} | } | ||||
}, []) | }, []) | ||||
const handleInsertTable = useCallback(() => { | |||||
editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run() | |||||
}, []) | |||||
React.useEffect(() => { | React.useEffect(() => { | ||||
editor.on('selectionUpdate', ({ editor }) => { | editor.on('selectionUpdate', ({ editor }) => { | ||||
const currentFormatList: string[] = [] | const currentFormatList: string[] = [] | ||||
@@ -312,6 +319,47 @@ const MailToolbar: React.FC<Props> = ({ | |||||
<FormatAlignRightIcon /> | <FormatAlignRightIcon /> | ||||
</ToggleButton> | </ToggleButton> | ||||
</ToggleButtonGroup> | </ToggleButtonGroup> | ||||
<ToggleButtonGroup | |||||
sx={{ marginTop: 2 }} | |||||
> | |||||
<ToggleButton id="insertTable" value="insertTable" onClick={() => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()}> | |||||
<GridOnIcon />{t("Insert Table")} | |||||
</ToggleButton> | |||||
<ToggleButton id="deleteTable" value="deleteTable" onClick={() => editor.chain().focus().deleteTable().run()}>{t("Delete table")}</ToggleButton> | |||||
<ToggleButton id="addColumnBefore" value="addColumnBefore" onClick={() => editor.chain().focus().addColumnBefore().run()}> | |||||
{t("Add column before")} | |||||
</ToggleButton> | |||||
<ToggleButton id="addColumnAfter" value="addColumnAfter" onClick={() => editor.chain().focus().addColumnAfter().run()}>{t("Add column after")}</ToggleButton> | |||||
<ToggleButton id="deleteColumn" value="deleteColumn" onClick={() => editor.chain().focus().deleteColumn().run()}>{t("Delete column")}</ToggleButton> | |||||
<ToggleButton id="addRowBefore" value="addRowBefore" onClick={() => editor.chain().focus().addRowBefore().run()}>{t("Add row before")}</ToggleButton> | |||||
<ToggleButton id="addRowAfter" value="addRowAfter" onClick={() => editor.chain().focus().addRowAfter().run()}>{t("Add row after")}</ToggleButton> | |||||
<ToggleButton id="deleteRow" value="deleteRow" onClick={() => editor.chain().focus().deleteRow().run()}>{t("Delete row")}</ToggleButton> | |||||
<ToggleButton id="mergeCells" value="mergeCells" onClick={() => editor.chain().focus().mergeCells().run()}>{t("Merge cells")}</ToggleButton> | |||||
<ToggleButton id="splitCell" value="splitCell" onClick={() => editor.chain().focus().splitCell().run()}>{t("Split cell")}</ToggleButton> | |||||
</ToggleButtonGroup> | |||||
<ToggleButtonGroup | |||||
// sx={{ marginLeft: 2 }} | |||||
> | |||||
<ToggleButton id="toggleHeaderColumn" value="toggleHeaderColumn" onClick={() => editor.chain().focus().toggleHeaderColumn().run()}> | |||||
{t("Toggle header column")} | |||||
</ToggleButton> | |||||
<ToggleButton id="toggleHeaderRow" value="toggleHeaderRow" onClick={() => editor.chain().focus().toggleHeaderRow().run()}> | |||||
{t("Toggle header row")} | |||||
</ToggleButton> | |||||
<ToggleButton id="toggleHeaderCell" value="toggleHeaderCell" onClick={() => editor.chain().focus().toggleHeaderCell().run()}> | |||||
{t("Toggle header cell")} | |||||
</ToggleButton> | |||||
<ToggleButton id="mergeOrSplit" value="mergeOrSplit" onClick={() => editor.chain().focus().mergeOrSplit().run()}>{t("Merge or split")}</ToggleButton> | |||||
<ToggleButton id="setCellAttribute" value="setCellAttribute" onClick={() => editor.chain().focus().setCellAttribute('colspan', 2).run()}> | |||||
{t("Set cell attribute")} | |||||
</ToggleButton> | |||||
<ToggleButton id="fixTables" value="fixTables" onClick={() => editor.chain().focus().fixTables().run()}>{t("Fix tables")}</ToggleButton> | |||||
<ToggleButton id="goToNextCell" value="goToNextCell" onClick={() => editor.chain().focus().goToNextCell().run()}>{t("Go to next cell")}</ToggleButton> | |||||
<ToggleButton id="goToPreviousCell" value="goToPreviousCell" onClick={() => editor.chain().focus().goToPreviousCell().run()}> | |||||
{t("Go to previous cell")} | |||||
</ToggleButton> | |||||
</ToggleButtonGroup> | |||||
</Grid> | </Grid> | ||||
); | ); | ||||
}; | }; | ||||
@@ -5,7 +5,7 @@ import Close from "@mui/icons-material/Close"; | |||||
import Button from "@mui/material/Button"; | import Button from "@mui/material/Button"; | ||||
import Stack from "@mui/material/Stack"; | import Stack from "@mui/material/Stack"; | ||||
import { useRouter } from "next/navigation"; | import { useRouter } from "next/navigation"; | ||||
import React, { useCallback, useState } from "react"; | |||||
import React, { useCallback, useContext, useEffect, useState } from "react"; | |||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import { | import { | ||||
FieldErrors, | FieldErrors, | ||||
@@ -20,6 +20,10 @@ import { Error } from "@mui/icons-material"; | |||||
import { MailSave, saveMail, testEveryone, test7th, test15th, testSendMail } from "@/app/api/mail/actions"; | import { MailSave, saveMail, testEveryone, test7th, test15th, testSendMail } from "@/app/api/mail/actions"; | ||||
import SettingDetails from "./SettingDetails"; | import SettingDetails from "./SettingDetails"; | ||||
import { errorDialog, submitDialog, successDialog } from "../Swal/CustomAlerts"; | import { errorDialog, submitDialog, successDialog } from "../Swal/CustomAlerts"; | ||||
import { MailTemplate } from "@/app/api/mail"; | |||||
import TemplateDetails from "./TemplateDetails"; | |||||
import QrCodeScanner from "../QrCodeScanner/QrCodeScanner"; | |||||
import { QcCodeScannerContext, useQcCodeScanner } from "../QrCodeScannerProvider/QrCodeScannerProvider"; | |||||
export interface Props { | export interface Props { | ||||
defaultInputs?: MailSave, | defaultInputs?: MailSave, | ||||
@@ -34,10 +38,10 @@ const hasErrorsInTab = ( | |||||
return ( | return ( | ||||
errors.settings | errors.settings | ||||
); | ); | ||||
// case 1: | |||||
// return ( | |||||
// errors.template | |||||
// ); | |||||
case 1: | |||||
return ( | |||||
errors.templates | |||||
); | |||||
default: | default: | ||||
false; | false; | ||||
} | } | ||||
@@ -134,6 +138,17 @@ const MailSetting: React.FC<Props> = ({ | |||||
const errors = formProps.formState.errors; | const errors = formProps.formState.errors; | ||||
const scanner = useQcCodeScanner() | |||||
useEffect(() => { | |||||
scanner.startScan() | |||||
}, []) | |||||
console.log("test", scanner.values) | |||||
if (scanner.values.length > 3) { | |||||
console.log("test", scanner.values) | |||||
scanner.resetScan() | |||||
scanner.stopScan() | |||||
} | |||||
return ( | return ( | ||||
<FormProvider {...formProps}> | <FormProvider {...formProps}> | ||||
<Stack | <Stack | ||||
@@ -161,17 +176,18 @@ const MailSetting: React.FC<Props> = ({ | |||||
} | } | ||||
iconPosition="end" | iconPosition="end" | ||||
/> | /> | ||||
{/* <Tab | |||||
label={t("Timesheet Template")} | |||||
<Tab | |||||
label={t("Template")} | |||||
icon={ | icon={ | ||||
hasErrorsInTab(1, errors) ? ( | hasErrorsInTab(1, errors) ? ( | ||||
<Error sx={{ marginInlineEnd: 1 }} color="error" /> | <Error sx={{ marginInlineEnd: 1 }} color="error" /> | ||||
) : undefined | ) : undefined | ||||
} | } | ||||
iconPosition="end" | iconPosition="end" | ||||
/> */} | |||||
/> | |||||
</Tabs> | </Tabs> | ||||
<SettingDetails isActive={tabIndex === 0}/> | <SettingDetails isActive={tabIndex === 0}/> | ||||
<TemplateDetails isActive={tabIndex === 1} /> | |||||
{/* <TimesheetMailDetails isActive={tabIndex === 1} /> */} | {/* <TimesheetMailDetails isActive={tabIndex === 1} /> */} | ||||
<Stack direction="row" justifyContent="flex-end" gap={1}> | <Stack direction="row" justifyContent="flex-end" gap={1}> | ||||
@@ -1,7 +1,7 @@ | |||||
// import { fetchUserAbilities } from "@/app/utils/fetchUtil"; | // import { fetchUserAbilities } from "@/app/utils/fetchUtil"; | ||||
import MailSetting from "./MailSetting"; | import MailSetting from "./MailSetting"; | ||||
import MailSettingLoading from "./MailSettingLoading"; | import MailSettingLoading from "./MailSettingLoading"; | ||||
import { fetchMailSetting } from "@/app/api/mail"; | |||||
import { fetchMailSetting, fetchMailTemplates } from "@/app/api/mail"; | |||||
interface SubComponents { | interface SubComponents { | ||||
Loading: typeof MailSettingLoading; | Loading: typeof MailSettingLoading; | ||||
@@ -11,10 +11,12 @@ const MailSettingWrapper: React.FC & SubComponents = async () => { | |||||
const [ | const [ | ||||
// abilities, | // abilities, | ||||
settings, | settings, | ||||
templates, | |||||
// timesheetTemplate, | // timesheetTemplate, | ||||
] = await Promise.all([ | ] = await Promise.all([ | ||||
// fetchUserAbilities(), | // fetchUserAbilities(), | ||||
fetchMailSetting(), | fetchMailSetting(), | ||||
fetchMailTemplates(), | |||||
// fetchMailTimesheetTemplate() | // fetchMailTimesheetTemplate() | ||||
]); | ]); | ||||
@@ -28,6 +30,7 @@ const MailSettingWrapper: React.FC & SubComponents = async () => { | |||||
<MailSetting | <MailSetting | ||||
defaultInputs={{ | defaultInputs={{ | ||||
settings: settings, | settings: settings, | ||||
templates: templates, | |||||
// template: tempTimesheetTemplate, | // template: tempTimesheetTemplate, | ||||
}} | }} | ||||
/> | /> | ||||
@@ -55,7 +55,7 @@ const SettingDetails: React.FC<Props> = ({ isActive }) => { | |||||
fields.map((field, index) => ( | fields.map((field, index) => ( | ||||
<Grid container key={"row-" + index} justifyContent="flex-start" alignItems="center" spacing={2} columns={{ xs: 6, sm: 12 }} sx={{ mt: 1 }}> | <Grid container key={"row-" + index} justifyContent="flex-start" alignItems="center" spacing={2} columns={{ xs: 6, sm: 12 }} sx={{ mt: 1 }}> | ||||
<Grid item key={"col-1-" + index} xs={4}> | <Grid item key={"col-1-" + index} xs={4}> | ||||
<Typography variant="body2">{t(field.name)}</Typography> | |||||
<Typography variant="body2">{`${t(field.name)}${requiredFields.some(name => field.name.toLowerCase().includes(name)) ? "*" : ""}`}</Typography> | |||||
</Grid> | </Grid> | ||||
{ | { | ||||
field.name.toLowerCase().includes("password") === true ? | field.name.toLowerCase().includes("password") === true ? | ||||
@@ -0,0 +1,239 @@ | |||||
"use client"; | |||||
import Stack from "@mui/material/Stack"; | |||||
import Box from "@mui/material/Box"; | |||||
import Card from "@mui/material/Card"; | |||||
import CardContent from "@mui/material/CardContent"; | |||||
import Grid from "@mui/material/Grid"; | |||||
import TextField from "@mui/material/TextField"; | |||||
import Typography from "@mui/material/Typography"; | |||||
import { useTranslation } from "react-i18next"; | |||||
import { Controller, useFieldArray, useFormContext } from "react-hook-form"; | |||||
import Link from "next/link"; | |||||
import React, { SyntheticEvent, useCallback, useMemo, useState } from "react"; | |||||
import MailField from "../MailField/MailField"; | |||||
import { MailSave } from "@/app/api/mail/actions"; | |||||
import { MailTemplate } from "@/app/api/mail"; | |||||
import { isEmpty, keys } from "lodash"; | |||||
import { Autocomplete, ListSubheader, MenuItem, UseAutocompleteProps } from "@mui/material"; | |||||
interface Props { | |||||
isActive: boolean; | |||||
} | |||||
interface OptionType { | |||||
value: number, | |||||
label: string, | |||||
group: string, | |||||
} | |||||
type fieldKeys = keyof MailTemplate | |||||
const TemplateDetails: React.FC<Props> = ({ isActive }) => { | |||||
const { t } = useTranslation(); | |||||
// const disabledFields: fieldKeys[] = [] | |||||
// const requiredFields: fieldKeys[] = [] | |||||
// const skipFields: fieldKeys[] = ["code", "subjectEng", "contentEng"] | |||||
const [selectedIndex, setSelectedIndex] = useState(0) | |||||
const { | |||||
register, | |||||
formState: { errors }, | |||||
control, | |||||
watch, | |||||
getValues | |||||
} = useFormContext<MailSave>(); | |||||
const { | |||||
fields, | |||||
} = useFieldArray({ | |||||
control, | |||||
name: "templates" | |||||
}) | |||||
const options: OptionType[] = useMemo(() => ( | |||||
fields.map((field, index) => { | |||||
return { | |||||
value: index, | |||||
label: `${field.code} - ${field.description}`, | |||||
group: field.type | |||||
} as OptionType | |||||
}) | |||||
), [fields]) | |||||
const makeAutocompleteChangeHandler = useCallback(() => { | |||||
return (e: SyntheticEvent, newValue: OptionType) => { | |||||
setSelectedIndex(() => newValue.value); | |||||
}; | |||||
}, []); | |||||
// const renderFieldsBySwitchCases = useCallback(() => { | |||||
// const fieldNames = keys(fields[0]) as fieldKeys[]; | |||||
// return fieldNames | |||||
// .filter((name) => !skipFields.includes(name)) | |||||
// .map((name: fieldKeys, index: number) => { | |||||
// switch (name) { | |||||
// case "contentCht": | |||||
// return ( | |||||
// <Grid item xs={12}> | |||||
// <Controller | |||||
// control={control} | |||||
// name={`templates.${selectedIndex}.contentCht`} | |||||
// render={({ field }) => ( | |||||
// <MailField | |||||
// content={field.value} | |||||
// onChange={field.onChange} | |||||
// error={Boolean(errors.templates?.[selectedIndex]?.contentCht)} | |||||
// /> | |||||
// )} | |||||
// rules={{ | |||||
// required: requiredFields.includes(name), | |||||
// }} | |||||
// /> | |||||
// </Grid> | |||||
// ) | |||||
// default: | |||||
// return ( | |||||
// <Grid item xs={8}> | |||||
// <TextField | |||||
// label={t(name)} | |||||
// fullWidth | |||||
// {...register(`templates.${selectedIndex}.cc`), | |||||
// { | |||||
// required: requiredFields.includes(name) | |||||
// }} | |||||
// /> | |||||
// </Grid> | |||||
// ) | |||||
// } | |||||
// }) | |||||
// }, [fields]) | |||||
return ( | |||||
<Card sx={{ display: isActive ? "block" : "none" }}> | |||||
<CardContent component={Stack} spacing={4}> | |||||
<Box> | |||||
<Typography variant="overline" display="block" marginBlockEnd={1}> | |||||
{t("Template")} | |||||
</Typography> | |||||
<Grid container spacing={2} columns={{ xs: 6, sm: 12 }}> | |||||
<Grid item xs={8}> | |||||
<Autocomplete | |||||
disableClearable | |||||
options={options} | |||||
value={options[selectedIndex]} | |||||
onChange={makeAutocompleteChangeHandler} | |||||
groupBy={(option) => ( | |||||
option.group && option.group.trim() !== '' ? option.group : 'Ungrouped' | |||||
)} | |||||
renderGroup={(params) => ( | |||||
<React.Fragment> | |||||
<ListSubheader>{params.group}</ListSubheader> | |||||
{params.children} | |||||
</React.Fragment> | |||||
)} | |||||
renderOption={( | |||||
params: React.HTMLAttributes<HTMLLIElement> & { key?: React.Key }, | |||||
option, | |||||
{ selected }, | |||||
) => { | |||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | |||||
const { key, ...rest } = params; | |||||
return ( | |||||
<MenuItem | |||||
{...rest} | |||||
disableRipple | |||||
value={option.value} | |||||
> | |||||
{option.label} | |||||
</MenuItem> | |||||
); | |||||
}} | |||||
renderInput={(params) => <TextField {...params} variant="outlined" label={t("Select Template (View By Code - Description)")} />} | |||||
/> | |||||
</Grid> | |||||
<Grid item xs={8}> | |||||
<TextField | |||||
label={t("Code")} | |||||
fullWidth | |||||
{...register(`templates.${selectedIndex}.code`, { | |||||
required: "Code is required!" | |||||
})} | |||||
required | |||||
error={Boolean(errors.templates?.[selectedIndex]?.code)} | |||||
/> | |||||
</Grid> | |||||
<Grid item xs={8}> | |||||
<TextField | |||||
label={t("Description")} | |||||
fullWidth | |||||
{...register(`templates.${selectedIndex}.description`, { | |||||
required: "Description is required!" | |||||
})} | |||||
required | |||||
error={Boolean(errors.templates?.[selectedIndex]?.description)} | |||||
/> | |||||
</Grid> | |||||
{/* <Grid item xs={8}> | |||||
<TextField | |||||
label={t("To")} | |||||
fullWidth | |||||
{...register(`templates.${selectedIndex}.to`, { | |||||
required: "To is required!" | |||||
})} | |||||
required | |||||
error={Boolean(errors.templates?.[selectedIndex]?.to)} | |||||
/> | |||||
</Grid> | |||||
<Grid item xs={8}> | |||||
<TextField | |||||
label={t("Cc")} | |||||
fullWidth | |||||
{...register(`templates.${selectedIndex}.cc`)} | |||||
/> | |||||
</Grid> | |||||
<Grid item xs={8}> | |||||
<TextField | |||||
label={t("Required Params (split by ',')")} | |||||
fullWidth | |||||
{...register(`templates.${selectedIndex}.params`)} | |||||
/> | |||||
</Grid> */} | |||||
<Grid item xs={8}> | |||||
<TextField | |||||
label={t("Subject CHT")} | |||||
fullWidth | |||||
{...register(`templates.${selectedIndex}.subjectCht`, | |||||
{ | |||||
required: "Mail Subject is required!", | |||||
})} | |||||
required | |||||
error={Boolean(errors.templates?.[selectedIndex]?.subjectCht)} | |||||
/> | |||||
</Grid> | |||||
<Grid item xs={12}> | |||||
<Controller | |||||
control={control} | |||||
name={`templates.${selectedIndex}.contentCht`} | |||||
render={({ field }) => ( | |||||
<MailField | |||||
content={field.value} | |||||
onChange={field.onChange} | |||||
error={Boolean(errors.templates?.[selectedIndex]?.contentCht)} | |||||
/> | |||||
)} | |||||
rules={{ | |||||
required: "Mail Content is required!", | |||||
}} | |||||
/> | |||||
</Grid> | |||||
</Grid> | |||||
</Box> | |||||
</CardContent> | |||||
</Card> | |||||
); | |||||
}; | |||||
export default TemplateDetails; |