From 49a06a9176e88b8ffa47fe3cffb301fcae01dc39 Mon Sep 17 00:00:00 2001 From: vincent Date: Wed, 18 Jan 2023 17:40:47 +0100 Subject: [PATCH] (ui) Update machines layout --- .../machines/machine-categories-list.tsx | 8 +- .../components/machines/machines-filters.tsx | 23 ++- .../components/machines/machines-list.tsx | 26 +-- .../components/machines/machines-settings.tsx | 153 ++++++++++++++++++ app/frontend/src/stylesheets/application.scss | 3 +- .../modules/machines/machine-categories.scss | 11 ++ .../modules/machines/machines-filters.scss | 62 +++---- .../modules/machines/machines-list.scss | 18 +++ .../modules/machines/machines-settings.scss | 21 +++ .../templates/admin/machines/index.html | 69 ++++---- .../templates/admin/machines/machines.html | 3 +- config/locales/app.admin.en.yml | 10 ++ config/locales/app.public.en.yml | 4 +- 13 files changed, 315 insertions(+), 96 deletions(-) create mode 100644 app/frontend/src/javascript/components/machines/machines-settings.tsx create mode 100644 app/frontend/src/stylesheets/modules/machines/machines-settings.scss diff --git a/app/frontend/src/javascript/components/machines/machine-categories-list.tsx b/app/frontend/src/javascript/components/machines/machine-categories-list.tsx index 408dc588e..9ca66f20a 100644 --- a/app/frontend/src/javascript/components/machines/machine-categories-list.tsx +++ b/app/frontend/src/javascript/components/machines/machine-categories-list.tsx @@ -117,8 +117,12 @@ export const MachineCategoriesList: React.FC = ({ on return (
-

{t('app.admin.machine_categories_list.machine_categories')}

- {t('app.admin.machine_categories_list.add_a_machine_category')} +
+

{t('app.admin.machine_categories_list.machine_categories')}

+
+ {t('app.admin.machine_categories_list.add_a_machine_category')} +
+
= ({ onFilterChange const defaultValue = { value: true, label: t('app.public.machines_filters.status_enabled') }; const categoryDefaultValue = { value: null, label: t('app.public.machines_filters.all_machines') }; + // Styles the React-select component + const customStyles = { + control: base => ({ + ...base, + width: '20ch', + border: 'none', + backgroundColor: 'transparent' + }), + indicatorSeparator: () => ({ + display: 'none' + }) + }; + /** * Provides boolean options in the react-select format (yes/no/all) */ @@ -56,21 +69,23 @@ export const MachinesFilters: React.FC = ({ onFilterChange return (
- +

{t('app.public.machines_filters.show_machines')}

+ options={buildCategoriesOptions()} + styles={customStyles}/>
}
diff --git a/app/frontend/src/javascript/components/machines/machines-list.tsx b/app/frontend/src/javascript/components/machines/machines-list.tsx index e954c56d3..5f324b99e 100644 --- a/app/frontend/src/javascript/components/machines/machines-list.tsx +++ b/app/frontend/src/javascript/components/machines/machines-list.tsx @@ -12,6 +12,8 @@ import { MachinesFilters } from './machines-filters'; import { User } from '../../models/user'; import { useTranslation } from 'react-i18next'; import { FabButton } from '../base/fab-button'; +import { EditorialBlock } from '../base/editorial-block'; +import { CalendarBlank } from 'phosphor-react'; declare const Application: IApplication; @@ -96,30 +98,14 @@ export const MachinesList: React.FC = ({ onError, onSuccess, }); }; - /** - * Go to store - */ - const linkToStore = (): void => { - window.location.href = '/#!/store'; - }; - - // TODO: Conditionally display the store ad return (
+ {/* TODO: Condition to display editorial block */} + {false && + + }
- {false && -
linkToStore}> -
-

{t('app.public.machines_list.store_ad.title')}

-

{t('app.public.machines_list.store_ad.buy')}

-

{t('app.public.machines_list.store_ad.sell')}

-
- } className="cta" onClick={linkToStore}> - {t('app.public.machines_list.store_ad.link')} - -
- } {machines && machines.map(machine => { return void, + onSuccess: (message: string) => void, +} + +/** + * Machines settings + */ +export const MachinesSettings: React.FC = () => { + const { t } = useTranslation('admin'); + const { register, control, formState, handleSubmit } = useForm(); + + // regular expression to validate the input fields + const urlRegex = /^(https?:\/\/)([^.]+)\.(.{2,30})(\/.*)*\/?$/; + + const [isActiveAutoCancellation, setIsActiveAutoCancellation] = useState(false); + const [isActiveAuthorizationValidity, setIsActiveAuthorizationValidity] = useState(false); + const [isActiveTextBlock, setIsActiveTextBlock] = useState(false); + const [isActiveValidationRule, setIsActiveValidationRule] = useState(false); + const [isActiveCta, setIsActiveCta] = useState(false); + + /** + * Callback triggered when the auto cancellation switch has changed. + */ + const toggleAutoCancellation = (value: boolean) => { + setIsActiveAutoCancellation(value); + }; + + /** + * Callback triggered when the authorisation validity switch has changed. + */ + const toggleAuthorizationValidity = (value: boolean) => { + setIsActiveAuthorizationValidity(value); + }; + + /** + * Callback triggered when the authorisation validity switch has changed. + */ + const toggleValidationRule = (value: boolean) => { + setIsActiveValidationRule(value); + }; + + /** + * Callback triggered when the text block switch has changed. + */ + const toggleTextBlockSwitch = (value: boolean) => { + setIsActiveTextBlock(value); + }; + + /** + * Callback triggered when the CTA switch has changed. + */ + const toggleTextBlockCta = (value: boolean) => { + setIsActiveCta(value); + }; + + /** + * Callback triggered when the CTA label has changed. + */ + const handleCtaLabelChange = (event: React.ChangeEvent): void => { + console.log('cta label:', event.target.value); + }; + /** + * Callback triggered when the cta url has changed. + */ + const handleCtaUrlChange = (event: React.ChangeEvent): void => { + console.log('cta url:', event.target.value); + }; + + /** + * Callback triggered when the form is submitted: save the settings + */ + const onSubmit: SubmitHandler = (data) => { + console.log(data); + }; + + return ( +
+
+

{t('app.admin.machines_settings.title')}

+ {t('app.admin.machines_settings.save')} +
+
+
+
+

{t('app.admin.machines_settings.generic_text_block')}

+

{t('app.admin.machines_settings.generic_text_block_info')}

+
+ +
+ + + + + {isActiveTextBlock && <> + + + {isActiveCta && <> + + + } + } +
+
+
+
+ ); +}; + +const MachinesSettingsWrapper: React.FC = (props) => { + return ( + + + + + + ); +}; + +Application.Components.component('machinesSettings', react2angular(MachinesSettingsWrapper, ['onError', 'onSuccess'])); diff --git a/app/frontend/src/stylesheets/application.scss b/app/frontend/src/stylesheets/application.scss index 57b0e297f..6601a45e5 100644 --- a/app/frontend/src/stylesheets/application.scss +++ b/app/frontend/src/stylesheets/application.scss @@ -62,11 +62,12 @@ @import "modules/invoices/vat-settings-modal"; @import "modules/layout/header-page"; @import "modules/machines/machine-card"; +@import "modules/machines/machine-categories"; @import "modules/machines/machine-form"; @import "modules/machines/machines-filters"; @import "modules/machines/machines-list"; +@import "modules/machines/machines-settings"; @import "modules/machines/required-training-modal"; -@import "modules/machines/machine-categories"; @import "modules/payment-schedule/payment-schedule-dashboard"; @import "modules/payment-schedule/payment-schedule-summary"; @import "modules/payment-schedule/payment-schedules-list"; diff --git a/app/frontend/src/stylesheets/modules/machines/machine-categories.scss b/app/frontend/src/stylesheets/modules/machines/machine-categories.scss index 5cbe40062..15d2f803e 100644 --- a/app/frontend/src/stylesheets/modules/machines/machine-categories.scss +++ b/app/frontend/src/stylesheets/modules/machines/machine-categories.scss @@ -1,4 +1,15 @@ .machine-categories-list { + max-width: 1200px; + margin: 0 auto; + padding-bottom: 6rem; + display: flex; + flex-direction: column; + & > header { + padding-bottom: 0; + @include header; + gap: 2.4rem; + } + .buttons { display: flex; justify-content: flex-end; diff --git a/app/frontend/src/stylesheets/modules/machines/machines-filters.scss b/app/frontend/src/stylesheets/modules/machines/machines-filters.scss index 7f5e7a1e5..fba6407bb 100644 --- a/app/frontend/src/stylesheets/modules/machines/machines-filters.scss +++ b/app/frontend/src/stylesheets/modules/machines/machines-filters.scss @@ -1,36 +1,40 @@ .machines-filters { - margin: 1.5em 0; + max-width: 1600px; + width: 100%; + margin: 0 auto; + padding: 0.8rem 2.4rem; display: flex; - justify-content: space-between; + flex-wrap: wrap; + background-color: var(--gray-soft); + border-radius: var(--border-radius); + + @media (min-width: 1024px) { + justify-content: flex-end; + & > *:not(:first-child) { + &::before { + content: ""; + margin: 0 2rem; + width: 1px; + height: 2rem; + background-color: var(--gray-hard-darkest); + } + } + } .filter-item { - &:first-child { - padding-right: 20px; - } - & { - display: block; - width: 50%; - } - & > label { - white-space: nowrap; - line-height: 2em; - } - & > * { - display: inline-block; - } - .status-select, .category-select { - width: 100%; - } + display: flex; + align-items: center; + p { margin: 0 0.8rem 0 0; } } } -@media screen and (max-width: 720px){ - .machines-filters { - display: block; - .filter-item { - padding-right: 0 !important; - display: block; - width: 100%; - } - } -} +//@media screen and (max-width: 720px){ +// .machines-filters { +// display: block; +// .filter-item { +// padding-right: 0 !important; +// display: block; +// width: 100%; +// } +// } +//} diff --git a/app/frontend/src/stylesheets/modules/machines/machines-list.scss b/app/frontend/src/stylesheets/modules/machines/machines-list.scss index 18a368a22..4124d6f16 100644 --- a/app/frontend/src/stylesheets/modules/machines/machines-list.scss +++ b/app/frontend/src/stylesheets/modules/machines/machines-list.scss @@ -1,6 +1,24 @@ .machines-list { + display: flex; + flex-direction: column; + gap: 1.6rem; + + &-container { + max-width: 1600px; + margin: 0 auto; + padding-bottom: 6rem; + display: flex; + flex-direction: column; + & > header { + padding-bottom: 0; + @include header; + gap: 2.4rem; + } + } + .all-machines { max-width: 1600px; + width: 100%; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); diff --git a/app/frontend/src/stylesheets/modules/machines/machines-settings.scss b/app/frontend/src/stylesheets/modules/machines/machines-settings.scss new file mode 100644 index 000000000..d7683c5a7 --- /dev/null +++ b/app/frontend/src/stylesheets/modules/machines/machines-settings.scss @@ -0,0 +1,21 @@ +.machines-settings { + max-width: 1200px; + margin: 0 auto; + padding-bottom: 6rem; + display: flex; + flex-direction: column; + & > header { + padding-bottom: 0; + @include header($sticky: true); + gap: 2.4rem; + } + + &-content { + display: flex; + flex-direction: column; + gap: 3.2rem; + + .settings-section { @include layout-settings; } + .save-btn { align-self: flex-start; } + } +} \ No newline at end of file diff --git a/app/frontend/templates/admin/machines/index.html b/app/frontend/templates/admin/machines/index.html index 4fc9b0eeb..3e9c36fc9 100644 --- a/app/frontend/templates/admin/machines/index.html +++ b/app/frontend/templates/admin/machines/index.html @@ -6,47 +6,44 @@

{{ 'app.admin.machines.the_fablab_s_machines' }}

- -
- -
-
+ -
- + - - - + +
+
+

{{ 'app.admin.machines.all_machines' }}

+ +
+ +
+
- - - + + + - - - - -
-
- -
+
diff --git a/app/frontend/templates/admin/machines/machines.html b/app/frontend/templates/admin/machines/machines.html index 1d59dd4de..fb4bc217e 100644 --- a/app/frontend/templates/admin/machines/machines.html +++ b/app/frontend/templates/admin/machines/machines.html @@ -1,5 +1,4 @@ -