Sending request form (#141)

This commit is contained in:
Maria Rushkova 2021-11-29 18:04:07 +01:00 committed by GitHub
parent faef8d0a02
commit 49417a5c25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 167 additions and 53 deletions

View File

@ -123,7 +123,6 @@ const Bubble = styled.div`
const Drag = styled.div` const Drag = styled.div`
position: absolute; position: absolute;
overflow: hidden;
`; `;
ReactDOM.render( ReactDOM.render(

View File

@ -32,8 +32,7 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
); );
const { setModal } = useModal(ProfileModalName); const { setModal } = useModal(ProfileModalName);
const { contact, setBlocked, setIsUntrustworthy, setIsUserFriend } = const { contact, setBlocked, setIsUntrustworthy } = useManageContact(id);
useManageContact(id);
if (!contact) return null; if (!contact) return null;
return ( return (
@ -54,14 +53,18 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) {
<MenuSection> <MenuSection>
<MenuItem <MenuItem
onClick={() => { onClick={() => {
setModal({ id, renamingState: false }); setModal({ id, renamingState: false, requestState: false });
}} }}
> >
<ProfileSvg width={16} height={16} /> <ProfileSvg width={16} height={16} />
<MenuText>View Profile</MenuText> <MenuText>View Profile</MenuText>
</MenuItem> </MenuItem>
{!contact.isFriend && ( {!contact.isFriend && (
<MenuItem onClick={() => setIsUserFriend(true)}> <MenuItem
onClick={() => {
setModal({ id, requestState: true });
}}
>
<AddContactSvg width={16} height={16} /> <AddContactSvg width={16} height={16} />
<MenuText>Send Contact Request</MenuText> <MenuText>Send Contact Request</MenuText>
</MenuItem> </MenuItem>

View File

@ -3,15 +3,17 @@ import styled from "styled-components";
interface UserIconProps { interface UserIconProps {
memberView?: boolean; memberView?: boolean;
modalView?: boolean;
} }
export const UserIcon = ({ memberView }: UserIconProps) => { export const UserIcon = ({ memberView, modalView }: UserIconProps) => {
return ( return (
<Icon <Icon
viewBox="0 0 34 34" viewBox="0 0 34 34"
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
memberView={memberView} memberView={memberView}
modalView={modalView}
> >
<ellipse cx="17" cy="10.3883" rx="6.94445" ry="6.94445" /> <ellipse cx="17" cy="10.3883" rx="6.94445" ry="6.94445" />
<path <path
@ -24,8 +26,10 @@ export const UserIcon = ({ memberView }: UserIconProps) => {
}; };
const Icon = styled.svg<UserIconProps>` const Icon = styled.svg<UserIconProps>`
width: ${({ memberView }) => (memberView ? "20px" : "34px")}; width: ${({ memberView, modalView }) =>
height: ${({ memberView }) => (memberView ? "20px" : "34px")}; memberView ? "20px" : modalView ? "80px" : "34px"};
height: ${({ memberView, modalView }) =>
memberView ? "20px" : modalView ? "80px" : "34px"};
& > path, & > path,
& > ellipse { & > ellipse {

View File

@ -9,7 +9,13 @@ import { AddIcon } from "../Icons/AddIcon";
import { textMediumStyles } from "../Text"; import { textMediumStyles } from "../Text";
import { Modal } from "./Modal"; import { Modal } from "./Modal";
import { ButtonSection, Heading, Section } from "./ModalStyle"; import {
ButtonSection,
Heading,
Hint,
inputStyles,
Section,
} from "./ModalStyle";
export const EditModalName = "editModal"; export const EditModalName = "editModal";
@ -96,26 +102,10 @@ const Label = styled.p`
${textMediumStyles} ${textMediumStyles}
`; `;
const Hint = styled.p`
color: ${({ theme }) => theme.secondary};
font-size: 12px;
line-height: 16px;
`;
const NameInput = styled.input` const NameInput = styled.input`
padding: 14px 70px 14px 8px; padding: 14px 70px 14px 8px;
background: ${({ theme }) => theme.inputColor};
border-radius: 8px;
border: 1px solid ${({ theme }) => theme.inputColor};
color: ${({ theme }) => theme.primary};
outline: none;
${textMediumStyles} ${inputStyles}
&:focus {
outline: none;
caret-color: ${({ theme }) => theme.notificationColor};
}
`; `;
const LogoSection = styled.div` const LogoSection = styled.div`

View File

@ -1,4 +1,4 @@
import styled from "styled-components"; import styled, { css } from "styled-components";
import { textMediumStyles } from "../Text"; import { textMediumStyles } from "../Text";
@ -29,3 +29,24 @@ export const ButtonSection = styled(Section)`
align-items: center; align-items: center;
position: relative; position: relative;
`; `;
export const Hint = styled.p`
color: ${({ theme }) => theme.secondary};
font-size: 12px;
line-height: 16px;
`;
export const inputStyles = css`
background: ${({ theme }) => theme.inputColor};
border-radius: 8px;
border: 1px solid ${({ theme }) => theme.inputColor};
color: ${({ theme }) => theme.primary};
outline: none;
${textMediumStyles}
&:focus {
outline: 1px solid ${({ theme }) => theme.tertiary};
caret-color: ${({ theme }) => theme.notificationColor};
}
`;

View File

@ -13,10 +13,16 @@ import { EditSvg } from "../Icons/EditIcon";
import { LeftIconSvg } from "../Icons/LeftIcon"; import { LeftIconSvg } from "../Icons/LeftIcon";
import { UntrustworthIcon } from "../Icons/UntrustworthIcon"; import { UntrustworthIcon } from "../Icons/UntrustworthIcon";
import { UserIcon } from "../Icons/UserIcon"; import { UserIcon } from "../Icons/UserIcon";
import { textMediumStyles } from "../Text"; import { textMediumStyles, textSmallStyles } from "../Text";
import { Modal } from "./Modal"; import { Modal } from "./Modal";
import { ButtonSection, Heading, Section } from "./ModalStyle"; import {
ButtonSection,
Heading,
Hint,
inputStyles,
Section,
} from "./ModalStyle";
export const ProfileModalName = "profileModal" as const; export const ProfileModalName = "profileModal" as const;
@ -24,11 +30,12 @@ export type ProfileModalProps = {
id: string; id: string;
image?: string; image?: string;
renamingState?: boolean; renamingState?: boolean;
requestState?: boolean;
}; };
export const ProfileModal = () => { export const ProfileModal = () => {
const { props } = useModal(ProfileModalName); const { props } = useModal(ProfileModalName);
const { id, image, renamingState } = useMemo( const { id, image, renamingState, requestState } = useMemo(
() => (props ? props : { id: "" }), () => (props ? props : { id: "" }),
[props] [props]
); );
@ -44,6 +51,12 @@ export const ProfileModal = () => {
setRenaming(renamingState ?? false); setRenaming(renamingState ?? false);
}, [renamingState]); }, [renamingState]);
const [request, setRequest] = useState("");
const [requestCreation, setRequestCreation] = useState(requestState ?? false);
useEffect(() => {
setRequestCreation(requestState ?? false);
}, [requestState]);
const { const {
contact, contact,
setBlocked, setBlocked,
@ -55,29 +68,35 @@ export const ProfileModal = () => {
if (!contact) return null; if (!contact) return null;
return ( return (
<Modal name={ProfileModalName} className="profile"> <Modal
name={ProfileModalName}
className={`${!requestCreation && "profile"}`}
>
<Section> <Section>
<Heading>{id.slice(0, 10)}s Profile</Heading> <Heading>{id.slice(0, 10)}s Profile</Heading>
</Section> </Section>
<ProfileSection> <ProfileSection>
<NameSection> <NameSection className={`${requestCreation && "small"}`}>
{image ? ( {image ? (
<ProfileIcon <ProfileIcon
style={{ style={{
backgroundImage: `url(${image}`, backgroundImage: `url(${image}`,
}} }}
className={`${requestCreation && "small"}`}
/> />
) : ( ) : (
<UserIcon /> <UserIcon modalView={!requestCreation} />
)} )}
<UserNameWrapper> <UserNameWrapper>
<UserName>{contact.customName ?? id.slice(0, 10)}</UserName> <UserName className={`${requestCreation && "small"}`}>
{contact.customName ?? id.slice(0, 10)}
</UserName>
{contact.isUntrustworthy && <UntrustworthIcon />} {contact.isUntrustworthy && <UntrustworthIcon />}
{!renaming && ( {!renaming && (
<button onClick={() => setRenaming(true)}> <button onClick={() => setRenaming(true)}>
{" "} {" "}
<EditSvg width={24} height={24} /> {!requestCreation && <EditSvg width={24} height={24} />}
</button> </button>
)} )}
</UserNameWrapper> </UserNameWrapper>
@ -105,16 +124,40 @@ export const ProfileModal = () => {
</NameInputWrapper> </NameInputWrapper>
) : ( ) : (
<> <>
<UserAddressWrapper> <UserAddressWrapper className={`${requestCreation && "small"}`}>
<UserAddress>Chatkey: {id.slice(0, 30)}</UserAddress> {requestCreation ? (
<UserAddress>
{id.slice(0, 10)}...{id.slice(-3)}
</UserAddress>
) : (
<>
<UserAddress className={`${requestCreation && "small"}`}>
Chatkey: {id.slice(0, 30)}
</UserAddress>
<CopyButton onClick={() => copy(id)}> <CopyButton onClick={() => copy(id)}>
<CopySvg width={24} height={24} /> <CopySvg width={24} height={24} />
</CopyButton> </CopyButton>
</>
)}
</UserAddressWrapper> </UserAddressWrapper>
<EmojiKey>🎩🍞🥑🦍🌈📡💅🏻🔔👵🅱</EmojiKey>{" "} <EmojiKey className={`${requestCreation && "small"}`}>
🎩🍞🥑🦍🌈📡💅🏻🔔👵🅱
</EmojiKey>{" "}
</> </>
)} )}
{requestCreation && (
<RequestSection>
<Hint>{request.length}/280</Hint>
<RequestInput
value={request}
placeholder="Say who you are / why you want to became a contact..."
maxLength={280}
onInput={(e) => setRequest(e.currentTarget.value)}
required
/>
</RequestSection>
)}
</ProfileSection> </ProfileSection>
<ButtonSection> <ButtonSection>
{renaming ? ( {renaming ? (
@ -132,6 +175,22 @@ export const ProfileModal = () => {
Apply nickname Apply nickname
</Btn> </Btn>
</> </>
) : requestCreation ? (
<>
<BackBtn onClick={() => setRequestCreation(false)}>
<LeftIconSvg width={28} height={28} />
</BackBtn>
<Btn
disabled={!request}
onClick={() => {
setIsUserFriend(true),
setRequestCreation(false),
setRequest("");
}}
>
Send Contact Request
</Btn>
</>
) : ( ) : (
<> <>
{!contact.isFriend && !isUser && ( {!contact.isFriend && !isUser && (
@ -161,7 +220,7 @@ export const ProfileModal = () => {
: "Mark as Untrustworthy"} : "Mark as Untrustworthy"}
</ProfileBtn> </ProfileBtn>
{!contact.isFriend && ( {!contact.isFriend && (
<Btn onClick={() => setIsUserFriend(true)}> <Btn onClick={() => setRequestCreation(true)}>
Send Contact Request Send Contact Request
</Btn> </Btn>
)} )}
@ -184,6 +243,10 @@ const NameSection = styled.div`
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-bottom: 16px; margin-bottom: 16px;
&.small {
margin-bottom: 0;
}
`; `;
const ProfileIcon = styled.div` const ProfileIcon = styled.div`
@ -199,6 +262,11 @@ const ProfileIcon = styled.div`
flex-shrink: 0; flex-shrink: 0;
position: relative; position: relative;
cursor: pointer; cursor: pointer;
&.small {
width: 64px;
height: 64px;
}
`; `;
const UserNameWrapper = styled.div` const UserNameWrapper = styled.div`
@ -219,6 +287,12 @@ const UserName = styled.p`
line-height: 30px; line-height: 30px;
letter-spacing: -0.2px; letter-spacing: -0.2px;
margin-right: 8px; margin-right: 8px;
&.small {
font-size: 17px;
line-height: 24px;
margin-right: 0;
}
`; `;
const UserTrueName = styled.p` const UserTrueName = styled.p`
@ -234,6 +308,10 @@ const UserAddressWrapper = styled.div`
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-bottom: 24px; margin-bottom: 24px;
&.small {
margin-bottom: 8px;
}
`; `;
const UserAddress = styled.p` const UserAddress = styled.p`
@ -243,6 +321,12 @@ const UserAddress = styled.p`
color: ${({ theme }) => theme.secondary}; color: ${({ theme }) => theme.secondary};
${textMediumStyles} ${textMediumStyles}
&.small {
margin-right: 0;
${textSmallStyles}
}
`; `;
const EmojiKey = styled.div` const EmojiKey = styled.div`
display: flex; display: flex;
@ -253,6 +337,10 @@ const EmojiKey = styled.div`
font-size: 15px; font-size: 15px;
line-height: 14px; line-height: 14px;
letter-spacing: 0.2px; letter-spacing: 0.2px;
&.small {
${textSmallStyles}
}
`; `;
const ProfileBtn = styled.button` const ProfileBtn = styled.button`
@ -331,16 +419,25 @@ const NameInputWrapper = styled.div`
const NameInput = styled.input` const NameInput = styled.input`
width: 328px; width: 328px;
padding: 11px 16px; padding: 11px 16px;
background: ${({ theme }) => theme.inputColor};
border-radius: 8px;
border: 1px solid ${({ theme }) => theme.border};
color: ${({ theme }) => theme.primary};
outline: none;
${textMediumStyles} ${inputStyles}
`;
&:focus {
outline: 1px solid ${({ theme }) => theme.tertiary}; const RequestSection = styled.div`
caret-color: ${({ theme }) => theme.notificationColor}; width: 100%;
} display: flex;
flex-direction: column;
align-items: flex-end;
margin: 16px 0;
`;
const RequestInput = styled.textarea`
width: 100%;
height: 152px;
padding: 10px 16px;
resize: none;
margin-top: 16px;
font-family: "Inter";
${inputStyles}
`; `;