Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…de-zap into feat/752-tag-colorization
  • Loading branch information
vi-wolhwa committed Oct 14, 2024
2 parents 5d7268c + 4df2f8a commit 2dd0d29
Show file tree
Hide file tree
Showing 33 changed files with 719 additions and 167 deletions.
75 changes: 0 additions & 75 deletions .github/workflows/frontend_cd.yml

This file was deleted.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "code-zap",
"version": "1.1.2",
"version": "1.1.3",
"description": "",
"main": "index.js",
"scripts": {
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/components/ContactUs/ContactUs.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import styled from '@emotion/styled';

export const ContactUSButton = styled.button`
cursor: pointer;
`;

export const Form = styled.form`
display: flex;
flex-direction: column;
gap: 1.25rem;
`;
111 changes: 111 additions & 0 deletions frontend/src/components/ContactUs/ContactUs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { useInput, useInputWithValidate, useToggle } from '@/hooks';
import { useToast } from '@/hooks/useToast';
import { validateEmail } from '@/service/validates';
import { theme } from '@/style/theme';

import { Button, Input, Modal, Text, Textarea } from '..';
import * as S from './ContactUs.style';

const ContactUs = () => {
const [isModalOpen, toggleModal] = useToggle();
const [message, handleMessage, resetMessage] = useInput('');
const {
value: email,
handleChange: handleEmail,
resetValue: resetEmail,
errorMessage: emailErrorMessage,
} = useInputWithValidate('', validateEmail);

const { failAlert, successAlert } = useToast();

const isValidContents = message.trim().length !== 0;

const handleSubmit = (e: React.FormEvent<HTMLFormElement> | React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();

if (!isValidContents || emailErrorMessage) {
return;
}

submitForm();
};

const submitForm = async () => {
const res = await sendData();

if (!res.ok) {
failAlert('보내기에 실패했습니다. 계속 실패한다면 이메일로 제보 부탁드립니다.');

return;
}

successSubmit();
successAlert('보내기 완료! 소중한 의견 감사합니다:)');
};

const sendData = () => {
const URL = process.env.GOOGLE_URL || '';

return fetch(URL, {
method: 'POST',
mode: 'no-cors',
body: JSON.stringify({ message, email }),
headers: {
'Content-Type': 'application/json',
},
});
};

const successSubmit = () => {
resetForm();
toggleModal();
};

const resetForm = () => {
resetEmail();
resetMessage();
};

return (
<>
<S.ContactUSButton onClick={toggleModal}>
<Text.Medium weight='bold' color={theme.color.light.secondary_800}>
문의하기
</Text.Medium>
</S.ContactUSButton>
<Modal isOpen={isModalOpen} toggleModal={toggleModal} size='large'>
<Modal.Header>문의하기</Modal.Header>
<Modal.Body>
<S.Form onSubmit={handleSubmit}>
<Text.Medium as='p' color={theme.color.light.secondary_500}>
질문/피드백을 편하게 남겨주세요! 여러분의 의견은 더 나은 서비스를 만드는 데 큰 도움이 됩니다. <br />
이미지 등을 함께 보내실 경우 [email protected]으로 직접 이메일을 보내실 수 있습니다.
</Text.Medium>
<Textarea id='voc' variant='outlined'>
<Textarea.Label htmlFor={'voc'}>무엇을 도와드릴까요?</Textarea.Label>
<Textarea.TextField minRows={5} maxRows={10} value={message} onChange={handleMessage} />
</Textarea>
<Text.Medium as='p' color={theme.color.light.secondary_500}>
답변이 필요하시면 아래 이메일 주소를 남겨주세요. 이메일은 오직 답변을 위해서만 사용됩니다 :)
</Text.Medium>
<Input variant='outlined' isValid={!emailErrorMessage}>
<Input.Label>이메일 (선택)</Input.Label>
<Input.TextField value={email} onChange={handleEmail} />
<Input.HelperText>{emailErrorMessage}</Input.HelperText>
</Input>
</S.Form>
</Modal.Body>
<Modal.Footer>
<Button onClick={toggleModal} variant='outlined'>
닫기
</Button>
<Button disabled={isValidContents && !emailErrorMessage ? false : true} onClick={handleSubmit}>
보내기
</Button>
</Modal.Footer>
</Modal>
</>
);
};

export default ContactUs;
9 changes: 3 additions & 6 deletions frontend/src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Text } from '@/components';
import { ContactUs, Text } from '@/components';
import { useAuth } from '@/hooks/authentication';

import * as S from './Footer.style';
Expand All @@ -19,11 +19,8 @@ const Footer = () => {
</Text.Small>{' '}
© All rights reserved.
</Text.Small>
<S.ContactEmail href='mailto:[email protected]'>
<Text.Small color='inherit' weight='bold'>
문의 :
</Text.Small>{' '}
<Text.Small color='inherit'>[email protected]</Text.Small>{' '}
<S.ContactEmail>
<ContactUs />
</S.ContactEmail>
</S.FooterContainer>
);
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Header/Header.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const HeaderContainer = styled.nav`
padding: 0 2rem;
background: white;
border-bottom: 2px solid ${theme.color.light.secondary_200};
border-bottom: 1px solid ${theme.color.light.secondary_300};
@media (max-width: 768px) {
padding: 0 1rem;
Expand Down Expand Up @@ -99,7 +99,7 @@ export const MobileMenuContainer = styled.div`
}
`;

export const HamburgerIconWrapper = styled.div`
export const HamburgerIconWrapper = styled.button`
display: none;
@media (max-width: 768px) {
Expand Down
74 changes: 49 additions & 25 deletions frontend/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useEffect } from 'react';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { Link, useLocation } from 'react-router-dom';

import { CodeZapLogo, HamburgerIcon, PlusIcon } from '@/assets/images';
import { Button, Flex, Heading, Text } from '@/components';
import { Button, ContactUs, Flex, Heading, Text } from '@/components';
import { ToastContext } from '@/contexts';
import { useCustomContext, useToggle } from '@/hooks';
import { useCustomContext, useCustomNavigate, useToggle } from '@/hooks';
import { useAuth } from '@/hooks/authentication/useAuth';
import { usePressESC } from '@/hooks/usePressESC';
import { useScrollDisable } from '@/hooks/useScrollDisable';
Expand All @@ -19,7 +19,7 @@ const Header = ({ headerRef }: { headerRef: React.RefObject<HTMLDivElement> }) =
const [menuOpen, toggleMenu] = useToggle();
const { failAlert } = useCustomContext(ToastContext);
const location = useLocation();
const navigate = useNavigate();
const navigate = useCustomNavigate();

useScrollDisable(menuOpen);
usePressESC(menuOpen, toggleMenu);
Expand Down Expand Up @@ -56,6 +56,7 @@ const Header = ({ headerRef }: { headerRef: React.RefObject<HTMLDivElement> }) =
<S.NavContainer>
{!isChecking && isLogin && <NavOption route={END_POINTS.MY_TEMPLATES} name='내 템플릿' />}
<NavOption route={END_POINTS.TEMPLATES_EXPLORE} name='구경가기' />
<ContactUs />
</S.NavContainer>
<S.NavContainer>
<S.MobileHiddenButton
Expand All @@ -64,16 +65,24 @@ const Header = ({ headerRef }: { headerRef: React.RefObject<HTMLDivElement> }) =
weight='bold'
hoverStyle='none'
onClick={handleTemplateUploadButton}
aria-description='템플릿 작성 페이지로 이동됩니다.'
>
<PlusIcon aria-label='' />새 템플릿
<PlusIcon />새 템플릿
</S.MobileHiddenButton>

{!isChecking && isLogin ? <LogoutButton /> : <LoginButton />}
</S.NavContainer>
</S.HeaderMenu>
<S.MobileMenuContainer>
<Button variant='outlined' size='small' weight='bold' hoverStyle='none' onClick={handleTemplateUploadButton}>
<PlusIcon aria-label='' />새 템플릿
<Button
variant='outlined'
size='small'
weight='bold'
hoverStyle='none'
onClick={handleTemplateUploadButton}
aria-description='템플릿 작성 페이지로 이동됩니다.'
>
<PlusIcon />새 템플릿
</Button>
<HeaderMenuButton menuOpen={menuOpen} toggleMenu={toggleMenu} />
</S.MobileMenuContainer>
Expand All @@ -83,24 +92,39 @@ const Header = ({ headerRef }: { headerRef: React.RefObject<HTMLDivElement> }) =
);
};

const Logo = () => (
<Link to={END_POINTS.HOME}>
<Flex align='center' gap='0.5rem'>
<CodeZapLogo aria-label='로고 버튼' />
<Heading.XSmall color={theme.color.light.primary_500}>코드잽</Heading.XSmall>
</Flex>
</Link>
);
const Logo = () => {
const location = useLocation();
const isLandingPage = location.pathname === '/';

const NavOption = ({ route, name }: { route: string; name: string }) => (
<Link to={route}>
<S.NavOptionButton>
<Text.Medium weight='bold' color={theme.color.light.secondary_800}>
{name}
</Text.Medium>
</S.NavOptionButton>
</Link>
);
return (
<Link to={END_POINTS.HOME}>
<Flex align='center' gap='0.5rem'>
<CodeZapLogo aria-label='로고 버튼' />
<Heading.XSmall color={isLandingPage ? theme.color.light.primary_500 : theme.color.light.secondary_800}>
코드잽
</Heading.XSmall>
</Flex>
</Link>
);
};

const NavOption = ({ route, name }: { route: string; name: string }) => {
const location = useLocation();
const isCurrentPage = location.pathname === route;

return (
<Link to={route}>
<S.NavOptionButton>
<Text.Medium
weight='bold'
color={isCurrentPage ? theme.color.light.primary_500 : theme.color.light.secondary_800}
>
{name}
</Text.Medium>
</S.NavOptionButton>
</Link>
);
};

const LogoutButton = () => {
const { mutateAsync } = useLogoutMutation();
Expand All @@ -125,7 +149,7 @@ const LoginButton = () => (
);

const HeaderMenuButton = ({ menuOpen, toggleMenu }: { menuOpen: boolean; toggleMenu: () => void }) => (
<S.HamburgerIconWrapper>
<S.HamburgerIconWrapper aria-label='메뉴'>
<HamburgerIcon menuOpen={menuOpen} onClick={toggleMenu} />
</S.HamburgerIconWrapper>
);
Expand Down
Loading

0 comments on commit 2dd0d29

Please sign in to comment.