이정민

pug files

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