Feat/phone email link enhancements (#1172)
* feat: Add type guards for ViewField email values and definitions, update ViewFieldTypes & peopleViewFields * feat: use ContactLink for EditablePhoneCell & create EditableEmailCell & EmailInputDisplay comp * fix: set second value for field * enhance: add edit btn for phone cell * feat: install dependencies intl-tel-input * feat: add phone cell input & connect intl-tel-input * fix: resolve rebase errors * fix: remove placeholder * feat(storybook): create stories for EmailInputDisplay, PhoneInputDisplay, and PhoneEditableField components --------- Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
This commit is contained in:
@ -0,0 +1,27 @@
|
||||
import { MouseEvent } from 'react';
|
||||
|
||||
import { ContactLink } from '@/ui/link/components/ContactLink';
|
||||
|
||||
function validateEmail(email: string) {
|
||||
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailPattern.test(email.trim());
|
||||
}
|
||||
|
||||
type OwnProps = {
|
||||
value: string | null;
|
||||
};
|
||||
|
||||
export function EmailInputDisplay({ value }: OwnProps) {
|
||||
return value && validateEmail(value) ? (
|
||||
<ContactLink
|
||||
href={`mailto:${value}`}
|
||||
onClick={(event: MouseEvent<HTMLElement>) => {
|
||||
event.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</ContactLink>
|
||||
) : (
|
||||
<ContactLink href="#">{value}</ContactLink>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
|
||||
import { EmailInputDisplay } from '../EmailInputDisplay';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Modules/People/EmailInputDisplay',
|
||||
component: EmailInputDisplay,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<StyledTestEmailContainer>
|
||||
<BrowserRouter>
|
||||
<Story />
|
||||
</BrowserRouter>
|
||||
</StyledTestEmailContainer>
|
||||
),
|
||||
ComponentDecorator,
|
||||
],
|
||||
args: {
|
||||
value: 'mustajab.ikram@google.com',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof EmailInputDisplay>;
|
||||
|
||||
const StyledTestEmailContainer = styled.div`
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
display: flex;
|
||||
`;
|
||||
export const Default: Story = {};
|
||||
@ -1,18 +1,7 @@
|
||||
import { MouseEvent } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isValidPhoneNumber, parsePhoneNumber } from 'libphonenumber-js';
|
||||
|
||||
import { RawLink } from '@/ui/link/components/RawLink';
|
||||
|
||||
const StyledRawLink = styled(RawLink)`
|
||||
overflow: hidden;
|
||||
|
||||
a {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
import { ContactLink } from '@/ui/link/components/ContactLink';
|
||||
|
||||
type OwnProps = {
|
||||
value: string | null;
|
||||
@ -20,15 +9,15 @@ type OwnProps = {
|
||||
|
||||
export function PhoneInputDisplay({ value }: OwnProps) {
|
||||
return value && isValidPhoneNumber(value) ? (
|
||||
<StyledRawLink
|
||||
<ContactLink
|
||||
href={parsePhoneNumber(value, 'FR')?.getURI()}
|
||||
onClick={(event: MouseEvent<HTMLElement>) => {
|
||||
event.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{parsePhoneNumber(value, 'FR')?.formatInternational() || value}
|
||||
</StyledRawLink>
|
||||
</ContactLink>
|
||||
) : (
|
||||
<StyledRawLink href="#">{value}</StyledRawLink>
|
||||
<ContactLink href="#">{value}</ContactLink>
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
|
||||
import { PhoneInputDisplay } from '../PhoneInputDisplay'; // Adjust the import path as needed
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Modules/People/PhoneInputDisplay',
|
||||
component: PhoneInputDisplay,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<StyledTestPhoneContainer>
|
||||
<BrowserRouter>
|
||||
<Story />
|
||||
</BrowserRouter>
|
||||
</StyledTestPhoneContainer>
|
||||
),
|
||||
ComponentDecorator,
|
||||
],
|
||||
args: {
|
||||
value: '+33788901234',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
type Story = StoryObj<typeof PhoneInputDisplay>;
|
||||
|
||||
const StyledTestPhoneContainer = styled.div`
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
display: flex;
|
||||
`;
|
||||
|
||||
export const Default: Story = {};
|
||||
Reference in New Issue
Block a user