Skip to content

Commit

Permalink
Merge pull request #330 from ReseauEntourage/feature/EN-7353-LinkedIn…
Browse files Browse the repository at this point in the history
…-et-CV-visibles-Onboarding

[EN-7353] linked in et cv visibles onboarding
  • Loading branch information
guillobits authored Sep 19, 2024
2 parents f0ff545 + becfc5f commit 47d3f68
Show file tree
Hide file tree
Showing 20 changed files with 366 additions and 58 deletions.
1 change: 1 addition & 0 deletions src/components/backoffice/onboarding/Onboarding.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ export const parseOnboadingProfileFields = (
helpOffers: fields.helpOffers?.map((help) => {
return { name: help };
}),
linkedinUrl: fields.linkedinUrl ? fields.linkedinUrl : undefined,
};
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { FormSchema } from 'src/components/forms/FormSchema';
import {
FileTypes,
FormComponents,
FormSchema,
} from 'src/components/forms/FormSchema';
import { BUSINESS_LINES, BusinessLineValue } from 'src/constants';
import { FilterConstant } from 'src/constants/utils';

Expand All @@ -7,6 +11,8 @@ export const formOnboardingCandidateJob: FormSchema<{
searchAmbition0: string;
searchBusinessLine1: FilterConstant<BusinessLineValue>;
searchAmbition1: string;
linkedinUrl: string;
externalCv: File;
}> = {
id: 'form-onboarding-candidate-job',
fields: [
Expand All @@ -19,7 +25,7 @@ export const formOnboardingCandidateJob: FormSchema<{
id: 'searchBusinessLine0',
name: 'searchBusinessLine0',
title: 'Secteur(s) recherché(s)',
component: 'select',
component: FormComponents.SELECT,
showLabel: true,
options: BUSINESS_LINES,
isMulti: false,
Expand All @@ -29,7 +35,7 @@ export const formOnboardingCandidateJob: FormSchema<{
{
id: 'searchAmbition0',
name: 'searchAmbition0',
component: 'text-input',
component: FormComponents.TEXT_INPUT,
showLabel: true,
title: 'Métier(s) recherché(s)',
placeholder: 'Métier 1',
Expand All @@ -45,7 +51,7 @@ export const formOnboardingCandidateJob: FormSchema<{
id: 'searchBusinessLine1',
name: 'searchBusinessLine1',
title: 'Secteur 2',
component: 'select',
component: FormComponents.SELECT,
isMulti: false,
options: BUSINESS_LINES,
rules: [
Expand All @@ -60,10 +66,40 @@ export const formOnboardingCandidateJob: FormSchema<{
{
id: 'searchAmbition1',
name: 'searchAmbition1',
component: 'text-input',
component: FormComponents.TEXT_INPUT,
title: 'Métier 2',
},
],
},
{
id: 'externalCv',
name: 'externalCv',
title:
'Télécharger votre CV pour que les membres puissent le découvrir !',
component: FormComponents.FILE,
fileType: FileTypes.CV,
showLabel: true,
accept: '.pdf',
},
{
id: 'linkedinUrl',
name: 'linkedinUrl',
component: FormComponents.TEXT_INPUT,
title:
'Ajouter votre profil Linkedin pour que les membres puissent le découvrir !',
placeholder: 'Ajouter le lien LinkedIn',
showLabel: true,
rules: [
{
method: (fieldValue) => {
return (
!fieldValue ||
(!!fieldValue && fieldValue.includes('linkedin.com'))
);
},
message: 'Doit être un lien Linkedin valide',
},
],
},
],
};
7 changes: 4 additions & 3 deletions src/components/backoffice/onboarding/useOnboarding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ export const useOnboarding = () => {
(fields: Partial<FlattenedOnboardingFormData>) => {
const fieldsToSend = parseOnboadingProfileFields(fields);
dispatch(
onboardingActions.validateFirstSecondStepOnboardingRequested(
fieldsToSend
)
onboardingActions.validateFirstSecondStepOnboardingRequested({
userProfile: fieldsToSend,
externalCv: fields.externalCv || undefined,
})
);
},
[dispatch]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { Close } from 'assets/icons/icons';
import { ButtonIcon } from 'src/components/utils';
import { IlluCV } from 'assets/icons/icons';
import { FilePreviewCV } from 'src/components/utils/Inputs/FileInput/FilePreview';
import { useAuthenticatedUser } from 'src/hooks/authentication/useAuthenticatedUser';
import { useCurrentUserExternalCv } from 'src/hooks/useCurrentUserExternalCv';
import { currentUserActions } from 'src/use-cases/current-user';
import {
StyledCvUploadInfosText,
StyledDeleteIconContainer,
StyledFilename,
} from './ExternalCVCard.styles';
import { StyledCvUploadInfosText } from './ExternalCVCard.styles';

interface ContentProps {
dataTestId?: string;
dataTestId: string;
}

export const Content = ({ dataTestId }: ContentProps) => {
Expand All @@ -38,21 +34,21 @@ export const Content = ({ dataTestId }: ContentProps) => {

if (user.userProfile.hasExternalCv) {
return (
<>
<StyledFilename onClick={openExternalCV}>Votre CV</StyledFilename>
<StyledDeleteIconContainer onClick={removeCallback}>
<ButtonIcon
icon={<Close width={10} height={10} />}
dataTestId={`${dataTestId}-button-edit`}
/>
</StyledDeleteIconContainer>
</>
<FilePreviewCV
filename="Votre CV"
onRemoveFile={removeCallback}
onOpenFile={openExternalCV}
dataTestId={dataTestId}
/>
);
}
return (
<StyledCvUploadInfosText>
Vous n&apos;avez pas encore de CV Entourage Pro. Téléchargez votre propre
CV.
</StyledCvUploadInfosText>
<>
<IlluCV width={70} height={70} />
<StyledCvUploadInfosText>
Vous n&apos;avez pas encore de CV Entourage Pro. Téléchargez votre
propre propre CV.
</StyledCvUploadInfosText>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import styled from 'styled-components';
import { COLORS } from 'src/constants/styles';

export const StyledCvUploadInfos = styled.div`
display: flex;
Expand All @@ -15,24 +14,6 @@ export const StyledCvCardContentContainer = styled.div`
gap: 20px;
`;

export const StyledFilename = styled.div`
text-decoration: underline;
cursor: pointer;
`;

export const StyledDeleteIconContainer = styled.div`
display: flex;
justify-content: center;
padding: 4px;
border-radius: 50%;
border: ${COLORS.primaryBlue} 1px solid;
transition: 0.3s ease-in-out;
cursor: pointer;
:hover {
background-color: ${COLORS.lightgray};
}
`;

export const StyledCvUploadInfosText = styled.p`
margin: 0;
`;
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import { Tooltip } from 'react-tooltip';
import { IlluCV } from 'assets/icons/icons';
import QuestionIcon from 'assets/icons/question.svg';
import { Button } from 'src/components/utils/Button';
import { Card } from 'src/components/utils/Cards/Card';
Expand All @@ -16,7 +15,7 @@ import {
const tooltipId = 'external-cv-tooltip';

export interface ExternalCvCardProps {
dataTestId?: string;
dataTestId: string;
}
export const ExternalCVCard = ({ dataTestId }: ExternalCvCardProps) => {
const dispatch = useDispatch();
Expand Down Expand Up @@ -58,7 +57,6 @@ export const ExternalCVCard = ({ dataTestId }: ExternalCvCardProps) => {
>
<StyledCvCardContentContainer>
<StyledCvUploadInfos>
<IlluCV width={70} height={70} />
<Content dataTestId={dataTestId} />
</StyledCvUploadInfos>
{!user.userProfile.hasExternalCv && (
Expand Down
23 changes: 22 additions & 1 deletion src/components/forms/FormSchema/FormSchema.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,24 @@ export const FormComponents = {
TEXT: 'text',
FIELDGROUP: 'fieldgroup',
MULTIPLE_FIELDS: 'multiple-fields',
FILE: 'file-input',
} as const;

export const FileTypes = {
CV: 'cv',
} as const;

export type FormComponent =
(typeof FormComponents)[keyof typeof FormComponents];

export type FileType = (typeof FileTypes)[keyof typeof FileTypes];

export type FieldValue =
| string
| string[]
| boolean
| number
| File
| FilterConstant
| FilterConstant[];

Expand All @@ -59,6 +67,7 @@ export interface FormComponentValues<M extends boolean> {
[FormComponents.TEXT]: never;
[FormComponents.FIELDGROUP]: never;
[FormComponents.MULTIPLE_FIELDS]: never;
[FormComponents.FILE]: File;
}

export type MultipleFieldValue = {
Expand Down Expand Up @@ -114,6 +123,9 @@ export const RadioComponents = [
FormComponents.RADIO_ASYNC,
] as const;

export const FileInputComponents = [FormComponents.FILE] as const;
export type FileInputComponent = (typeof FileInputComponents)[number];

export type RadioComponent = (typeof RadioComponents)[number];

export const TextComponents = [
Expand All @@ -136,7 +148,8 @@ export type InputComponent =
| SelectComponent
| SelectRequestComponent
| SelectGraphicComponent
| RadioComponent;
| RadioComponent
| FileInputComponent;

export type GetValueType<V extends FormSchemaValidation> = UseFormGetValues<V>;

Expand Down Expand Up @@ -193,6 +206,13 @@ export interface FormFieldCheckBox<V extends FormSchemaValidation>
component: CheckBoxComponent;
}

export interface FormFieldFile<V extends FormSchemaValidation>
extends FormFieldInputCommonProperties<V, FileInputComponent> {
component: FileInputComponent;
fileType: FileType;
accept: string;
}

export interface FormFieldCheckBoxAlert<V extends FormSchemaValidation>
extends FormFieldInputCommonProperties<V, CheckBoxAlertComponent> {
component: CheckBoxAlertComponent;
Expand Down Expand Up @@ -280,6 +300,7 @@ export type FormFieldInput<V extends FormSchemaValidation> = StrictUnion<
| FormFieldSelectGraphic<V>
| FormFieldSelect<V>
| FormFieldSelectRequest<V>
| FormFieldFile<V>
>;

export interface FormFieldText<V extends FormSchemaValidation>
Expand Down
13 changes: 11 additions & 2 deletions src/components/forms/FormSchema/FormSchema.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
TextComponents,
TextInputComponent,
TextInputComponents,
FormFieldFile,
} from './FormSchema.types';

export function mapFieldRules<
Expand Down Expand Up @@ -135,6 +136,12 @@ export function isFormFieldSelectGraphic<S extends FormSchemaValidation>(
);
}

export function isFormFieldFile<S extends FormSchemaValidation>(
field: FormField<S>
): field is FormFieldFile<S> {
return field.component === 'file-input';
}

export function isFormFieldInput<S extends FormSchemaValidation>(
field: FormField<S>
): field is
Expand All @@ -144,15 +151,17 @@ export function isFormFieldInput<S extends FormSchemaValidation>(
| FormFieldCheckBoxAlert<S>
| FormFieldSelect<S>
| FormFieldSelectRequest<S>
| FormFieldSelectGraphic<S> {
| FormFieldSelectGraphic<S>
| FormFieldFile<S> {
return (
isFormFieldTextInput(field) ||
isFormFieldCheckbox(field) ||
isFormFieldCheckboxAlert(field) ||
isFormFieldRadio(field) ||
isFormFieldSelect(field) ||
isFormFieldSelectRequest(field) ||
isFormFieldSelectGraphic(field)
isFormFieldSelectGraphic(field) ||
isFormFieldFile(field)
);
}

Expand Down
11 changes: 11 additions & 0 deletions src/components/forms/fields/GenericField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
SelectSimple,
TextArea,
TextInput,
FileInput,
} from 'src/components/utils/Inputs';
import { CommonInputProps } from 'src/components/utils/Inputs/Inputs.types';
import { RadioTypes } from 'src/components/utils/Inputs/Radio/Radio.types';
Expand Down Expand Up @@ -190,6 +191,16 @@ export function GenericField<S extends FormSchema<AnyCantFix>>({
);
}

if (field.component === 'file-input') {
return (
<FileInput
{...commonProps}
accept={field.accept}
fileType={field.fileType}
/>
);
}

if (field.component === 'tel-input') {
return <PhoneInput {...commonProps} />;
}
Expand Down
35 changes: 35 additions & 0 deletions src/components/utils/Inputs/FileInput/FileInput.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Meta, StoryObj } from '@storybook/react';
import React from 'react';
import { FileTypes } from 'src/components/forms/FormSchema';
import { FileInput, FileInputProps } from './FileInput';

const FileInputConfigured = ({ fileType, accept }: FileInputProps) => {
const [file, setFile] = React.useState<File | null>(null);
return (
<FileInput
accept={accept}
fileType={fileType}
id="file-input-storybook"
name="cv"
value={file}
onChange={(value) => {
setFile(value);
}}
/>
);
};

const meta = {
title: 'FileInput',
render: FileInputConfigured,
} satisfies Meta<typeof FileInput>;

export default meta;
type Story = StoryObj<typeof FileInput>;

export const Cv: Story = {
args: {
fileType: FileTypes.CV,
accept: '.pdf',
},
};
Loading

0 comments on commit 47d3f68

Please sign in to comment.