From f1bdf439c838810c890ed031ecbabb285a9bc076 Mon Sep 17 00:00:00 2001 From: NatSquared Date: Tue, 24 Sep 2024 14:29:09 -0700 Subject: [PATCH] Undo changes to AuthoringFeedback.tsx --- .../create/authoring/AuthoringFeedback.tsx | 403 +++++++++++++----- .../admin/create/authoring/types.ts | 7 + 2 files changed, 302 insertions(+), 108 deletions(-) diff --git a/met-web/src/components/engagement/admin/create/authoring/AuthoringFeedback.tsx b/met-web/src/components/engagement/admin/create/authoring/AuthoringFeedback.tsx index f61093cdc..488d60441 100644 --- a/met-web/src/components/engagement/admin/create/authoring/AuthoringFeedback.tsx +++ b/met-web/src/components/engagement/admin/create/authoring/AuthoringFeedback.tsx @@ -1,21 +1,239 @@ -import { Grid, MenuItem, Select, SelectChangeEvent } from '@mui/material'; +// import React from 'react'; +// export const AuthoringFeedback = () => { +// return
AuthoringFeedback
; +// }; +// export default AuthoringFeedback; + +import { Grid, IconButton, MenuItem, Select, SelectChangeEvent, Tab, Tabs } from '@mui/material'; import { EyebrowText as FormDescriptionText } from 'components/common/Typography'; import { colors, MetLabel, MetHeader3, MetLabel as MetBigLabel } from 'components/common'; import { Button, TextField } from 'components/common/Input'; +import React, { SyntheticEvent, useState } from 'react'; import { RichTextArea } from 'components/common/Input/RichTextArea'; -import { EditorState } from 'draft-js'; -import React, { useState } from 'react'; +import { AuthoringTemplateOutletContext, DetailsTabProps, TabValues } from './types'; +import { useOutletContext } from 'react-router-dom'; import { Palette } from 'styles/Theme'; +import { Unless, When } from 'react-if'; +import { TabContext, TabPanel } from '@mui/lab'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faX } from '@fortawesome/pro-regular-svg-icons'; +import { EditorState } from 'draft-js'; + +const handleDuplicateTabNames = (newTabs: TabValues[], newTabName: string) => { + // Will add a sequencial number suffix for up to 10 numbers if there is a duplicate, then add (copy) if none of those are available. + for (let i = 2; i < 12; i++) { + if (!newTabs.find((tab) => tab.heading === `${newTabName} (${i})`)) { + return `${newTabName} (${i})`; + } + } + return `${newTabName} (copy)`; +}; + +const AuthoringDetails = () => { + const { + setValue, + contentTabsEnabled, + tabs, + setTabs, + setSingleContentValues, + setContentTabsEnabled, + singleContentValues, + defaultTabValues, + }: AuthoringTemplateOutletContext = useOutletContext(); // Access the form functions and values from the authoring template + const [currentTab, setCurrentTab] = useState(tabs[0]); + + const tabsStyles = { + borderBottom: `2px solid ${colors.surface.gray[60]}`, + overflow: 'hidden', + '& .MuiTabs-flexContainer': { + justifyContent: 'flex-start', + width: 'max-content', + }, + }; + const tabStyles = { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '48px', + padding: '4px 18px 2px 18px', + fontSize: '14px', + borderRadius: '0px 16px 0px 0px', + border: `1px solid ${colors.surface.gray[60]}`, + borderBottom: 'none', + boxShadow: + '0px 2px 5px 0px rgba(0, 0, 0, 0.12), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 3px 1px -2px rgba(0, 0, 0, 0.20)', + backgroundColor: 'gray.10', + color: 'text.secondary', + fontWeight: 'normal', + '&.Mui-selected': { + backgroundColor: 'primary.main', + borderColor: 'primary.main', + color: 'white', + fontWeight: 'bold', + }, + outlineOffset: '-4px', + '&:focus-visible': { + outline: `2px solid`, + outlineColor: '#12508F', + border: '4px solid', + borderColor: '#12508F', + padding: '0px 20px 0px 14px', + }, + }; + + const handleCloseTab = (e: React.MouseEvent, tab: TabValues) => { + e.stopPropagation(); + const index = tabs.findIndex((t) => t.heading === tab.heading); + if (-1 < index) { + const newTabs = [...tabs]; + newTabs.splice(index, 1); + if (1 === newTabs.length) { + // If we're switching back to single content mode + 'Tab 1' !== tabs[0].heading + ? setSingleContentValues(tabs[0]) + : setSingleContentValues({ ...tabs[0], heading: '' }); // If the current Section Heading is "Tab 1" then change it to a blank value. + setTabs([tabs[0]]); + setContentTabsEnabled('false'); + } else { + setTabs(newTabs); + tab === currentTab && setCurrentTab(newTabs[index - 1]); // Switch tabs if you're closing the current one + } + } + }; -const AuthoringFeedback = () => { - const [sectionHeading, setSectionHeading] = useState(''); - // const [bodyText, setBodyText] = useState(''); - const [editorState, setEditorState] = useState(); - const [surveyButtonText, setSurveyButtonText] = useState(''); - const [thirdPartyCtaText, setThirdPartyCtaText] = useState(''); - const [thirdPartyCtaLink, setThirdPartyCtaLink] = useState(''); - const [currentWidget, setCurrentWidget] = useState(''); + const handleAddTab = () => { + const newTabs = [...tabs]; + const newTabName = 'Tab ' + (newTabs.length + 1); + newTabs.find((tab) => newTabName === tab.heading) + ? newTabs.push({ ...defaultTabValues, heading: handleDuplicateTabNames(newTabs, newTabName) }) + : newTabs.push({ ...defaultTabValues, heading: newTabName }); // Don't create duplicate entries + setTabs(newTabs); + setCurrentTab(newTabs[newTabs.length - 1]); + }; + return ( + + + + tab.heading === currentTab.heading) + ? tabs[tabs.findIndex((t) => t.heading === currentTab.heading)].heading + : tabs[tabs.length - 1].heading + } + > + tab.heading === currentTab.heading) + ? tabs[tabs.findIndex((t) => t.heading === currentTab.heading)].heading + : tabs[tabs.length - 1].heading + } + onChange={(event: SyntheticEvent, value: string) => + tabs.find((tab) => tab.heading === value) && + setCurrentTab(tabs[tabs.findIndex((tab) => tab.heading === value)]) + } + > + {tabs.map((tab, key) => { + return ( + + {tab.heading} + + handleCloseTab(e, tab)} + > + + + + + } + key={key} + value={tab.heading} + disableFocusRipple + /> + ); + })} + + + {tabs.map((tab, key) => { + return ( + + + + ); + })} + + + + + + + + ); +}; + +export default AuthoringDetails; + +const DetailsTab = ({ + // setValue, + setTabs, + setCurrentTab, + setSingleContentValues, + tabs, + tabIndex, + singleContentValues, + defaultTabValues, +}: DetailsTabProps) => { // Define the styles const metBigLabelStyles = { fontSize: '1.05rem', @@ -40,13 +258,15 @@ const AuthoringFeedback = () => { const metLabelStyles = { fontSize: '0.95rem', }; - const buttonStyles = { - height: '2.6rem', + const conditionalSelectStyles = { + width: '100%', + backgroundColor: colors.surface.white, borderRadius: '8px', - border: 'none', - padding: '0 1rem', - minWidth: '8.125rem', - fontSize: '0.9rem', + boxShadow: '0 0 0 1px #7A7876 inset', + lineHeight: '1.4375em', + height: '48px', + marginTop: '8px', + padding: '0', }; const widgetPreviewStyles = { margin: '2rem 4rem 4rem', @@ -57,16 +277,15 @@ const AuthoringFeedback = () => { justifyContent: 'center', borderRadius: '16px', }; - const conditionalSelectStyles = { - width: '100%', - backgroundColor: colors.surface.white, + const buttonStyles = { + height: '2.6rem', borderRadius: '8px', - boxShadow: '0 0 0 1px #7A7876 inset', - lineHeight: '1.4375em', - height: '48px', - marginTop: '8px', - padding: '0', + border: 'none', + padding: '0 1rem', + minWidth: '8.125rem', + fontSize: '0.9rem', }; + const toolbar = { options: ['inline', 'list', 'link', 'blockType', 'history'], inline: { @@ -76,31 +295,57 @@ const AuthoringFeedback = () => { list: { options: ['unordered', 'ordered'] }, }; - const handleEditorChange = (newEditorState: EditorState) => { - setEditorState(newEditorState); - // const plainText = newEditorState.getCurrentContent().getPlainText(); - // setBodyText(plainText); + const handleSectionHeadingChange = (value: string) => { + const newHeading = value; + if (2 > tabs.length && 0 === tabIndex) { + // If there are no tabs + setSingleContentValues({ ...singleContentValues, heading: newHeading }); + setTabs([{ ...defaultTabValues, heading: newHeading }]); + } else { + // If there are tabs + const newTabs = [...tabs]; + newTabs[tabIndex].heading = newTabs.find((tab) => tab.heading === newHeading) + ? handleDuplicateTabNames(newTabs, newHeading) + : newHeading; // If the new name is the same as an existing one, rename it + setSingleContentValues(newTabs[0]); + setTabs([...newTabs]); + setCurrentTab(newTabs[tabIndex]); + } }; const handleWidgetChange = (event: SelectChangeEvent) => { - setCurrentWidget(event.target.value); + const newWidget = event.target.value; + const newTabs = [...tabs]; + newTabs[tabIndex].widget = newWidget; + setTabs(newTabs); }; const handleRemoveWidget = () => { - if ('' === currentWidget) { + if ('' === tabs[tabIndex].widget) { return; } else { - setCurrentWidget(''); + const newTabs = [...tabs]; + newTabs[tabIndex].widget = ''; + setTabs(newTabs); } }; + const handleBodyTextChange = (newEditorState: EditorState) => { + const plainText = newEditorState.getCurrentContent().getPlainText(); + const newTabs = [...tabs]; + newTabs[tabIndex].bodyCopyEditorState = newEditorState; + newTabs[tabIndex].bodyCopyPlainText = plainText; + setTabs(newTabs); + }; + return ( Primary Content (Required) - This section of content should provide a brief overview of what your engagement is about and what - you would like your audience to do. + Primary content will display on the left two thirds of the page on large screens and full width on + small screens. (If you add optional supporting content in the section below, on small screens, your + primary content will display first (on top) followed by your supporting content (underneath). @@ -114,36 +359,39 @@ const AuthoringFeedback = () => { { - setSectionHeading(value); - }} + onChange={handleSectionHeadingChange} /> - - - - - - - - - - Supporting Content (Optional) @@ -228,7 +417,7 @@ const AuthoringFeedback = () => { sx={{ ...conditionalSelectStyles, maxWidth: '300px' }} id="widget_select" onChange={handleWidgetChange} - value={currentWidget} + value={tabs[tabIndex].widget} > Video Other @@ -246,7 +435,7 @@ const AuthoringFeedback = () => { item > - {currentWidget} {currentWidget && 'Widget'} + {tabs[tabIndex].widget} {tabs[tabIndex].widget && 'Widget'} {/* todo: show a preview of the widget here */} @@ -284,5 +473,3 @@ const AuthoringFeedback = () => { ); }; - -export default AuthoringFeedback; diff --git a/met-web/src/components/engagement/admin/create/authoring/types.ts b/met-web/src/components/engagement/admin/create/authoring/types.ts index 2407013a7..35d100254 100644 --- a/met-web/src/components/engagement/admin/create/authoring/types.ts +++ b/met-web/src/components/engagement/admin/create/authoring/types.ts @@ -62,6 +62,13 @@ export interface AuthoringTemplateOutletContext { setDefaultValues: Dispatch>; fetcher: FetcherWithComponents; pageName: string; + contentTabsEnabled: string; + tabs: TabValues[]; + setTabs: Dispatch>; + setSingleContentValues: Dispatch>; + setContentTabsEnabled: Dispatch>; + singleContentValues: TabValues; + defaultTabValues: TabValues; } export interface DetailsTabProps {