Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checkout component for email notifications #152

Merged
merged 6 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/api/src/types/UserType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ export type GetUserResponse = {
id: string;
username: string | null;
email: string | null;
name: string | null;
emailNotification: boolean;
createdAt: string;
updatedAt: string;
};

export type PutUserRequest = {
userId: string;
username: string;
name?: string;
emailNotification?: boolean;
email?: string;
groupIds: string[];
userAttributes: Record<string, string>;
Expand Down
4 changes: 4 additions & 0 deletions packages/api/src/updateUserData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { PutUserRequest, GetUserResponse } from './types/UserType';
async function updateUserData({
userId,
username,
emailNotification,
name,
email,
groupIds,
userAttributes,
Expand All @@ -19,6 +21,8 @@ async function updateUserData({
username,
email,
userAttributes,
emailNotification,
name,
}),
});

Expand Down
53 changes: 53 additions & 0 deletions packages/berlin/src/components/checkbox/Checkbox.styled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import styled from 'styled-components';

export const Container = styled.div`
display: grid;
grid-template-columns: 1.5rem 1fr;
column-gap: 0.5rem;
`;

export const CheckboxContainer = styled.div`
align-items: center;
display: flex;
height: 1.5rem;
justify-content: center;
width: 1.5rem;
`;

export const HiddenCheckbox = styled.input`
border: 0;
clip-path: inset(50%);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;

&:focus-within {
outline: 2px solid red;
}
`;

export const Icon = styled.svg`
fill: none;
stroke: var(--color-black);
stroke-width: 3px;
`;

export const StyledCheckbox = styled.div<{ $checked: boolean }>`
align-items: center;
border-radius: 3px;
border: 1.25px solid var(--color-black);
cursor: pointer;
display: flex;
height: 1.125rem;
justify-content: center;
width: 1.125rem;

${Icon} {
visibility: ${(props) => (props.$checked ? 'visible' : 'hidden')};
}
`;
46 changes: 46 additions & 0 deletions packages/berlin/src/components/checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Label from '../typography/Label';
import {
CheckboxContainer,
Container,
HiddenCheckbox,
Icon,
StyledCheckbox,
} from './Checkbox.styled';
import React from 'react';

type CheckboxProps = {
text: string;
$required?: boolean;
onClick?: () => void;
value: boolean;
};

const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
({ text, $required, onClick, value }, ref) => {
return (
<Container>
<CheckboxContainer>
<HiddenCheckbox
type="checkbox"
checked={value}
id={text}
name={text}
required={$required}
ref={ref}
onChange={() => {}}
/>
<StyledCheckbox $checked={value} onClick={onClick}>
<Icon viewBox="0 0 24 24">
<polyline points="20 6 9 17 4 12" />
</Icon>
</StyledCheckbox>
</CheckboxContainer>
<Label $required={$required} htmlFor={text} onClick={onClick}>
{text}
</Label>
</Container>
);
},
);

export default Checkbox;
1 change: 1 addition & 0 deletions packages/berlin/src/components/checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Checkbox';
15 changes: 15 additions & 0 deletions packages/berlin/src/components/textarea/Textarea.styled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styled from 'styled-components';

export const StyledTextarea = styled.textarea`
background-color: var(--color-white);
border-radius: 0.5rem;
border: 1px solid var(--color-black);
height: 12rem;
padding: 0.75rem 1rem;
resize: none;
width: 100%;

&:disabled {
cursor: not-allowed;
}
`;
29 changes: 29 additions & 0 deletions packages/berlin/src/components/textarea/Textarea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Components
import React from 'react';
import { FlexColumn } from '../containers/FlexColum.styled';
import Label from '../typography/Label';

// Styled Components
import { StyledTextarea } from './Textarea.styled';

interface TextareaProps extends React.InputHTMLAttributes<HTMLTextAreaElement> {
label: string;
$required?: boolean;
}

const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ label, $required, ...props }, ref) => {
return (
<FlexColumn>
{label && (
<Label $required={$required} htmlFor={props.name}>
{label}
</Label>
)}
<StyledTextarea {...props} name={props.name} ref={ref} />
</FlexColumn>
);
},
);

export default Textarea;
1 change: 1 addition & 0 deletions packages/berlin/src/components/textarea/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Textarea';
51 changes: 37 additions & 14 deletions packages/berlin/src/pages/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { FlexColumn } from '../components/containers/FlexColum.styled';
import { FlexRowToColumn } from '../components/containers/FlexRowToColumn.styled';
import { Title } from '../components/typography/Title.styled';
import Button from '../components/button';
import Checkbox from '../components/checkbox';
import IconButton from '../components/iconButton';
import Input from '../components/input';
import Label from '../components/typography/Label';
Expand All @@ -44,7 +45,6 @@ type CredentialsGroup = {
}[];

type UserAttributes = {
name: string;
institution: string;
role: string;
publications: { value: string }[];
Expand All @@ -54,6 +54,8 @@ type UserAttributes = {

type InitialUser = {
username: string;
name: string;
emailNotification: boolean;
email: string;
group: string;
userAttributes: UserAttributes | undefined;
Expand Down Expand Up @@ -86,9 +88,11 @@ function Account() {
enabled: !!user?.id,
});

const initialUser = {
const initialUser: InitialUser = {
username: user?.username || '',
name: user?.name || '',
email: user?.email || '',
emailNotification: user?.emailNotification ?? true,
group: (userGroups && userGroups[0]?.id) || '',
userAttributes: userAttributes?.reduce(
(acc, curr) => {
Expand All @@ -111,7 +115,6 @@ function Account() {
}
},
{
name: '',
institution: '',
role: '',
publications: [{ value: '' }],
Expand Down Expand Up @@ -207,6 +210,8 @@ function AccountForm({
userId: user.id,
username: value.username,
email: value.email,
emailNotification: value.emailNotification,
name: value.name,
groupIds: [value.group],
userAttributes: {
...value.userAttributes,
Expand All @@ -224,6 +229,16 @@ function AccountForm({
}
};

const credentialOnChange = (value: string, i: number) => {
if (value === 'None') {
setValue(`userAttributes.credentialsGroup.${i}.institution`, 'None');
setValue(`userAttributes.credentialsGroup.${i}.field`, 'None');
// Manually trigger validation
trigger(`userAttributes.credentialsGroup.${i}.institution`);
trigger(`userAttributes.credentialsGroup.${i}.field`);
}
};

return (
<FlexColumn>
<Title>Complete your registration</Title>
Expand All @@ -236,7 +251,7 @@ function AccountForm({
{...register('username', { required: 'Username is required', minLength: 3 })}
errors={errors.username ? [errors.username.message ?? ''] : []}
/>
<Input label="Name" placeholder="Enter your Name" {...register('userAttributes.name')} />
<Input label="Name" placeholder="Enter your Name" {...register('name')} />
<Input label="Email" placeholder="Enter your Email" {...register('email')} />
<Controller
name="group"
Expand Down Expand Up @@ -286,13 +301,7 @@ function AccountForm({
onChange={(value) => {
field.onChange(value);
// Check if selected credential is 'None' and set default values accordingly
if (value === 'None') {
setValue(`userAttributes.credentialsGroup.${i}.institution`, 'None');
setValue(`userAttributes.credentialsGroup.${i}.field`, 'None');
// Manually trigger validation
trigger(`userAttributes.credentialsGroup.${i}.institution`);
trigger(`userAttributes.credentialsGroup.${i}.field`);
}
credentialOnChange(value, i);
}}
onBlur={field.onBlur}
value={field.value}
Expand Down Expand Up @@ -341,7 +350,7 @@ function AccountForm({
/>
</FlexColumn>
<FlexColumn $gap="0.5rem">
<Label >Publications</Label>
<Label>Publications</Label>
{fieldsPublications.map((field, i) => (
<FlexRowToColumn key={field.id}>
<Input
Expand All @@ -362,7 +371,7 @@ function AccountForm({
/>
</FlexColumn>
<FlexColumn $gap="0.5rem">
<Label >Contributions to MEV</Label>
<Label>Contributions to MEV</Label>
{fieldsContributions.map((field, i) => (
<FlexRowToColumn key={field.id}>
<Input
Expand All @@ -382,7 +391,21 @@ function AccountForm({
icon={{ src: `/icons/add-${theme}.svg`, alt: 'Add icon' }}
/>
</FlexColumn>
<Button type="submit">Submit</Button>
<Controller
name={`emailNotification`}
control={control}
render={({ field }) => (
<Checkbox
text="Would you like to receive email notifications?"
{...field}
onClick={() => field.onChange(!field.value)}
value={field.value}
/>
)}
/>
<Button type="submit" disabled={!isValid}>
Submit
</Button>
</FlexColumn>
</form>
</FlexColumn>
Expand Down
Loading
Loading