Skip to content

Commit

Permalink
[배포] 메타태그, 사이드바, 앰플리튜드, 이메일 valid check ... (#88)
Browse files Browse the repository at this point in the history
* fix:: 새 탭에서 열기 버그 fix
- noopener, noreferrer 속성을 통해, 새 탭으로 연 창에서도 새탭 열기 가능하도록

* fix:: major category 선택 모달 디자인

* feat:: 새로운 시간표 추가 버튼 구현

* mod:: Timetable 컴포넌트 밖에서도 BottomSheet 열고 닫을 수 있도록 코드 수정

* mod:: BottomSheet Position 조정

* fix:: Attendance 진행 시 포인트 히스토리도 업데이트

* mod:: ticket -> key로 워딩 수정

* feat:: Reading Key Expiration Card 구현 & API 적용

* design:: Figma Style과 동기화 & 반응형 적용

* feat:: setInterval을 통한 자동 카운트 다운

* feat:: 캐릭터 변경 성공 시 스크롤 up

* feat:: Change Password Error Handling

* feat:: Change Profile Error Handling

* mod:: Apply Btn 스타일 변경

* fix:: Response가 오지 않을 때 처리

* mod:: MyPage 게시글 모아보기에서 사진 안 보이도록 수정

* feat:: My Community Page Search Param을 통해 url 분기

* mod:: My Community 댓글 카드 디자인 수정

* feat:: <head>에 Amplitude 추가

* Feat/temp password (#67)

* feat:: 비밀번호 찾기 페이지 연결

* feat:: 비밀번호 리셋 이후 모달 창으로 로그인 네비게이션

---------

Co-authored-by: halion <[email protected]>

* feat: make Dockerfile

* mod: Dockerfile KU-key에 맞추어 수정

* feat:: 방송국 단체 youtube link 연결 및 단체 변경 (#71)

* feat:: serve를 통한 build file 실행

* fix:: 오타 수정

* chore:: Create docker-image.yml

* chore:: 도커 빌드 때 ts도 설치

* chore:: Panda init도 실행

* fix::yarn 깔기 전에 panda init?

* fix:: Panda init 롤백

* chore:: build 때 tsc 제외

* chore:: Local 환경과 똑같이 세팅

* fix:: 순서 변경

* fix:: Drop Production

* fix:: frozen lockfile & ignore scripts 속성 주기

* fix:: tsc -noEmit 설정

* test:: yarn dev로 실행해보기

* chore:: vite config에 절대경로 명시

* fix:: DockerFile

* Revert "fix:: DockerFile"

This reverts commit e0c3f37.

* Revert "chore:: vite config에 절대경로 명시"

This reverts commit 75ee8d9.

* chore:: yarn install & serve with serve

* fix:: Panda CSS Config 경로 수정

* fix:: DockerFile 실행 전 panda config copy

* fix:: dockerfile copy

* fix: 처음에 Copy하기

* feat: main-deploy.yml

* feat:: dev-deploy.yml

* #38 (#68)

* [#38] feat:: 삭제된 댓글 Username 지정

* feat:: 게시글 댓글 익명성에 따른 ui 반영

* fix:: isAuthor 인자 추가하기

* [#38] feat:: 삭제된 댓글 Username 지정

* feat:: 게시글 댓글 익명성에 따른 ui 반영

* fix:: isAuthor 인자 추가하기

* design:: Lecture 추가를 위한 버튼 삭제 & BottomSheet Drawer 정상화

* feat:: 빈 학기에 들어갈 시 자동 타임테이블 추가 :RealCookie:

* feat:: My Timetable Page에서는 Null table이 보이지 않도록 처리

* fix:: merge conflict

* Feat/comment delete api (#69)

* [#38] feat:: 삭제된 댓글 Username 지정

* feat:: 게시글 댓글 익명성에 따른 ui 반영

* fix:: isAuthor 인자 추가하기

* feat:: 댓글 삭제 api 연결

- 삭제된 댓글 기준 util button 감추기
- 댓글 삭제 이후 invalidation queryKey 커스텀 훅으로 핸들링

* feat:: 댓글 작성시 최상단에 배치

- 리렌더링할 때 백엔드 api에 따라 배치

* fix:: queryKey parse Type error

* feat:: 삭제된 댓글 UI 버튼 visibility 만 조정

* mod: PR Review 반영 - Bottom Sheet State는Sheet 컴포넌트 내에서 관리

* fix: Dummy Timetable이어도 서버로 요청 보내는 문제

* mod: INIT data 중복 제거

* chore: Add Amplitude Library

* mod: Amplitude init script tag에서 tsx provider로

* feat:: Docker 버리고 S3 정적 배포

* test: deploy 돌아가는지 테스트

* fix: aws cli 설치 추가

* fix: Cli 설치과정 삭제, CloudFront invalidation 로직 변경

* test: dev 브랜치로 testing하던거 정상화

* feat: .env 파일 등록

* test: dev -> main

* typo: change deploy.yml name

* rename: Academic Calendar 로직 & 컴포넌트 Calendar로 합병

* feat: Banner API

* mod: isLoading으로 스켈레톤 관리

* fix: 사진 로딩이 덜 되어 화면 깜빡거리는 현상

* fix: 스켈레톤 배너 width가 제대로 안 먹는 버그

* feat: MetaTag Component

* feat: Club Page 메타태그 적용

* mod: Change Club Description

* feat: Academic Schedule Page 메타태그 적용

* feat: 사이드 탭 구현 (#79)

* feat: side-tab component 구현

* chore: default 캐릭터 이미지 교체

* feat: side-tab nav 연결

* feat: 사이드 탭 유저 정보 보여주기

* chore: 불필요한 type export 없애기

* chore: sheet 필수 요소 title, description srOnly 로 주입

* chore: import 이름 수정

* feat: pr 리뷰 반영

* fix: 회원가입 이메일 인증코드 valid check (#85)

* feat: menu에 로그인 항목 넣기 (#87)

* feat: menu에 로그인 항목 넣기

* feat: input fontsize smDown 인 경우 16px 로 수정

* fix: Footer 라우팅 버그, 메뉴 수정

* fix: Routing 달라질 때 기본 Scroll Up

* fix: timetable 라우팅 내에서는 스크롤이 초기화되지 않는 버그

* mod: PR 반영
- 불필요한 useEffect 제거

* fix: curPath 바뀔 때 항상 Scroll Up
- useScrollUp 훅 만료

* fix: useScrollUp 훅 만료

---------

Co-authored-by: Seungmin Cha <[email protected]>
  • Loading branch information
halionaz and Virtuso1225 authored Oct 1, 2024
1 parent 479cd47 commit 9f4539f
Show file tree
Hide file tree
Showing 29 changed files with 702 additions and 63 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/assets/Logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>KU-key</title>
</head>
<body>
<div id="root"></div>
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
"preview": "vite preview"
},
"dependencies": {
"@amplitude/analytics-browser": "^2.11.6",
"@hookform/resolvers": "^3.3.4",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-menubar": "^1.1.1",
Expand Down
40 changes: 40 additions & 0 deletions panda.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
shadowRecipe,
tagRecipe,
textStyles,
sheetRecipe,
} from './src/lib/recipes/index'
import { tokenToRem } from './src/lib/constants/tokenToRem'

Expand Down Expand Up @@ -44,6 +45,7 @@ export default defineConfig({
reactionButton: reactionTagRecipe,
carouselButton: carouselButtonRecipe,
postCard: postCardRecipe,
sheet: sheetRecipe,
},
slotRecipes: {
menubar: menubar,
Expand Down Expand Up @@ -94,6 +96,44 @@ export default defineConfig({
from: { transform: 'scale(1)', opacity: 1 },
to: { transform: 'scale(0.95)', opacity: 0 },
},
slideInFromTop: {
from: { transform: 'translateY(-100%)' },
to: { transform: 'translateY(0)' },
},
slideOutToTop: {
from: { transform: 'translateY(0)' },
to: { transform: 'translateY(-100%)' },
},
slideInFromBottom: {
from: { transform: 'translateY(100%)' },
to: { transform: 'translateY(0)' },
},
slideOutToBottom: {
from: { transform: 'translateY(0)' },
to: { transform: 'translateY(100%)' },
},
slideInFromLeft: {
from: { transform: 'translateX(-100%)' },
to: { transform: 'translateX(0)' },
},
slideOutToLeft: {
from: { transform: 'translateX(0)' },
to: { transform: 'translateX(-100%)' },
},
slideInFromRight: {
from: { transform: 'translateX(100%)' },
to: { transform: 'translateX(0)' },
},
slideOutToRight: {
from: { transform: 'translateX(0)' },
to: { transform: 'translateX(100%)' },
},
},
breakpoints: {
xs: '390px',
sm: '580px',
md: '900px',
lg: '1200px',
},
},
},
Expand Down
5 changes: 5 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useRoutes } from 'react-router-dom'

import routes from '@/lib/router/router'
import AmplitudeProvider from '@/util/AmplitudeProvider'
import AuthProvider from '@/util/auth/AuthProvider'
import ScrollToTop from '@/util/ScrollToTop'

const queryClient = new QueryClient({
defaultOptions: {
queries: {
Expand All @@ -19,6 +22,8 @@ function App() {
<QueryClientProvider client={queryClient}>
{/* <ReactQueryDevtools initialIsOpen={false} /> */}
<AuthProvider />
<AmplitudeProvider />
<ScrollToTop />
{router}
</QueryClientProvider>
)
Expand Down
Binary file modified src/assets/CharacterDefault.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 37 additions & 14 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { css } from '@styled-system/css'
import { useCallback, useState } from 'react'
import { Link } from 'react-router-dom'

// TODO: ADD Instagram & Notion Link
// import instagramIcon from '@/assets/instagram.svg'
import KUkeyLogo from '@/assets/KU-keyLogo.svg'
import mailIcon from '@/assets/mail.svg'
import NoticeModal from '@/components/ui/modal/NoticeModal'
import { HEADER_MESSAGE } from '@/lib/messages/header'
import { footerRouteConfig } from '@/lib/router/footer-route'
import { useAuth } from '@/util/auth/useAuth'
import { useModal } from '@/util/useModal'
// import notionIcon from '@/assets/notion.svg'

const supportApps = [
Expand All @@ -26,8 +32,31 @@ const tabs = css({
})

const Footer = () => {
const { isAuthenticated, authState } = useAuth()
const { isOpen: isModalOpen, handleOpen: handleModalOpen } = useModal(true)
const [modalContent, setModalContent] = useState(HEADER_MESSAGE.NOT_VERIFIED_USER)

const handleNavClick = useCallback(
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, route: string) => {
if (route === 'matching') {
e.preventDefault()
setModalContent(HEADER_MESSAGE.NOT_READY)
handleModalOpen()
return
}
if (!isAuthenticated) return // 미로그인 유저
if (!authState) {
// 인증 안 된 유저
e.preventDefault()
setModalContent(HEADER_MESSAGE.NOT_VERIFIED_USER)
handleModalOpen()
}
},
[authState, handleModalOpen, isAuthenticated],
)

return (
<div
<footer
className={css({
w: 'full',
borderTop: '1.211px solid {colors.lightGray.2}',
Expand Down Expand Up @@ -96,20 +125,14 @@ const Footer = () => {
h: 25,
})}
>
<Link to="/" className={tabs}>
MY PAGE
</Link>
<Link to="/timetable" className={tabs}>
TIMETABLE
</Link>
<Link to="/community" className={tabs}>
COMMUNITY
</Link>
<Link to="/matching" className={tabs}>
1:1 MATCHING
</Link>
{footerRouteConfig.map(nav => (
<Link key={nav.route} to={`/${nav.route}`} className={tabs} onClick={e => handleNavClick(e, nav.route)}>
{nav.navName}
</Link>
))}
</div>
</div>
<NoticeModal isOpen={isModalOpen} content={modalContent} />
</footer>
)
}

Expand Down
63 changes: 41 additions & 22 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import { useLogOut } from '@/api/hooks/auth'
import KUkeyLogo from '@/assets/KU-keyLogo.svg'
import { NavLinkButton } from '@/components/header/NavLinkButton'
import NotifyWindow from '@/components/header/NotifyWindow'
import HeaderMenu from '@/components/HeaderMenu'
import NoticeModal from '@/components/ui/modal/NoticeModal'
import { HEADER_MESSAGE } from '@/lib/messages/header'
import { headerRouteConfig } from '@/lib/router/header-route'
import { useAuth } from '@/util/auth/useAuth'
import { useMediaQuery } from '@/util/useMediaQuery'
import { useModal } from '@/util/useModal'

const Header = () => {
Expand All @@ -24,6 +26,7 @@ const Header = () => {
const { isOpen: isModalOpen, handleOpen: handleModalOpen } = useModal(true)
const [modalContent, setModalContent] = useState(HEADER_MESSAGE.NOT_VERIFIED_USER)
const navigate = useNavigate()
const mediaQuery = useMediaQuery('(max-width: 900px)')
const handleUserButton = useCallback(() => {
isAuthenticated ? mutateSignOut() : navigate('/login')
}, [isAuthenticated, mutateSignOut, navigate])
Expand Down Expand Up @@ -86,7 +89,7 @@ const Header = () => {
bg: 'white',
justifyContent: 'space-between',
alignItems: 'center',
px: { base: '150px', mdDown: 5 },
px: { base: '150px', lgDown: '100px', mdDown: '60px', smDown: '20px' },
})}
>
<nav
Expand Down Expand Up @@ -122,29 +125,45 @@ const Header = () => {
))}
</nav>
<div className={css({ display: 'flex', alignItems: 'center', gap: '30px' })}>
{isAuthenticated && (
<div
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 4,
color: 'darkGray.2',
})}
>
<NotifyWindow />
<Link
to="/mypage"
className={css({ display: 'flex', alignItems: 'center' })}
onClick={e => handleNavClick(e, 'mypage')}
>
<CircleUser size={20} />
</Link>
</div>
)}
<div
className={css({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 4,
color: 'darkGray.2',
})}
>
{isAuthenticated && (
<>
<NotifyWindow />
<Link
to="/mypage"
className={css({ display: 'flex', alignItems: 'center', mdDown: { display: 'none' } })}
onClick={e => handleNavClick(e, 'mypage')}
>
<CircleUser size={20} />
</Link>
</>
)}
{mediaQuery && (
<HeaderMenu
handleNavClick={handleNavClick}
curPath={curPath}
handleUserButton={handleUserButton}
isAuthenticated={isAuthenticated}
/>
)}
</div>

<button
onClick={handleUserButton}
className={css({ cursor: 'pointer', textStyle: 'body1_L', color: 'lightGray.1' })}
className={css({
cursor: 'pointer',
textStyle: 'body1_L',
color: 'lightGray.1',
mdDown: { display: 'none' },
})}
>
{isAuthenticated ? 'Log out' : 'Log in'}
</button>
Expand Down
119 changes: 119 additions & 0 deletions src/components/HeaderMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { css, cva, cx } from '@styled-system/css'
import { Menu } from 'lucide-react'
import { useCallback, useState } from 'react'
import { Link } from 'react-router-dom'

import SideTabLogInLink from '@/components/header/SideTabLogInLink'
import SideTabProfile from '@/components/header/SideTabProfile'
import { Sheet, SheetContent, SheetDescription, SheetTitle, SheetTrigger } from '@/components/ui/sheet'
import { headerRouteConfig } from '@/lib/router/header-route'

interface HeaderProps {
curPath: string
handleNavClick: (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, navName: string) => void
handleUserButton: () => void
isAuthenticated: boolean
}
const HeaderMenu = ({ handleNavClick, curPath, handleUserButton, isAuthenticated }: HeaderProps) => {
const curPathRoot = curPath.split('/')[1]
const [isSheetOpen, setIsSheetOpen] = useState(false)
const handleSheetNavClick = useCallback(
(e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, navName: string) => {
navName !== '1:1 Matching' && setIsSheetOpen(p => !p)
handleNavClick(e, navName)
},
[handleNavClick],
)
const handleSheetCloseLogOut = useCallback(() => {
setIsSheetOpen(false), handleUserButton()
}, [handleUserButton])
return (
<Sheet open={isSheetOpen} onOpenChange={() => setIsSheetOpen(p => !p)}>
<SheetTrigger asChild>
<button className={css({ mdDown: { display: 'flex' }, base: { display: 'none' }, color: 'darkGray.2' })}>
<Menu />
</button>
</SheetTrigger>
<SheetContent className={css({ display: 'flex', flexDir: 'column', py: 15, gap: 10 })} closeButton={false}>
{isAuthenticated ? <SideTabProfile /> : <SideTabLogInLink handleSheetNavClick={handleSheetNavClick} />}
<SheetTitle className={css({ srOnly: true })}>Navigation SideTab</SheetTitle>
<SheetDescription className={css({ srOnly: true })}>For Mobile or medium size screen</SheetDescription>
<nav
className={css({
display: { base: 'flex' },
flexDir: 'column',
gap: '38px',
alignItems: 'flex-start',
textStyle: 'body1_M',
letterSpacing: '-0.4px',
})}
>
{headerRouteConfig.map(nav => {
if (nav.innerTab === undefined) {
return (
<div key={nav.route} className={menuButton({ isSelected: curPathRoot === nav.route })}>
<Link to={`/${nav.route}`} onClick={e => handleSheetNavClick(e, nav.navName)}>
{nav.navName}
</Link>
</div>
)
}
return (
<div
key={nav.route}
className={css({ display: 'flex', flexDir: 'column', alignItems: 'flex-start', gap: 2 })}
>
<div className={cx(menuButton({ isSelected: false }), css({ gap: 0 }))}>{nav.navName}</div>
<div className={css({ display: 'flex', flexDir: 'column', pl: 4, alignItems: 'flex-start', gap: 2 })}>
{nav.innerTab.map((innerTab, index) => (
<div key={innerTab} className={menuButton({ isSelected: curPath === `/${innerTab}` })}>
<Link
to={`/${innerTab}`}
onClick={e => handleSheetNavClick(e, innerTab)}
className={css({ fontSize: 15 })}
>
{index === 0 ? 'My schedule' : 'Friend list'}
</Link>
</div>
))}
</div>
</div>
)
})}
<div className={menuButton({ isSelected: curPathRoot === 'mypage' })}>
<Link to={`/mypage`} onClick={e => handleSheetNavClick(e, 'mypage')}>
My Page
</Link>
</div>
<button
onClick={handleSheetCloseLogOut}
className={css({
cursor: 'pointer',
color: 'darkGray.1',
})}
>
{isAuthenticated ? 'Log Out' : 'Log In'}
</button>
</nav>
</SheetContent>
</Sheet>
)
}

export default HeaderMenu

const menuButton = cva({
base: {
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'all 0.2s ease-out',
gap: 2.5,
},
variants: {
isSelected: {
true: { color: 'red.2' },
false: { color: 'darkGray.1' },
},
},
})
Loading

0 comments on commit 9f4539f

Please sign in to comment.