Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
FullOfOrange committed Dec 6, 2019
2 parents 5785e5a + eac8d3c commit 87d658e
Show file tree
Hide file tree
Showing 22 changed files with 177 additions and 83 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<h1>BookUs!</h1>
<p>
<img alt="travis" src="https://api.travis-ci.org/connect-foundation/2019-12.svg?branch=master" />
<img alt="Version" src="https://img.shields.io/badge/version-0.2.0-blue.svg?cacheSeconds=2592000" />
<img alt="Release" src="https://img.shields.io/github/v/release/connect-foundation/2019-12" />
<img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" />
</p>

### [HomePage](http://www.foorg.xyz/)

[Bookus!](http://www.foorg.xyz/)๋Š” ์ด๋ฒคํŠธ ์˜ˆ์•ฝ ์„œ๋น„์Šค [Festa!](https://festa.io/) ํด๋ก  ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค. ์ˆœ๊ฐ„์ ์œผ๋กœ ๋งŽ์€ ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ฆฌ๋”๋ผ๋„ ์ค‘๋‹จ๋˜์ง€ ์•Š๋Š” **์•ˆ์ •์ ์ธ** ์„ ์ฐฉ์ˆœ ์˜ˆ์•ฝ ์„œ๋น„์Šค๋ฅผ ๋ชฉํ‘œ๋กœ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋„์ „๊ณผ์ œ๋ฅผ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

### ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’๊ณ  ํ…Œ์ŠคํŠธ๋กœ ๊ฒ€์ฆ๋œ UI Component
Expand Down
1 change: 1 addition & 0 deletions client/.env.template
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
REACT_APP_SERVER_URL=
REACT_APP_SERVER_RESERVE_URL=
REACT_APP_GOOGLE_MAP_API_KEY=
24 changes: 11 additions & 13 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';
import defaultTheme from '../src/commons/style/themes/default';
import Normalize from '../src/commons/style/Normalize';
import GlobalStyles from '../src/commons/style/GlobalStyle';

import Login from './pages/Login';
import SignUp from './pages/SignUp';
import Main from './pages/Main';
import EventDetail from './pages/EventDetail';
import EventJoin from './pages/EventJoin';

import GlobalStoreProvider from './stores';
import defaultTheme from 'commons/style/themes/default';
import Normalize from 'commons/style/Normalize';
import GlobalStyles from 'commons/style/GlobalStyle';
import Login from 'pages/Login';
import SignUp from 'pages/SignUp';
import Main from 'pages/Main';
import EventDetail from 'pages/EventDetail';
import EventJoin from 'pages/EventJoin';
import NotFound from 'pages/NotFound';
import GlobalStoreProvider from 'stores';

const App: React.FC = () => (
<GlobalStoreProvider>
Expand All @@ -32,9 +32,7 @@ const App: React.FC = () => (
path="/events/:eventId([0-9]+)/register/tickets"
component={EventJoin}
/>
<Route path="*">
<div>404 page</div>
</Route>
<Route path="*" component={NotFound} />
</Switch>
</Router>
</ThemeProvider>
Expand Down
2 changes: 1 addition & 1 deletion client/src/commons/constants/number.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const EVENT_NAME_MAX_LENGTH = 45;
export const EVENT_NAME_MAX_LENGTH = 40;
4 changes: 2 additions & 2 deletions client/src/commons/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ export default {
SIGNUP: '/signup',
LOGIN: '/login',
USER: '/user',
EVENT_CREATE: 'event/create',
EVENT_DETAIL: 'event/detail',
EVENT_CREATE: '/event/create',
EVENT_DETAIL: '/events',
MYPAGE: '/', // ์ถ”ํ›„์— mypage๋กœ ๋ณ€๊ฒฝํ•ด์•ผํ•จ. ํ˜„์žฌ MYPAGE๋กœ ์ด๋™ํ•ด์•ผํ•˜๋Š” Route ๋Š” ์ „๋ถ€ ์ด๊ฒƒ์„ ์‚ฌ์šฉ.

// TODO : Modify google api to server api using google api
Expand Down
11 changes: 6 additions & 5 deletions client/src/components/molecules/Card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ export interface Props {
price: number;
}

const shortenTitle = (title: string) =>
title.length >= EVENT_NAME_MAX_LENGTH
? `${title.slice(0, EVENT_NAME_MAX_LENGTH)}...`
: title;

function Card({
to,
imgSrc,
Expand All @@ -28,11 +33,7 @@ function Card({
host,
price,
}: Props): React.ReactElement {
const eventTitle =
title.length >= EVENT_NAME_MAX_LENGTH
? `${title.slice(0, EVENT_NAME_MAX_LENGTH)}...`
: title;

const eventTitle = shortenTitle(title);
return (
<S.LinkWrapper to={to} data-testid={'main-card'}>
<S.HeaderWrapper></S.HeaderWrapper>
Expand Down
12 changes: 7 additions & 5 deletions client/src/components/organisms/CardGrid/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React from 'react';

import * as S from './style';
import Card from '../../molecules/Card';
import { Event } from '../../../types/Event';
import Card from 'components/molecules/Card';
import { Event } from 'types/Event';
import ROUTES from 'commons/constants/routes';

interface Props {
cards: Event[];
Expand All @@ -10,7 +12,7 @@ interface Props {

function CardGrid({ cards, setRef }: Props): React.ReactElement {
return (
<S.CardGridWrapper>
<>
<S.CardGridContainer>
{cards.map(card => (
<Card
Expand All @@ -20,12 +22,12 @@ function CardGrid({ cards, setRef }: Props): React.ReactElement {
title={card.title}
host={card.user.lastName + card.user.firstName}
price={card.ticketType.price}
to={`/events/${card.id}`}
to={`${ROUTES.EVENT_DETAIL}/${card.id}`}
/>
))}
</S.CardGridContainer>
<div ref={setRef}></div>
</S.CardGridWrapper>
</>
);
}

Expand Down
8 changes: 6 additions & 2 deletions client/src/components/organisms/CardGrid/style.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import styled from 'styled-components';

export const CardGridWrapper = styled.div``;
export const CardGridContainer = styled.div`
display: grid;
grid-template-columns: repeat(2, 49%);
justify-content: space-between;
column-gap: 1%;
row-gap: 2rem;
@media screen and (min-width: 32rem) {
grid-template-columns: repeat(2, 49%);
column-gap: 1%;
row-gap: 2rem;
}
@media screen and (min-width: 64rem) {
grid-template-columns: repeat(4, 24%);
column-gap: 1%;
Expand Down
6 changes: 1 addition & 5 deletions client/src/hooks/base/useIntersect/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect, useCallback } from 'react';

interface OptionProps {
root?: null;
root?: HTMLElement | null;
threshold?: number;
rootMargin?: string;
}
Expand All @@ -23,7 +23,6 @@ export const useIntersect = (
React.Dispatch<React.SetStateAction<HTMLElement | null>>,
] => {
const [ref, setRef] = useState<HTMLElement | null>(null);
// intersecting์ด ์žˆ์„ ๋•Œ target ์—”ํŠธ๋ฆฌ์™€ observer๋ฅผ ๋„˜๊ฒจ์ฃผ์ž.
const checkIntersect = useCallback(
([entry]: IntersectionObserverEntry[], observer: IntersectionObserver) => {
if (entry.isIntersecting) {
Expand All @@ -32,15 +31,13 @@ export const useIntersect = (
},
[onIntersect],
);
// ref๋‚˜ option์ด ๋ฐ”๋€” ๊ฒฝ์šฐ observer๋ฅผ ์ƒˆ๋กœ ๋“ฑ๋กํ•œ๋‹ค.
useEffect(() => {
let observer: IntersectionObserver;
if (ref) {
observer = new IntersectionObserver(checkIntersect, {
...baseOption,
...option,
});
// start to observe ref
observer.observe(ref);
}
return (): void => observer && observer.disconnect();
Expand All @@ -52,6 +49,5 @@ export const useIntersect = (
checkIntersect,
option,
]);
// setRef๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด์„œ ref๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
return [ref, setRef];
};
6 changes: 2 additions & 4 deletions client/src/pages/EventDetail/store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ const defaultState: EventDetailState = {
place: '',
address: '',
placeDesc: '',
location: {
latitude: 0,
longitude: 0,
},
latitude: 37.5662952,
longitude: 126.9779451,
mainImg: '',
desc: '',

Expand Down
9 changes: 7 additions & 2 deletions client/src/pages/EventDetail/view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ function EventDetailView({ eventId }: Props): React.ReactElement {
place,
address,
placeDesc,
location,
latitude,
longitude,
} = eventData;

const requestFetch = useFetch({
Expand Down Expand Up @@ -84,7 +85,11 @@ function EventDetailView({ eventId }: Props): React.ReactElement {
// TODO: eventContent will change to contentViewer component
eventContent={<div dangerouslySetInnerHTML={{ __html: desc }} />}
ticket={<Ticket {...ticketType} />}
place={<Place {...{ place, address, placeDesc, location }} />}
place={
<Place
{...{ place, address, placeDesc, location: { latitude, longitude } }}
/>
}
/>
);
}
Expand Down
54 changes: 39 additions & 15 deletions client/src/pages/EventJoin/view.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react';

import React, { useState } from 'react';
import axios from 'axios';

import EventJoinTemplate from './template';
import TicketBox from 'components/organisms/TicketBox';
import Counter from 'components/molecules/Counter';
import Btn from 'components/atoms/Btn';
import * as S from './style';
import { useHistory } from 'react-router-dom';
import httpStatus from 'http-status';

const { REACT_APP_SERVER_RESERVE_URL } = process.env;

Expand All @@ -28,24 +29,26 @@ interface Props {
}

function EventJoin({ eventId }: Props): React.ReactElement {
const [isReserved, setisReserved] = useState(false);

const history = useHistory();
let ticketCount = 0;
/**
* .post('/api/users/ticket')
.set({
Cookie: `UID=${token}`,
Accept: 'application/json',
})
.send({
ticketId: 2,
orderTicketNum: 1,
})
*/

const counterHandler = (count: number) => {
ticketCount = count;
};

const requestOrder = async () => {
console.log(REACT_APP_SERVER_RESERVE_URL);
if (isReserved) {
return;
}
if (ticketCount <= 0) {
alert('ํ‹ฐ์ผ“ ๊ฐœ์ˆ˜๋Š” 1๊ฐœ ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.');
return;
}
// 401 : ๋กœ๊ทธ์ธ
// 403, 404 : ban

await axios({
url: `${REACT_APP_SERVER_RESERVE_URL}/api/users/ticket`,
method: 'POST',
Expand All @@ -57,7 +60,28 @@ function EventJoin({ eventId }: Props): React.ReactElement {
orderTicketNum: ticketCount,
},
withCredentials: true,
});
})
.then(res => {
const { status } = res;
if (status === httpStatus.OK) {
setisReserved(true);

alert('์˜ˆ์•ฝ์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');
history.push('/');
}
})
.catch(err => {
const { response } = err;
const { status } = response;
if (status === httpStatus.UNAUTHORIZED) {
history.push('/login');
} else if (
status === httpStatus.FORBIDDEN ||
status === httpStatus.NOT_FOUND
) {
alert('ํ‹ฐ์ผ“ ๊ตฌ๋งค์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ˜”');
}
});
};

return (
Expand Down
12 changes: 4 additions & 8 deletions client/src/pages/Main/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,12 @@ import MainBanner from 'components/organisms/MainBanner';
import CardGrid from 'components/organisms/CardGrid';
import { Event } from '../../types/Event';
import { useIntersect } from '../../hooks';
import delay from '../../utils/delay';

function Main(): React.ReactElement {
const [events, setEvents] = useState<Event[]>([]);
const { REACT_APP_SERVER_URL: SERVER_URL } = process.env;

const delay = (seconds: number): Promise<void> =>
new Promise(resolve =>
setTimeout(() => {
resolve();
}, seconds * 1000),
);

const fetchItems = useCallback(async () => {
const startAt =
events.length === 0
Expand All @@ -28,7 +22,7 @@ function Main(): React.ReactElement {
url: `${SERVER_URL}/api/events?cnt=12${startAt}`,
withCredentials: true,
});
await delay(0.5);
await delay(100);
setEvents([...events, ...data]);
}, [SERVER_URL, events]);

Expand All @@ -40,7 +34,9 @@ function Main(): React.ReactElement {
await fetchItems();
},
{
root: null,
threshold: 1.0,
rootMargin: '0% 0% 25% 0%',
},
);

Expand Down
10 changes: 10 additions & 0 deletions client/src/pages/NotFound/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';
import NotFound from '.';

export default {
title: 'Pages / NotFound',
};

export const notFound: React.FC = () => {
return <NotFound />;
};
21 changes: 21 additions & 0 deletions client/src/pages/NotFound/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';

import NotFoundTemplate from './template';
import ImgBtn from 'components/molecules/ImgBtn';
import ROUTES from 'commons/constants/routes';

function NotFound(): React.ReactElement {
return (
<NotFoundTemplate
content={
<ImgBtn
alt="404 NOT FOUND"
src="https://kr.object.ncloudstorage.com/bookus/notfound.jpg"
to={ROUTES.HOME}
/>
}
/>
);
}

export default NotFound;
Loading

0 comments on commit 87d658e

Please sign in to comment.