이정민

pug files

extends layout
block good
h2= good.name
div= '등록자: ' + good.owner.nick
div= '시작가: ' + good.price + '원'
strong#time(data-start=good.createdAt)
img#good-img(src='/img/' + good.img)
block content
.timeline
#bid
for bid in auction
div
span= bid.user.nick + '님: '
strong= bid.bid + '원에 입찰하셨습니다.'
if bid.msg
span= '(' + bid.msg + ')'
form#bid-form
input(type='number' name='bid' placeholder='입찰가' required min=good.price)
input(type='msg' name='msg' placeholder='메시지(선택사항)' maxlength='100')
button.btn(type='submit') 입찰
if auctionError
.error-message= auctionError
script(src='https://cdnjs.cloudflare.com/ajax/libs/event-source-polyfill/0.0.9/eventsource.min.js')
script(src='/socket.io/socket.io.js')
script.
document.querySelector('#bid-form').addEventListener('submit', function (e) {
e.preventDefault();
var xhr = new XMLHttpRequest();
var errorMessage = document.querySelector('.error-message');
xhr.onload = function () {
if (xhr.status === 200) {
e.target.bid.value = '';
e.target.msg.value = '';
errorMessage.textContent = '';
} else {
console.error(xhr.responseText);
e.target.bid.value = '';
e.target.msg.value = '';
errorMessage.textContent = xhr.responseText
}
};
xhr.open('POST', '/good/#{good.id}/bid');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
bid: e.target.bid.value,
msg: e.target.msg.value,
}));
});
var es = new EventSource("/sse");
var time = document.querySelector('#time');
es.onmessage = function (e) {
var end = new Date(time.dataset.start);
var server = new Date(parseInt(e.data, 10));
end.setDate(end.getDate() + 1);
if (server >= end) {
return time.textContent = '00:00:00';
} else {
var t = end - server;
var seconds = ('0' + Math.floor((t / 1000) % 60)).slice(-2);
var minutes = ('0' + Math.floor((t / 1000 / 60) % 60)).slice(-2);
var hours = ('0' + Math.floor((t / (1000 * 60 * 60)) % 24)).slice(-2);
return time.textContent = hours + ':' + minutes + ':' + seconds;
}
};
var socket = io.connect('http://localhost:8010', {
path: '/socket.io'
});
socket.on('bid', function (data) {
var div = document.createElement('div');
var span = document.createElement('span');
span.textContent = data.nick + '님: ';
var strong = document.createElement('strong');
strong.textContent = data.bid + '원에 입찰하셨습니다.';
div.appendChild(span);
div.appendChild(strong);
if (data.msg) {
span = document.createElement('span');
span.textContent = '(' + data.msg + ')';
div.appendChild(span);
}
document.querySelector('#bid').appendChild(div);
});
extends layout
block content
h1= message
h2= error.status
pre #{error.stack}
extends layout
block content
.timeline
form#good-form(action='/good' method='post' enctype='multipart/form-data')
.input-group
label(for='good-name') 상품명
input#good-name(name='name' required autofocus style='height:50px;')
.input-group
label(for='good-photo') 상품 사진
input#good-photo(type='file' name='img' required autofocus style='height:50px;')
.input-group
label(for='good-price') 시작 가격
input#good-price(type='number' name='price' required style='height:50px;')
button#join-btn.btn(type='submit' mar style="font-family:Yeon Sung ") 상품 등록
extends layout
block content
.timeline
form#join-form(action='/auth/join' method='post')
.input-group
label(for='join-email') 이메일
input#join-email(type='email' name='email')
.input-group
label(for='join-nick') 닉네임
input#join-nick(type='text' name='nick')
.input-group
label(for='join-password') 비밀번호
input#join-password(type='password' name='password')
.input-group
label(for='join-money') 보유자산
input#join-money(type='number' name='money')
if joinError
.error-message= joinError
button#join-btn.btn(type='submit' style='font-family:Yeon Sung') 회원가입
doctype
html
head
meta(charset='UTF-8')
title= title
meta(name='viewport' content='width=device-width, user-scalable=no')
meta(http-equiv='X-UA-Compatible' content='IE=edge')
link(rel='stylesheet' href='/main.css')
link(rel='stylesheet' href='https://fonts.googleapis.com/css?family=Yeon+Sung&subset=korean')
link(rel='stylesheet' href='https://fonts.googleapis.com/css?family=Song+Myung&subset=korean')
h1(style='font-family:Song Myung; font-size:50px; text-align:center; padding-top:30px;')
| 중고로운 경희나라
body
.container
.profile-wrap
.profile
if user && user.id
.user-name= '안녕하세요! ' + user.nick + '님'
.user-money= '보유 자산: ' + user.money + '원'
input#my-id(type='hidden' value=user.id)
a#logout.btn(href='/auth/logout') 로그아웃
a#register.btn(href='/good') 상품 등록
a#list.btn(href='/list') 낙찰 내역
else
form#login-form(action='/auth/login' method='post')
.input-group
label(for='email' style='font-family:Yeon Sung; font-size:20px; color:black') 이메일
input#email(type='email' name='email' required autofocus style='font-family:Yeon Sung; font-size:15px')
.input-group
label(for='password' style='font-family:Yeon Sung; font-size:20px; color:black') 비밀번호
input#password(type='password' name='password' required style='font-family:Yeon Sung; font-size:15px')
if loginError
.error-message= loginError
a#join.btn(href='/join' style='font-family:Yeon Sung; font-size:20px') 회원가입
button#login.btn(type='submit' style='font-family:Yeon Sung; font-size:20px') 로그인
footer(style='font-family:Yeon Sung')
| Made by 이정민 서예진 김대욱
block good
block content
extends layout
block content
.timeline
h2 경매 낙찰 목록
table#good-list
tr
th 상품명
th 사진
th 낙찰가
for good in goods
tr
td= good.name
td: img(src='/img/' + good.img)
td= good.auctions[0].bid
extends layout
block content
.timeline
h2 경매 진행 목록
table#good-list
tr
th 상품명
th 이미지
th 시작 가격
th 종료 시간
th 입장
for good in goods
tr
td= good.name
td: img(src='/img/' + good.img)
td= good.price
td.time(data-start=good.createdAt) 00:00:00
td: a.enter.btn(href='/good/' + good.id) 입장
script(src='https://cdnjs.cloudflare.com/ajax/libs/event-source-polyfill/0.0.9/eventsource.min.js')
script.
var es = new EventSource('/sse');
es.onmessage = function (e) {
document.querySelectorAll('.time').forEach(function(td) {
var end = new Date(td.dataset.start);
var server = new Date(parseInt(e.data, 10));
end.setDate(end.getDate() + 1);
if (server >= end) {
return td.textContent = '00:00:00';
} else {
var t = end - server;
var seconds = ('0' + Math.floor((t / 1000) % 60)).slice(-2);
var minutes = ('0' + Math.floor((t / 1000 / 60) % 60)).slice(-2);
var hours = ('0' + Math.floor((t / (1000 * 60 * 60)) % 24)).slice(-2);
return td.textContent = hours + ':' + minutes + ':' + seconds ;
}
});
};