Sending request form (#141)
This commit is contained in:
parent
faef8d0a02
commit
49417a5c25
|
@ -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(
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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`
|
||||||
|
|
|
@ -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};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
|
@ -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}
|
||||||
`;
|
`;
|
||||||
|
|
Loading…
Reference in New Issue