From e47bf76e099b77e09e88c29701460b06c8585d6d Mon Sep 17 00:00:00 2001 From: Bamidele Oluwatobi <56609046+tobi-bams@users.noreply.github.com> Date: Fri, 24 Nov 2023 19:33:35 +0100 Subject: [PATCH] Feat/add user design (#981) * feat: add user to organization new flow * feat: assign user roles * update: made some db query change * update: moved all styles in add user model to a new style file * update: moved assign user role styles to style file * update: updated syntax based on review * feat: added search to find add user modal * feat: added test for formatting roles that are displayed * fix: fix import * fix: moved function to another file * update: added img for users without image --- db/db.go | 2 +- .../app/src/helpers/__test__/helpers.spec.ts | 57 ++++- frontend/app/src/helpers/helpers-extended.ts | 60 +++++ .../app/src/people/widgetViews/AboutView.tsx | 50 ++-- .../widgetViews/OrganizationDetails.tsx | 28 +- .../widgetViews/organization/AddUserModal.tsx | 161 ++++++------ .../organization/AssignUserRole.tsx | 160 ++++++++++++ .../widgetViews/organization/RolesModal.tsx | 43 +--- .../widgetViews/organization/interface.ts | 8 + .../people/widgetViews/organization/style.ts | 242 ++++++++++++++++++ 10 files changed, 656 insertions(+), 155 deletions(-) create mode 100644 frontend/app/src/people/widgetViews/organization/AssignUserRole.tsx diff --git a/db/db.go b/db/db.go index 2119b346c..529fc3239 100644 --- a/db/db.go +++ b/db/db.go @@ -1046,7 +1046,7 @@ func (db database) CreateOrEditOrganization(m Organization) (Organization, error func (db database) GetOrganizationUsers(uuid string) ([]OrganizationUsersData, error) { ms := []OrganizationUsersData{} - err := db.db.Raw(`SELECT org.org_uuid, org.created as user_created, person.* FROM public.organization_users AS org LEFT OUTER JOIN public.people AS person ON org.owner_pub_key = person.owner_pub_key WHERE org.org_uuid = '` + uuid + `' OR org.organization = '` + uuid + `' ORDER BY org.created DESC`).Find(&ms).Error + err := db.db.Raw(`SELECT org.org_uuid, org.created as user_created, person.* FROM public.organization_users AS org LEFT OUTER JOIN public.people AS person ON org.owner_pub_key = person.owner_pub_key WHERE org.org_uuid = '` + uuid + `' ORDER BY org.created DESC`).Find(&ms).Error return ms, err } diff --git a/frontend/app/src/helpers/__test__/helpers.spec.ts b/frontend/app/src/helpers/__test__/helpers.spec.ts index 93c1a213a..16a8772dc 100644 --- a/frontend/app/src/helpers/__test__/helpers.spec.ts +++ b/frontend/app/src/helpers/__test__/helpers.spec.ts @@ -1,3 +1,5 @@ +import crypto from 'crypto'; +import moment from 'moment'; import { extractGithubIssueFromUrl, extractRepoAndIssueFromIssueUrl, @@ -6,10 +8,10 @@ import { toCapitalize, userHasRole, spliceOutPubkey, - userHasManageBountyRoles + userHasManageBountyRoles, + RolesCategory, + handleDisplayRole } from '../helpers-extended'; -import crypto from 'crypto'; -import moment from 'moment'; beforeAll(() => { // for test randomString @@ -210,4 +212,53 @@ describe('testing helpers', () => { expect(pub).toBe(pubkey); }); }); + + describe('format roles', () => { + test('should correctly set the default data roles for the first assigned user', () => { + const displayedRoles: RolesCategory[] = []; + const result = handleDisplayRole(displayedRoles); + expect(result.newDisplayedRoles).toEqual([]); + expect(result.tempDataRole).toEqual({}); + }); + + test('should correctly update the status of a role if it is present in the default roles', () => { + const displayedRoles: RolesCategory[] = [ + { name: 'Manage bounties', roles: [], status: false }, + { name: 'Fund organization', roles: [], status: false }, + { name: 'Withdraw from organization', roles: [], status: false }, + { name: 'View transaction history', roles: [], status: false } + ]; + const result = handleDisplayRole(displayedRoles); + expect(result.newDisplayedRoles).toEqual([ + { name: 'Manage bounties', roles: [], status: true }, + { name: 'Fund organization', roles: [], status: true }, + { name: 'Withdraw from organization', roles: [], status: true }, + { name: 'View transaction history', roles: [], status: true } + ]); + expect(result.tempDataRole).toEqual({}); + }); + + test('should correctly update the tempDataRole object with the data roles of a role if it is present in the default roles', () => { + const displayedRoles: RolesCategory[] = [ + { name: 'Manage bounties', roles: ['role1', 'role2'], status: false }, + { name: 'Fund organization', roles: ['role3'], status: false }, + { name: 'Withdraw from organization', roles: ['role4'], status: false }, + { name: 'View transaction history', roles: ['role5'], status: false } + ]; + const result = handleDisplayRole(displayedRoles); + expect(result.newDisplayedRoles).toEqual([ + { name: 'Manage bounties', roles: ['role1', 'role2'], status: true }, + { name: 'Fund organization', roles: ['role3'], status: true }, + { name: 'Withdraw from organization', roles: ['role4'], status: true }, + { name: 'View transaction history', roles: ['role5'], status: true } + ]); + expect(result.tempDataRole).toEqual({ + role1: true, + role2: true, + role3: true, + role4: true, + role5: true + }); + }); + }); }); diff --git a/frontend/app/src/helpers/helpers-extended.ts b/frontend/app/src/helpers/helpers-extended.ts index 52a12bbce..abbe1556f 100644 --- a/frontend/app/src/helpers/helpers-extended.ts +++ b/frontend/app/src/helpers/helpers-extended.ts @@ -164,6 +164,45 @@ export type Roles = export const ManageBountiesGroup = ['ADD BOUNTY', 'UPDATE BOUNTY', 'DELETE BOUNTY', 'PAY BOUNTY']; +export interface RolesCategory { + name: string; + roles: string[]; + status: boolean; +} + +export const s_RolesCategories = [ + { + name: 'Manage organization', + roles: ['EDIT ORGANIZATION'], + status: false + }, + { + name: 'Manage bounties', + roles: ManageBountiesGroup, + status: false + }, + { + name: 'Fund organization', + roles: ['ADD BUDGET'], + status: false + }, + { + name: 'Withdraw from organization', + roles: ['WITHDRAW BUDGET'], + status: false + }, + { + name: 'View transaction history', + roles: ['VIEW REPORT'], + status: false + }, + { + name: 'Update members', + roles: ['ADD USER', 'UPDATE USER', 'DELETE USER', 'ADD ROLES'], + status: false + } +]; + export const userHasRole = ( bountyRoles: any[], userRoles: any[], @@ -239,3 +278,24 @@ export const spliceOutPubkey = (userAddress: string): string => { return userAddress; }; + +export function handleDisplayRole(displayedRoles: RolesCategory[]) { + // Set default data roles for first assign user + const defaultRole = { + 'Manage bounties': true, + 'Fund organization': true, + 'Withdraw from organization': true, + 'View transaction history': true + }; + + const tempDataRole: { [id: string]: boolean } = {}; + const newDisplayedRoles = displayedRoles.map((role: RolesCategory) => { + if (defaultRole[role.name]) { + role.status = true; + role.roles.forEach((dataRole: string) => (tempDataRole[dataRole] = true)); + } + return role; + }); + + return { newDisplayedRoles, tempDataRole }; +} diff --git a/frontend/app/src/people/widgetViews/AboutView.tsx b/frontend/app/src/people/widgetViews/AboutView.tsx index a2c8e630b..26d79b2d6 100644 --- a/frontend/app/src/people/widgetViews/AboutView.tsx +++ b/frontend/app/src/people/widgetViews/AboutView.tsx @@ -8,33 +8,33 @@ import QrBar from '../utils/QrBar'; import { renderMarkdown } from '../utils/RenderMarkdown'; const Badge = styled.div` -display:flex; -justify-content:center; -align-items:center; -margin-left:10px; -height:20px; -color:#ffffff; -background: #1DA1F2; -border-radius: 32px; -font-weight: bold; -font-size: 8px; -line-height: 9px; -padding 0 10px; + display: flex; + justify-content: center; + align-items: center; + margin-left: 10px; + height: 20px; + color: #ffffff; + background: #1da1f2; + border-radius: 32px; + font-weight: bold; + font-size: 8px; + line-height: 9px; + padding: 0 10px; `; const CodeBadge = styled.div` -display:flex; -justify-content:center; -align-items:center; -margin-right:10px; -height:26px; -color:#5078F2; -background: #DCEDFE; -border-radius: 32px; -font-weight: bold; -font-size: 12px; -line-height: 13px; -padding 0 10px; -margin-bottom:10px; + display: flex; + justify-content: center; + align-items: center; + margin-right: 10px; + height: 26px; + color: #5078f2; + background: #dcedfe; + border-radius: 32px; + font-weight: bold; + font-size: 12px; + line-height: 13px; + padding: 0 10px; + margin-bottom: 10px; `; const ItemRow = styled.div` display: flex; diff --git a/frontend/app/src/people/widgetViews/OrganizationDetails.tsx b/frontend/app/src/people/widgetViews/OrganizationDetails.tsx index 05ba3399f..4d2247d17 100644 --- a/frontend/app/src/people/widgetViews/OrganizationDetails.tsx +++ b/frontend/app/src/people/widgetViews/OrganizationDetails.tsx @@ -40,6 +40,7 @@ import { ViewBudgetWrap, ViewBudgetTextWrap } from './organization/style'; +import AssignUserRoles from './organization/AssignUserRole'; let interval; @@ -68,6 +69,7 @@ const OrganizationDetails = (props: { const [toasts, setToasts]: any = useState([]); const [invoiceStatus, setInvoiceStatus] = useState(false); const { path, url } = useRouteMatch(); + const [isOpenAssignRoles, setIsOpenAssignRoles] = useState(false); const isOrganizationAdmin = props.org?.owner_pubkey === ui.meInfo?.owner_pubkey; @@ -86,7 +88,7 @@ const OrganizationDetails = (props: { function addToast(title: string, color: 'danger' | 'success') { setToasts([ { - id: '1', + id: `${Math.random()}`, title, color } @@ -101,6 +103,7 @@ const OrganizationDetails = (props: { if (uuid) { const users = await main.getOrganizationUsers(uuid); setUsers(users); + return users; } }, [main, uuid]); @@ -193,6 +196,10 @@ const OrganizationDetails = (props: { setIsOpenWithdrawBudget(false); }; + const closeAssignRolesHandler = () => { + setIsOpenAssignRoles(false); + }; + const onSubmitUser = async (body: any) => { setIsLoading(true); @@ -200,7 +207,13 @@ const OrganizationDetails = (props: { const res = await main.addOrganizationUser(body); if (res.status === 200) { - await getOrganizationUsers(); + addToast('User added to organization successfully', 'success'); + const recentUsers = await getOrganizationUsers(); + const user = recentUsers?.filter((user: Person) => user.owner_pubkey === body.owner_pubkey); + if (user?.length === 1) { + setUser(user[0]); + setIsOpenAssignRoles(true); + } } else { addToast('Error: could not add user', 'danger'); } @@ -452,6 +465,17 @@ const OrganizationDetails = (props: { loading={loading} /> )} + {isOpenAssignRoles && ( + + )} {isOpenRoles && ( { const isMobile = useIsMobile(); - const { isOpen, close, onSubmit, loading, disableFormButtons, setDisableFormButtons } = props; - const [displayHint, setDisplayHint] = useState(false); - - const hintText = 'Route hint detected and removed'; - - const checkDisplayHint = (address: string) => { - if (address.includes(':')) { - setDisplayHint(true); - } else { - setDisplayHint(false); - } - }; + const { isOpen, close, onSubmit, loading } = props; + const { main, ui } = useStores(); + const [selectedPubkey, setSelectedPubkey] = useState(); + const [searchTerm, setSearchName] = useState(''); + const [people, setPeople] = useState( + (main.people && main.people.filter((f: any) => !f.hide)) || [] + ); + const currentUserPubkey = ui.meInfo?.owner_pubkey; const config = nonWidgetConfigs['organizationusers']; - const schema = [...config.schema]; - - const formRef = useRef(null); + function checkIsActive(pubkey: string) { + return !!(selectedPubkey && pubkey !== selectedPubkey); + } - const initValues = { - owner_pubkey: '' + const handleSearchUser = async (e: ChangeEvent) => { + const name = e.target.value; + setSearchName(name); + const persons = await main.getPeopleByNameAliasPubkey(name); + setPeople(persons.filter((person: Person) => person.owner_pubkey !== currentUserPubkey)); }; return ( @@ -51,7 +61,8 @@ const AddUserModal = (props: AddUserModalProps) => { zIndex: 20, ...(config?.modalStyle ?? {}), maxHeight: '100%', - borderRadius: '10px' + borderRadius: '10px', + minWidth: '22rem' }} overlayClick={close} bigCloseImage={close} @@ -62,66 +73,44 @@ const AddUserModal = (props: AddUserModalProps) => { borderRadius: '50%' }} > - - {({ setFieldTouched, handleSubmit, values, setFieldValue, errors, initialValues }: any) => ( - - Add new user - {displayHint && {hintText}} -
- {schema.map((item: FormField) => ( - { - if (errors[item.name]) delete errors[item.name]; - }} - handleChange={(e: any) => { - checkDisplayHint(e); - const pubkey = spliceOutPubkey(e); - setFieldValue(item.name, pubkey); - }} - setFieldValue={(e: any, f: any) => { - setFieldValue(e, f); - }} - setFieldTouched={setFieldTouched} - handleBlur={() => setFieldTouched(item.name, false)} - handleFocus={() => setFieldTouched(item.name, true)} - setDisableFormButtons={setDisableFormButtons} - borderType={'bottom'} - imageIcon={true} - style={ - item.name === 'github_description' && !values.ticket_url - ? { - display: 'none' - } - : undefined - } - /> - ))} -
-
- )} -
+ + + Add New User + + + + {people.length > 0 ? ( + people.map((person: any, index: number) => ( + + + + {person.owner_alias} + + setSelectedPubkey(person.owner_pubkey)} + > + Add + + + )) + ) : ( +

No user with such alias

+ )} +
+ + onSubmit({ owner_pubkey: selectedPubkey })} + disabled={!selectedPubkey} + > + {loading ? : 'Add User'} + + +
); }; diff --git a/frontend/app/src/people/widgetViews/organization/AssignUserRole.tsx b/frontend/app/src/people/widgetViews/organization/AssignUserRole.tsx new file mode 100644 index 000000000..b1cb76845 --- /dev/null +++ b/frontend/app/src/people/widgetViews/organization/AssignUserRole.tsx @@ -0,0 +1,160 @@ +import React, { useState, useEffect, ChangeEvent } from 'react'; +import { useIsMobile } from 'hooks/uiHooks'; +import { EuiLoadingSpinner } from '@elastic/eui'; +import { useStores } from 'store'; +import { RolesCategory, s_RolesCategories } from 'helpers/helpers-extended'; +import { nonWidgetConfigs } from 'people/utils/Constants'; +import { handleDisplayRole } from 'helpers'; +import { Modal } from '../../../components/common'; +import { colors } from '../../../config/colors'; +import { AssignUserModalProps } from './interface'; +import { + AssignRoleUserImage, + AssignRoleUsername, + AssignUserContainer, + AssingUserBtn, + Checkbox, + Label, + RoleContainer, + RolesContainer, + UserInfoContainer, + UserRolesContainer, + UserRolesTitle +} from './style'; + +interface BackendRoles { + name: string; + status: boolean; +} + +const color = colors['light']; + +const AssignUserRoles = (props: AssignUserModalProps) => { + const { isOpen, close, loading, user, setLoading, onSubmit, addToast } = props; + const { main } = useStores(); + + const config = nonWidgetConfigs['organizationusers']; + + const isMobile = useIsMobile(); + + const roleData = main.bountyRoles.map((role: any) => ({ + name: role.name, + status: false + })); + + const [rolesData, setRolesData] = useState(roleData); + const [displayedRoles, setDisplayedRoles] = useState(s_RolesCategories); + + useEffect(() => { + const { newDisplayedRoles, tempDataRole } = handleDisplayRole(displayedRoles); + + setRolesData((prev: BackendRoles[]) => + prev.map((role: BackendRoles) => { + if (tempDataRole[role.name]) { + role.status = true; + } + return role; + }) + ); + setDisplayedRoles(newDisplayedRoles); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const handleOnchange = (e: ChangeEvent, role: RolesCategory) => { + // Handle display role + const newDisplayRoles = displayedRoles.map((displayRole: RolesCategory) => { + if (displayRole.name === role.name) { + displayRole.status = e.target.checked; + } + return displayRole; + }); + setDisplayedRoles(newDisplayRoles); + + // update backend role + const newBackendObj = {}; + role.roles.forEach( + (value: string) => (newBackendObj[`${value}`] = { value: e.target.checked }) + ); + + setRolesData((prev: BackendRoles[]) => + prev.map((role: BackendRoles) => { + if (newBackendObj[role.name]) { + role.status = newBackendObj[role.name].value; + } + return role; + }) + ); + }; + + async function handleSubmitRole() { + setLoading(true); + try { + await onSubmit(rolesData); + setLoading(false); + addToast('Roles Assigned Successfully', 'success'); + close(); + } catch (error) { + setLoading(false); + addToast('An internal error occured, please contact support', 'danger'); + } + } + + return ( + + + + + {user?.owner_alias} + + + User Roles + + {displayedRoles.map((role: RolesCategory) => ( + + ) => handleOnchange(e, role)} + /> + + + ))} + + + {loading ? : 'Assign'} + + + + + ); +}; + +export default AssignUserRoles; diff --git a/frontend/app/src/people/widgetViews/organization/RolesModal.tsx b/frontend/app/src/people/widgetViews/organization/RolesModal.tsx index 3f211140b..004eac407 100644 --- a/frontend/app/src/people/widgetViews/organization/RolesModal.tsx +++ b/frontend/app/src/people/widgetViews/organization/RolesModal.tsx @@ -3,7 +3,7 @@ import { Wrap } from 'components/form/style'; import { useIsMobile } from 'hooks/uiHooks'; import { nonWidgetConfigs } from 'people/utils/Constants'; import styled from 'styled-components'; -import { userHasRole, Roles, ManageBountiesGroup } from 'helpers'; +import { userHasRole, Roles, s_RolesCategories } from 'helpers'; import { useStores } from 'store'; import avatarIcon from '../../../public/static/profile_avatar.svg'; import { Button, Modal } from '../../../components/common'; @@ -31,10 +31,10 @@ const UserRolesImage = styled(UserImage)` position: fixed; left: 50%; transform: translate(-40px, -90px); - borderstyle: solid; - borderradius: 50%; - borderwidth: 4px; - bordercolor: white; + border-style: solid; + border-radius: 50%; + border-width: 4px; + border-color: white; `; const HLine = styled.div` @@ -44,39 +44,6 @@ const HLine = styled.div` margin: 5px 0px 20px; `; -const s_RolesCategories = [ - { - name: 'Manage organization', - roles: ['EDIT ORGANIZATION'], - status: false - }, - { - name: 'Manage bounties', - roles: ManageBountiesGroup, - status: false - }, - { - name: 'Fund organization', - roles: ['ADD BUDGET'], - status: false - }, - { - name: 'Withdraw from organization', - roles: ['WITHDRAW BUDGET'], - status: false - }, - { - name: 'View transaction history', - roles: ['VIEW REPORT'], - status: false - }, - { - name: 'Update members', - roles: ['ADD USER', 'UPDATE USER', 'DELETE USER', 'ADD ROLES'], - status: false - } -]; - const RolesModal = (props: UserRolesModalProps) => { const { main } = useStores(); const isMobile = useIsMobile(); diff --git a/frontend/app/src/people/widgetViews/organization/interface.ts b/frontend/app/src/people/widgetViews/organization/interface.ts index b6d69cbbe..1a7b687f8 100644 --- a/frontend/app/src/people/widgetViews/organization/interface.ts +++ b/frontend/app/src/people/widgetViews/organization/interface.ts @@ -68,3 +68,11 @@ export interface UserListProps { handleSettingsClick: (user: Person) => void; handleDeleteClick: (user: Person) => void; } + +export interface AssignUserModalProps extends ModalProps { + loading: boolean; + onSubmit: (body: any) => void; + user?: Person; + setLoading: (value: boolean) => void; + addToast: (title: string, color: 'danger' | 'success') => void; +} diff --git a/frontend/app/src/people/widgetViews/organization/style.ts b/frontend/app/src/people/widgetViews/organization/style.ts index cdc39c25c..c05782aa8 100644 --- a/frontend/app/src/people/widgetViews/organization/style.ts +++ b/frontend/app/src/people/widgetViews/organization/style.ts @@ -1,6 +1,14 @@ import styled from 'styled-components'; import { Button } from 'components/common'; +interface SmallBtnProps { + selected: boolean; +} + +interface UserProps { + inactive: boolean; +} + export const ModalTitle = styled.h3` font-size: 1.2rem; `; @@ -518,3 +526,237 @@ export const RouteHintText = styled.p` text-align: center; color: #9157f6; `; + +export const AddUserContainer = styled.div` + display: flex; + flex-direction: column; + width: 100%; +`; + +export const AddUserHeaderContainer = styled.div` + display: flex; + padding: 1.875rem; + flex-direction: column; +`; + +export const AddUserHeader = styled.h2` + color: #3c3f41; + font-family: 'Barlow'; + font-size: 1.625rem; + font-style: normal; + font-weight: 800; + line-height: normal; + margin-bottom: 1.25rem; +`; + +export const SearchUserInput = styled.input` + padding: 0.9375rem 0.875rem; + border-radius: 0.375rem; + border: 1px solid #dde1e5; + background: #fff; + width: 100%; + color: #292c33; + font-family: 'Barlow'; + font-size: 0.8125rem; + font-style: normal; + font-weight: 400; + + ::placeholder { + color: #8e969c; + } +`; + +export const UsersListContainer = styled.div` + display: flex; + flex-direction: column; + padding: 1rem 1.875rem; + background-color: #f2f3f5; + height: 16rem; + overflow-y: auto; +`; + +export const UserContianer = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1rem; +`; + +export const UserInfo = styled.div` + display: flex; + align-items: center; + opacity: ${(p: any) => (p.inactive ? 0.3 : 1)}; +`; + +export const UserImg = styled.img` + width: 2rem; + height: 2rem; + border-radius: 50%; + margin-right: 0.63rem; + object-fit: cover; +`; + +export const Username = styled.p` + color: #3c3f41; + font-family: 'Barlow'; + font-size: 0.8125rem; + font-style: normal; + font-weight: 500; + line-height: 1rem; + margin-bottom: 0; +`; + +export const SmallBtn = styled.button` + width: 5.375rem; + height: 2rem; + padding: 0.625rem; + border-radius: 0.375rem; + background: ${(p: any) => (p.selected ? '#618AFF' : '#dde1e5')}; + color: ${(p: any) => (p.selected ? '#FFF' : '#5f6368')}; + font-family: 'Barlow'; + font-size: 0.8125rem; + font-style: normal; + font-weight: 600; + line-height: 0rem; /* 0% */ + letter-spacing: 0.00813rem; + border: none; +`; + +export const FooterContainer = styled.div` + display: flex; + padding: 1.125rem 1.875rem; + flex-direction: column; + justify-content: center; + align-items: center; +`; + +export const AddUserBtn = styled.button` + height: 3rem; + padding: 0.5rem 1rem; + width: 100%; + border-radius: 0.375rem; + font-family: 'Barlow'; + font-size: 0.9375rem; + font-style: normal; + font-weight: 500; + line-height: 0rem; + letter-spacing: 0.00938rem; + background: #618aff; + box-shadow: 0px 2px 10px 0px rgba(97, 138, 255, 0.5); + border: none; + color: #fff; + &:disabled { + border: 1px solid rgba(0, 0, 0, 0.07); + background: rgba(0, 0, 0, 0.04); + color: rgba(142, 150, 156, 0.85); + cursor: not-allowed; + box-shadow: none; + } +`; + +export const AssignUserContainer = styled.div` + display: flex; + flex-direction: column; + width: 100%; + position: relative; +`; + +export const UserInfoContainer = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: absolute; + top: -2.5rem; + left: 0; + right: 0; +`; + +export const AssignRoleUserImage = styled.img` + width: 5rem; + height: 5rem; + border-radius: 50%; + background: #dde1e5; + border: 4px solid #fff; + object-fit: cover; +`; + +export const AssignRoleUsername = styled.p` + color: #3c3f41; + text-align: center; + font-family: 'Barlow'; + font-size: 1.25rem; + font-style: normal; + font-weight: 500; + line-height: 1.625rem; + margin-top: 0.69rem; + margin-bottom: 0; + text-transform: capitalize; +`; + +export const UserRolesContainer = styled.div` + padding: 3.25rem 3rem 3rem 3rem; + margin-top: 3.25rem; +`; + +export const UserRolesTitle = styled.h2` + color: #3c3f41; + font-family: 'Barlow'; + font-size: 1.625rem; + font-style: normal; + font-weight: 800; + line-height: 1.625rem; + margin-bottom: 2.81rem; +`; + +export const RolesContainer = styled.div` + display: flex; + flex-direction: column; +`; + +export const RoleContainer = styled.div` + display: flex; + align-items: center; + margin-bottom: 1rem; +`; + +export const Checkbox = styled.input` + margin-right: 1rem; + width: 1rem; + height: 1rem; +`; + +export const Label = styled.label` + margin-bottom: 0; + color: #1e1f25; + font-family: 'Barlow'; + font-size: 0.9375rem; + font-style: normal; + font-weight: 500; + line-height: 1.125rem; +`; + +export const AssingUserBtn = styled.button` + height: 3rem; + padding: 0.5rem 1rem; + width: 100%; + border-radius: 0.375rem; + font-family: 'Barlow'; + font-size: 0.9375rem; + font-style: normal; + font-weight: 500; + line-height: 0rem; + letter-spacing: 0.00938rem; + background: #618aff; + box-shadow: 0px 2px 10px 0px rgba(97, 138, 255, 0.5); + border: none; + margin-top: 3rem; + color: #fff; + &:disabled { + border: 1px solid rgba(0, 0, 0, 0.07); + background: rgba(0, 0, 0, 0.04); + color: rgba(142, 150, 156, 0.85); + cursor: not-allowed; + box-shadow: none; + } +`;