Skip to content

Commit

Permalink
fix(frontend): fix select opacity on Chrome; add an empty option
Browse files Browse the repository at this point in the history
  • Loading branch information
Falinor committed Feb 4, 2025
1 parent a6c280e commit d8b2083
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 15 deletions.
1 change: 1 addition & 0 deletions frontend/src/App.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@use "reset";
@use "colors";
@use "dsfr-fix";
@use "src/components/Map/housing-popup-overrides";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,6 @@ function HousingEditionSideMenu(props: HousingEditionSideMenuProps) {
label="Sous-statut de suivi"
name="subStatus"
multiple={false}
value={subStatusDisabled ? null : form.getValues().subStatus}
options={
getSubStatusOptions(statusField.value as HousingStatus) ?? []
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRef, useState } from 'react';
import { useId, useRef, useState } from 'react';
import classNames from 'classnames';
import { useOutsideClick } from '../../hooks/useOutsideClick';
import { SelectOption } from '../../models/SelectOption';
Expand Down Expand Up @@ -34,16 +34,21 @@ const HousingStatusSelect = ({
setShowOptions(false);
};

const inputId = useId();

return (
<div className="select-single-input" ref={wrapperRef}>
<div
className={classNames({
[`fr-select-group--${messageType}`]: messageType
})}
>
<label className="fr-label">Statut de suivi</label>
<label className="fr-label" htmlFor={inputId}>
Statut de suivi
</label>
<button
className="fr-select"
id={inputId}
title={showOptions ? 'Masquer les options' : 'Afficher les options'}
onClick={() => setShowOptions(!showOptions)}
>
Expand Down
42 changes: 31 additions & 11 deletions frontend/src/components/_app/AppSelect/AppSelectNext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ import {
MenuItem,
Select as MuiSelect
} from '@mui/material';
import classNames from 'classnames';
import { useId } from 'react';
import { useController } from 'react-hook-form';
import { noop } from 'ts-essentials';
import { match, Pattern } from 'ts-pattern';
import { useController } from 'react-hook-form';

import styles from './app-select-next.module.scss';

interface Option<Value> {
id?: string;
Expand Down Expand Up @@ -48,26 +51,36 @@ function AppSelectNext<Value extends string, Multiple extends boolean = false>(
});

const isControlled = props.value !== undefined;
const value: SelectValue<Value, Multiple> = isControlled
? props.value
: field.value;
const value: SelectValue<Value, Multiple> =
props.options.length === 0 ? '' : isControlled ? props.value : field.value;
const onChange = isControlled ? props.onChange : field.onChange;

return (
<Box>
<Box
className={classNames(
fr.cx('fr-select-group', {
[fr.cx('fr-select-group--disabled')]: props.disabled
})
)}
>
<label className="fr-label" id={labelId}>
{props.label}
</label>
<MuiSelect
classes={{
root: fr.cx('fr-mt-1w'),
select: fr.cx('fr-select', 'fr-pt-1w', 'fr-pr-5w'),
select: classNames(
fr.cx('fr-select', 'fr-pt-1w', 'fr-pr-5w', {
[styles.selectDisabled]: props.disabled
})
),
icon: fr.cx('fr-hidden')
}}
disabled={props.disabled}
disableUnderline
displayEmpty
label={props.label}
id={selectId}
fullWidth
labelId={labelId}
multiple={multiple}
MenuProps={{
Expand All @@ -78,9 +91,13 @@ function AppSelectNext<Value extends string, Multiple extends boolean = false>(
elevation: 0,
marginThreshold: null,
disableScrollLock: true,
sx: {
filter: 'drop-shadow(var(--raised-shadow))',
maxHeight: '40rem'
slotProps: {
paper: {
sx: {
filter: 'drop-shadow(var(--raised-shadow))',
maxHeight: '13.125rem'
}
}
},
transformOrigin: {
vertical: 'top',
Expand All @@ -90,6 +107,10 @@ function AppSelectNext<Value extends string, Multiple extends boolean = false>(
}}
native={false}
renderValue={(values) => {
if (values === '') {
return 'Sélectionnez une option';
}

return match(values)
.with(Pattern.string, (value) => {
return props.options.find((option) => option.value === value)
Expand All @@ -106,7 +127,6 @@ function AppSelectNext<Value extends string, Multiple extends boolean = false>(
})
.otherwise(() => '');
}}
sx={{ width: '100%' }}
value={value ?? ''}
variant="standard"
onChange={onChange}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.selectDisabled {
cursor: not-allowed;
color: var(--text-disabled-grey);
box-shadow: inset 0 -2px 0 0 var(--border-disabled-grey);
--data-uri-svg: url(data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 24 24' ><path fill='%23929292' d='M12,13.1l5-4.9l1.4,1.4L12,15.9L5.6,9.5l1.4-1.4L12,13.1z'/></svg>);
background-image: var(--data-uri-svg);
}
5 changes: 5 additions & 0 deletions frontend/src/reset.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
input:disabled,
select:disabled,
option:disabled {
opacity: 1;
}
36 changes: 35 additions & 1 deletion frontend/src/views/Housing/test/HousingView.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,41 @@ describe('Housing view', () => {
expect(newOccupancy).toHaveTextContent(/En location/i);
});

it('should update the status', async () => {
renderView(housing);

const [update] = await screen.findAllByRole('button', {
name: /Mettre à jour/
});
await user.click(update);
const mobilizationTab = await screen.findByRole('tab', {
name: 'Mobilisation'
});
await user.click(mobilizationTab);
const mobilizationPanel = await screen.findByRole('tabpanel', {
name: 'Mobilisation'
});
const status =
await within(mobilizationPanel).findByLabelText(/Statut de suivi/);
await user.click(status);
const statusOption = await screen.findByLabelText(/Premier contact/);
await user.click(statusOption);
const subStatus =
await within(mobilizationPanel).findByLabelText(/Sous-statut/);
await user.click(subStatus);
screen.logTestingPlaygroundURL();
const subStatusOption = await screen.findByRole('option', {
name: 'En pré-accompagnement'
});
await user.click(subStatusOption);
const save = await screen.findByRole('button', {
name: 'Enregistrer'
});
await user.click(save);
const mobilization = await screen.findByText('Premier contact');
expect(mobilization).toBeVisible();
});

it('should create a note', async () => {
renderView(housing);

Expand Down Expand Up @@ -280,7 +315,6 @@ describe('Housing view', () => {
const panel = await screen.findByRole('tabpanel', {
name: 'Historique de suivi'
});
screen.logTestingPlaygroundURL();
const note = await within(panel).findByText('Note');
expect(note).toBeVisible();
});
Expand Down

0 comments on commit d8b2083

Please sign in to comment.