파일 구조, 이름 변경 및 url 부분 수정

This commit is contained in:
ByungyeonKim
2021-11-15 00:35:40 +09:00
parent 87fbfe6032
commit 1384ad0ec6
2 changed files with 481 additions and 0 deletions

390
src/index.css Normal file
View File

@@ -0,0 +1,390 @@
/* 아스키코드 문자열이 아닐 경우 UTF-8로 인코딩 셋 지정 */
@charset "UTF-8";
/* 리셋 */
html, body, div, span, p, ol, ul, /* */
li, h1, h2, h3, h4, button, input, strong {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
body {
font-family: 'Apple SD Gothic Neo', '나눔 고딕', NanumGothic, '돋움',
Dotum, sans-serif;
line-height: 1;
}
ol,
ul {
list-style: none;
}
a {
text-decoration: none;
color: var(--cl-text-black);
}
/* 글로벌, 공용 속성 */
:root {
font-size: 62.5%;
--fs--title: 4.2rem;
--fs--xl: 2.4rem;
--fs--600: 1.9rem;
--fs--500: 1.7rem;
--fs--400: 1.5rem;
--fs--xs: 1.2rem;
--cl-zum-blue: #175cbe;
--cl-white: #fff;
--cl-description: #999;
--cl-title: #444;
--cl-detail: #444;
--cl-tag: #497eb1;
--cl-text-black: #000;
--cl-text-gray: #333;
--cl-hover: #547ea7;
--cl-border: #eaeaea;
--cl-top-background: #f5f5f5;
}
* {
box-sizing: border-box;
}
.blind {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
/* 헤더 */
header {
border-bottom: 1px solid var(--cl-border);
}
.header-wrap {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1170px;
margin: auto;
padding: 21px 10px;
}
.header-wrap .logo a {
color: var(--cl-zum-blue);
font-size: var(--fs--xl);
font-weight: bold;
}
.header-wrap .service-wrap {
display: flex;
align-items: center;
font-size: var(--fs--xs);
}
.header-wrap .service-wrap .search {
border: 1px solid var(--cl-border);
padding: 8px 16px 8px 8px;
}
.header-wrap .service-menu {
display: flex;
margin-left: 16px;
}
.header-wrap .service-menu li {
margin-right: 8px;
}
.header-wrap .login {
position: relative;
padding-left: 8px;
}
.header-wrap .login::before {
position: absolute;
top: 0;
left: 0;
height: 10px;
border-left: 1px solid #e4e4e5;
content: '';
}
/* 전체 메뉴 */
.nav-menu {
font-size: var(--fs--500);
color: var(--cl-text-gray);
border-bottom: 1px solid var(--cl-border);
}
.nav-menu .menu-list {
display: flex;
justify-content: flex-start;
align-items: center;
max-width: 1170px;
margin: auto;
}
.nav-menu .menu-list li {
padding: 16px 10px;
cursor: pointer;
}
.nav-menu .menu-list li:not(:nth-last-child(1)) {
margin-right: 16px;
}
.nav-menu .menu-list li:hover {
color: var(--cl-hover);
}
/* 콘텐츠 */
.contents-section {
max-width: 1170px;
margin: auto;
padding: 10px 0;
}
.contents-section:not(:first-of-type) {
padding-top: 16px;
margin-top: 16px;
border-top: 1px solid var(--cl-border);
}
.tag-title {
font-size: var(--fs--600);
color: var(--cl-tag);
padding: 16px 0;
}
.contents-section .contents-wrap {
display: flex;
justify-content: space-between;
}
.contents-section .contents-wrap .content {
display: flex;
flex-direction: column;
max-width: 270px;
cursor: pointer;
}
.contents-section .contents-wrap .content:hover .title {
color: var(--cl-hover);
}
.contents-section .contents-wrap .content:hover .thumbnail {
filter: brightness(0.8);
}
.contents-wrap .content .title {
font-size: var(--fs--500);
color: var(--cl-title);
padding: 16px 0;
}
.contents-wrap .content .description {
font-size: var(--fs--400);
line-height: 16px;
color: var(--cl-description);
margin-bottom: 16px;
/* 말줄임 */
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.contents-wrap .content .author {
font-size: var(--fs--xs);
color: var(--cl-description);
}
/* 실시간 TOP 12 */
.best-section {
max-width: 1170px;
font-size: var(--fs--500);
margin: auto;
padding: 16px 10px;
margin-top: 16px;
border-top: 1px solid var(--cl-border);
}
.best-section .best-list {
display: flex;
flex-wrap: wrap;
}
.best-section .best-list .best-item {
display: flex;
flex: 1 1 30%;
background-color: var(--cl-top-background);
margin-bottom: 16px;
margin-right: 8px;
padding: 16px;
cursor: pointer;
}
.best-section .best-list .best-item:hover {
background-color: var(--cl-hover);
}
.best-section .best-list .best-item:hover .title,
.best-section .best-list .best-item:hover .author {
color: var(--cl-white);
}
.best-list .best-item .title-box {
display: flex;
flex-direction: column;
color: var(--cl-title);
margin-left: 16px;
}
.best-list .best-item .lank {
font-size: var(--fs--600);
font-weight: bold;
margin-top: 2px;
}
.best-list .best-item .title {
font-size: var(--fs--400);
line-height: 17px;
margin-bottom: 8px;
/* 말줄임 */
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.best-list .best-item .author {
font-size: var(--fs--xs);
color: var(--cl-description);
}
/* 푸터 */
footer {
text-align: center;
font-size: var(--fs--400);
padding: 16px 10px;
margin-top: 16px;
border-top: 1px solid var(--cl-border);
}
footer .stacks-list {
max-width: 320px;
display: flex;
justify-content: center;
flex-wrap: wrap;
margin: auto;
}
footer .stacks-list .stacks-item {
padding: 8px;
}
/* 상세 페이지 */
.article-title {
min-height: 200px;
background-color: var(--cl-zum-blue);
padding: 72px 10px;
margin-bottom: 36px;
}
.article-title a {
display: inline-block;
color: var(--cl-white);
font-size: var(--fs--400);
margin-bottom: 12px;
}
.article-title .main-title {
color: var(--cl-white);
font-size: var(--fs--title);
}
.article-title .author {
display: block;
color: var(--cl-white);
padding-top: 17px;
}
.article-title .top,
.article-title .main-title,
.article-title .author {
max-width: 1170px;
margin: auto;
}
/* 메인 콘텐츠 */
.article-body {
max-width: 780px;
margin: auto;
color: var(--cl-detail);
font-size: var(--fs--400);
line-height: 29px;
}
.sub_title {
font-size: var(--fs--600);
line-height: 26px;
letter-spacing: -1px;
margin: 88px 0 29px;
}
.img_block {
text-align: center;
margin: 43px auto;
border-collapse: collapse;
border-spacing: 0;
}
.img_block img {
vertical-align: top;
max-width: 780px;
}
.img_cap {
color: var(--cl-description);
font-size: 12px;
font-family: , dotum, Helvetica, 'Apple SD Gothic Neo', sans-serif;
line-height: 17px;
text-align: center;
padding: 11px 0px 0px 8px;
}
.mov_block {
padding: 48px 0;
margin: auto;
}
.se2_quote6 {
color: var(--cl-description);
line-height: 27px;
border: 1px solid var(--cl-border);
padding: 14px 20px 13px;
margin: 27px 0 42px;
}

91
src/index.js Normal file
View File

@@ -0,0 +1,91 @@
import './index.css';
import Header from './components/header.js';
import store from './store.js';
import Home from './components/home.js';
import Contents from './service/contents.js';
import Footer from './components/footer.js';
import Detail from './components/detail.js';
import axios from 'axios';
const category = ['life', 'food', 'trip', 'culture'];
const httpClient = axios.create({
baseURL: 'http://localhost:8080/api',
});
const contents = new Contents(httpClient);
for (const name of category) {
contents //
.getContents(name)
.then((result) => {
store.setState({ [name]: result });
render();
});
}
contents //
.realTimeBest()
.then((result) => {
store.setState({ realTimeBest: result });
render();
});
const goToDetailPage = () => {
const contentsWrap = document.querySelectorAll('.contents-wrap');
contentsWrap.forEach((content) => {
content.addEventListener('click', (event) => {
const content = event.target.closest('.content');
if (!content) {
return;
}
const url = content.dataset.url
.replace(/https:\/\/hub.zum.com\//g, '')
.replace(/\//g, ' ');
contents //
.detailPage(url)
.then((result) => {
history.pushState({ page: 'detail' }, '', '/life');
store.setSelectedPage({ selectedPage: result });
render();
useLazyLoading();
});
});
});
};
const useLazyLoading = () => {
const imgs = document.querySelectorAll('.article-body img');
const observerCallback = (entries, observer) => {
entries.forEach(({ isIntersecting, intersectionRatio, target }) => {
if (isIntersecting && intersectionRatio > 0) {
if (target.dataset.src) {
target.src = target.dataset.src;
}
observer.unobserve(target);
}
});
};
const io = new IntersectionObserver(observerCallback);
imgs.forEach((img) => io.observe(img));
};
const render = () => {
const app = document.getElementById('app');
app.innerHTML = `
${Header()}
${history.state ? Detail() : Home()}
${Footer()}
`;
goToDetailPage();
};
window.onpopstate = () => {
render();
};