Skip to content

Commit 74eba02

Browse files
committed
레이아웃에 후원사 목록 추가
1 parent 258c0f4 commit 74eba02

File tree

9 files changed

+180
-7
lines changed

9 files changed

+180
-7
lines changed

@types/sponsor.ts

+18
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,21 @@ export interface SponsorLevelTypeApiResponse {
5252
limit: number;
5353
id: number;
5454
}
55+
56+
export interface ISponsorListItem {
57+
level: string;
58+
list: ISponsorData[];
59+
}
60+
export interface ISponsorData {
61+
name: string;
62+
logoImage: string;
63+
level: string;
64+
id: number;
65+
}
66+
67+
export interface ISponsorApiListItem {
68+
name: string;
69+
logo_image: string;
70+
level: number;
71+
id: number;
72+
}

api/login.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function signIn(id: string, password: string): Promise<string> {
1717
resolve(response.data.basic_auth_token);
1818
})
1919
.catch((e) => {
20-
console.error(e);
20+
//console.error(e);
2121
reject(e);
2222
});
2323
});
@@ -35,7 +35,7 @@ export function signOut(): Promise<void> {
3535
resolve();
3636
})
3737
.catch((e) => {
38-
console.error(e);
38+
// console.error(e);
3939
reject(e);
4040
});
4141
});

api/sponsor.ts

+19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import axios from '@/lib/axios';
22
import { getHeaders } from '.';
3+
import { ISponsorApiListItem, ISponsorListItem } from '@/@types/sponsor';
4+
import { SponsorLevel } from '@/data/enums/SponsorLevel';
5+
import { groupBy } from '@/helpers/array.helpers';
36

47
export function addSponsor(formData: FormData): Promise<void> {
58
return new Promise((resolve, reject) => {
@@ -18,3 +21,19 @@ export function addSponsor(formData: FormData): Promise<void> {
1821
});
1922
});
2023
}
24+
25+
export async function getSponsorList(): Promise<ISponsorListItem[]> {
26+
const response = await axios.get(`/sponsors/list/`);
27+
const list = response.data.map((item: ISponsorApiListItem) => ({
28+
id: item.id || 0,
29+
name: item.name || '',
30+
logoImage: item.logo_image || '',
31+
level: item.level ? SponsorLevel[item.level] : '',
32+
}));
33+
const groupedList = groupBy(list, (item) => item.level);
34+
const sponsorList = Object.entries(groupedList).map(([level, data]) => ({
35+
level,
36+
list: data,
37+
}));
38+
return sponsorList;
39+
}

components/layout/Container.tsx

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { styled } from 'stitches.config';
22
import NavBar from '@/components/layout/NavBar';
33
import Footer from '@/components/layout/Footer';
4+
import SponsorList from '@/components/sponsor/SponsorList';
5+
import { ISponsorListItem } from '@/@types/sponsor';
46

57
const ContainerBody = styled('div', {
68
maxWidth: '1920px',
@@ -27,15 +29,27 @@ const Wrapper = styled('div', {
2729
width: '100%',
2830
});
2931

32+
const SponsorWrapper = styled('div', {
33+
marginTop: '32px',
34+
});
35+
3036
type ContainerProps = {
3137
children: React.ReactNode;
38+
sponsorList: ISponsorListItem[];
3239
};
3340

34-
const Container = ({ children }: ContainerProps) => (
41+
const Container = ({ children, sponsorList }: ContainerProps) => (
3542
<ContainerBody>
3643
<NavBar />
3744
<Main>
38-
<Wrapper>{children}</Wrapper>
45+
<Wrapper>
46+
{children}
47+
{sponsorList.length > 0 ?? (
48+
<SponsorWrapper>
49+
<SponsorList list={sponsorList} />
50+
</SponsorWrapper>
51+
)}
52+
</Wrapper>
3953
</Main>
4054
<Footer />
4155
</ContainerBody>

components/sponsor/SponsorList.tsx

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { ISponsorData, ISponsorListItem } from '@/@types/sponsor';
2+
import { H3, H4 } from '@/components/heading';
3+
import { sponsorLevelLabel } from '@/constants/sponsor/sponsorLevel';
4+
import { styled } from 'stitches.config';
5+
6+
const SponsorGroupContainer = styled('div', {
7+
marginTop: 32,
8+
});
9+
const SponsorLevelContainer = styled('div', {
10+
marginBottom: 8,
11+
});
12+
13+
const SponsorGroup = styled('ul', {
14+
display: 'flex',
15+
alignItems: 'center',
16+
justifyContent: 'center',
17+
flexWrap: 'wrap',
18+
flex: 'auto',
19+
gap: '2rem',
20+
});
21+
22+
const SponsorGroupItem = styled('li', {
23+
width: '200px',
24+
height: '200px',
25+
textAlign: 'center',
26+
listStyle: 'none',
27+
display: 'inline-flex',
28+
alignItems: 'center',
29+
});
30+
31+
const SponsorImage = styled('img', {
32+
width: '100%',
33+
display: 'inline-block',
34+
verticalAlign: 'top',
35+
});
36+
37+
const SponsorListItem: React.FC<{ sponsor: ISponsorData }> = (props: {
38+
sponsor: ISponsorData;
39+
}) => {
40+
const { sponsor } = props;
41+
return (
42+
<SponsorGroupItem>
43+
<SponsorImage src={sponsor.logoImage} alt={sponsor.name} />
44+
</SponsorGroupItem>
45+
);
46+
};
47+
48+
const SponsorList: React.FC<{ list: ISponsorListItem[] }> = (props: {
49+
list: ISponsorListItem[];
50+
}) => {
51+
return (
52+
<div>
53+
<H3>후원사 목록</H3>
54+
<SponsorGroupContainer>
55+
{props.list.map((item: ISponsorListItem) => (
56+
<SponsorLevelContainer key={`level-${item.level}`}>
57+
<H4>
58+
{sponsorLevelLabel[item.level as keyof typeof sponsorLevelLabel]}
59+
</H4>
60+
<SponsorGroup>
61+
{item.list.map((item, index) => (
62+
<SponsorListItem
63+
key={`sponsor-${item.level}-${index}`}
64+
sponsor={item}
65+
/>
66+
))}
67+
</SponsorGroup>
68+
</SponsorLevelContainer>
69+
))}
70+
</SponsorGroupContainer>
71+
</div>
72+
);
73+
};
74+
75+
export default SponsorList;

constants/sponsor/sponsorLevel.ts

+13
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,16 @@ export const SponsorLevelData2 = [
223223
publisher: '현수막\n스탠딩 배너\n웹사이트',
224224
},
225225
];
226+
227+
export const sponsorLevelLabel = {
228+
Keystone: '키스톤',
229+
Diamond: '다이아몬트',
230+
Sapphire: '사파이어',
231+
Platinum: '플래티넘',
232+
Ruby: '루비',
233+
Gold: '골드',
234+
Silver: '실버',
235+
Startup: '스타트업',
236+
Community: '커뮤니티',
237+
Publisher: '출판사',
238+
};

data/enums/SponsorLevel.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export enum SponsorLevel {
2+
Keystone = 1,
3+
Diamond = 2,
4+
Sapphire = 3,
5+
Platinum = 4,
6+
Ruby = 5,
7+
Gold = 6,
8+
Silver = 7,
9+
Startup = 8,
10+
Community = 9,
11+
Publisher = 10,
12+
}

helpers/array.helpers.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { groupBy as _groupBy } from 'lodash-es';
2+
3+
export const groupBy = _groupBy;

pages/_app.tsx

+22-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import Script from 'next/script';
1111
import { darkTheme } from '@/stitches.config';
1212
import { ThemeProvider } from 'next-themes';
1313
import RecoilNexus from 'recoil-nexus';
14+
import { getSponsorList } from '@/api/sponsor';
15+
import { ISponsorListItem } from '@/@types/sponsor';
1416

1517
function RecoilDebugObserver() {
1618
const snapshot = useRecoilSnapshot();
@@ -27,7 +29,11 @@ function RecoilDebugObserver() {
2729

2830
const queryClient = new QueryClient();
2931

30-
function MyApp({ Component, pageProps }: AppProps) {
32+
function App({
33+
Component,
34+
pageProps,
35+
sponsorList,
36+
}: AppProps & { sponsorList: ISponsorListItem[] }) {
3137
const router = useRouter();
3238
React.useEffect(() => {
3339
const handleRouteChange = (url: URL) => {
@@ -70,7 +76,7 @@ function MyApp({ Component, pageProps }: AppProps) {
7076
<RecoilNexus />
7177
{process.env.NODE_ENV === 'development' && <RecoilDebugObserver />}
7278
<QueryClientProvider client={queryClient}>
73-
<Container>
79+
<Container sponsorList={sponsorList}>
7480
<Script
7581
strategy="afterInteractive"
7682
src={`https://www.googletagmanager.com/gtag/js?id=${gtag.GA_TRACKING_ID}`}
@@ -85,4 +91,17 @@ function MyApp({ Component, pageProps }: AppProps) {
8591
);
8692
}
8793

88-
export default MyApp;
94+
App.getInitialProps = async () => {
95+
try {
96+
const sponsorList = await getSponsorList();
97+
console.log(sponsorList);
98+
return {
99+
sponsorList,
100+
};
101+
} catch (e) {
102+
console.error(e);
103+
return [];
104+
}
105+
};
106+
107+
export default App;

0 commit comments

Comments
 (0)