diff --git a/backend/app.js b/backend/app.js index 2ec4475fe66ed3b7cbcd2229621ff9a62c73bbfe..c325d6b6b5a901fd201044e0ef88b836d7b7bb28 100644 --- a/backend/app.js +++ b/backend/app.js @@ -19,7 +19,9 @@ mongoose.Promise = global.Promise; var mongoDB = "mongodb+srv://dragonash:team202@cluster0-sgfno.mongodb.net/test"; var promise = mongoose.connect(mongoDB, { - useMongoClient: true + useNewUrlParser: true, + useUnifiedTopology: true, + useCreateIndex: true }); //mongoose.connect(mongoDB); diff --git a/backend/models/Book.js b/backend/models/Book.js index d5a98782e47011d7588af39b525c23082f13e40a..757788b9a0780c447839b5ffb3403aeb85613ffc 100644 --- a/backend/models/Book.js +++ b/backend/models/Book.js @@ -1,39 +1,49 @@ -var mongoose = require('mongoose'); +var mongoose = require("mongoose"); var Schema = mongoose.Schema; +var autoInc = require("mongoose-auto-increment"); -const BookSchema = mongoose.Schema({ - title: {typr :String}, - grade: { type: Number }, - major: { type: String}, - type: { type: String}, - src: { type: String}, - seller :[{ - seller_id: { type: String}, - on_transaction : {type: Boolean} - }], - - stock: {type: Number} +const BookSchema = new Schema({ + _id: { type: Number }, + title: { type: String }, + grade: { type: Number }, + major: { type: String }, + type: { type: String }, + src: { type: String }, + seller: [ + { + seller_id: { type: String }, + on_transaction: { type: Boolean } + } + ], + + stock: { type: Number } }); BookSchema.statics.create = function(Book_info) { - const { - title, - grade, - major, - type, - src, - } = Book_info; + const { + title, + grade, + major, + type, + src, + stock, + seller: [] + } = Book_info; + const Book = new this({ + title, + grade, + major, + type, + src, + stock, + seller: [] + }); + // return the Promise + return Book.save(); +}; - const Book = new this({ - title, - grade, - major, - type, - src, - }) - // return the Promise - return Book.save() -} +autoInc.initialize(mongoose.connection); +BookSchema.plugin(autoInc.plugin, "Book"); -module.exports = mongoose.model('Book', BookSchema); \ No newline at end of file +module.exports = mongoose.model("Book", BookSchema); diff --git a/backend/models/transaction.js b/backend/models/transaction.js index 3bccd27b5478250a22fb9dc690e7dff3a2601db8..82e1cc3c4aebff7db13f6727b41c4fc3641d18be 100644 --- a/backend/models/transaction.js +++ b/backend/models/transaction.js @@ -1,12 +1,15 @@ -var mongoose = require('mongoose'); +var mongoose = require("mongoose"); var Schema = mongoose.Schema; +var autoInc = require("mongoose-auto-increment"); -const TransactionSchema = mongoose.Schema({ - buyerid : {type:String}, - sellerid : {type:String}, - ontransaction :{type:Boolean} +const TransactionSchema = new Schema({ + _id: Number, + buyerid: { type: String }, + sellerid: { type: String }, + ontransaction: { type: Boolean } }); +autoInc.initialize(mongoose.connection); +TransactionSchema.plugin(autoInc.plugin, "transaction"); - -module.exports = mongoose.model('transaction', TransactionSchema); \ No newline at end of file +module.exports = mongoose.model("transaction", TransactionSchema); diff --git a/backend/models/user.js b/backend/models/user.js index 3a43b7bfb69de00f7a3d5212d2e63e03d89c7ab9..83512248fb1fc075b1554abd35a0c0ed6477b632 100644 --- a/backend/models/user.js +++ b/backend/models/user.js @@ -1,7 +1,9 @@ var mongoose = require("mongoose"); var Schema = mongoose.Schema; +var autoInc = require("mongoose-auto-increment"); var userSchema = new Schema({ + _id: Number, user: String, name: String, id: String, @@ -11,4 +13,7 @@ var userSchema = new Schema({ create_date: { type: Date, default: Date.now } }); +autoInc.initialize(mongoose.connection); +userSchema.plugin(autoInc.plugin, "user"); + module.exports = mongoose.model("user", userSchema); diff --git a/backend/package.json b/backend/package.json index c264c6bb22afe483735ad93311974b3fd48ed987..aabd5d3345811cd18a5cba2575474b7d55867af7 100644 --- a/backend/package.json +++ b/backend/package.json @@ -14,9 +14,10 @@ "express-session": "^1.17.0", "http-errors": "~1.6.3", "mongoose": "^5.7.12", + "mongoose-auto-increment": "^5.0.1", "morgan": "~1.9.1", + "nodemailer": "^6.4.0", "pug": "2.0.0-beta11", - "session-file-store": "^1.3.1", - "nodemailer": "^6.4.0" + "session-file-store": "^1.3.1" } } diff --git a/backend/routes/books.js b/backend/routes/books.js index 6a93a91b3aaafa5834e01d53a399657a1750edd5..c72f7c95b2047037f4c5e6d4373d33de49890ff8 100644 --- a/backend/routes/books.js +++ b/backend/routes/books.js @@ -1,27 +1,61 @@ -var express = require('express'); +var express = require("express"); var router = express.Router(); -var fs = require('fs'); -var path = require('path'); -var User = require('../models/user'); -var Book = require('../models/Book'); +var fs = require("fs"); +var path = require("path"); +var User = require("../models/user"); +var Book = require("../models/Book"); -router.get('/', function(req, res) { - console.log("Get start") - Book.find({}, function(err, Books){ - if(err) res.json({result: false, message: "not found Books"}) - res.json(Books); - }) +// 梨� 紐⑸줉 遺덈윭�ㅺ린 +router.get("/", function(req, res) { + console.log("Get start"); + Book.find({}, function(err, Books) { + if (err) res.json({ result: false, message: "not found Books" }); + res.json(Books); + }); +}); + +// �뱀젙 梨� 遺덈윭�ㅺ린(id媛믪쑝濡� 遺덈윭��) +router.get("/:id", function(req, res) { + Book.findById(req.params.id, function(err, book) { + if (err) { + console.error(err); + return; + } + if (!book) { + res.json({ result: false, message: "Cannot find book" }); + } + res.send(book); + }); }); -router.post('/', function(req, res) { - console.log("Post start") - const Book_info = req.body; +// 梨� 異붽� +router.post("/", function(req, res) { + console.log("Post start"); + const Book_info = req.body; - Book.create(Book_info) + Book.create(Book_info) .then(result => { - if(result) res.json({result:true}); - else res.json({result:false}); + if (result) res.json({ result: true }); + else res.json({ result: false }); + }) + .catch(function(error) { + console.log(error); }); }); -module.exports = router; \ No newline at end of file +// 梨� �먮ℓ +router.post("/:id", function(req, res) { + Book.findById(req.params.id, function(err, book) { + if (err) { + console.error(err); + return; + } + console.log(req.body.userId); + book.seller.push({ seller_id: req.body.userId, on_transaction: false }); + book.stock++; + book.save(); + res.json({ result: true }); + }); +}); + +module.exports = router; diff --git a/backend/routes/login.js b/backend/routes/login.js index 66a879e238c63e1acb3671d3c114a2dc89409bfb..42b589b201bb27a26fab304ec79a81f6b9dc7252 100644 --- a/backend/routes/login.js +++ b/backend/routes/login.js @@ -43,7 +43,7 @@ router.get("/logout", function(req, res) { if (err) { console.log(err); } else { - res.redirect("/"); // �섏젙�댁빞 �� �� + res.redirect("/"); } }); } else { @@ -59,4 +59,13 @@ router.get("/checkSession", function(req, res) { } }); +router.get("/getUserId", function(req, res) { + console.log("getUserId start"); + var sess = req.session; + console.log(sess.userid); + if (sess.userid) { + res.json(sess.userid); + } +}); + module.exports = router; diff --git a/frontend/src/components/BookSearchPage.vue b/frontend/src/components/BookSearchPage.vue index fa52caf4f77a6b5eb315946c216fbecd1447f322..e700ade8517316c4fea8362312b6a7b4be903936 100644 --- a/frontend/src/components/BookSearchPage.vue +++ b/frontend/src/components/BookSearchPage.vue @@ -22,29 +22,34 @@ color="#999" style="float: left; marginLeft: 1%; width: 2%; marginTop:0.1%" v-on:click="Search" - >寃���</md-button> + >寃���</md-button + > <!-- ==================================================================== --> <div v-if="SearchResult === true"> - <div v-for="Book in Books" :key="Book.id"> + <div v-for="Book in Books" :key="Book._id"> <md-card style="width: 50%; margin: 4px;marginTop:100px; display: inline-block; vertical-align: top;" > <md-card-header> <md-card-header-text> <div class="md-title"> - {{Book.title}} + {{ Book.title }} <br /> <br /> </div> - <div class="md-subhead" style="text-align:left;font-weight: bold;"> - # �숇뀈: {{Book.grade}} + <div + class="md-subhead" + style="text-align:left;font-weight: bold;" + > + # �숇뀈: {{ Book.grade }} <br /> - # �꾧났: {{Book.major}} + # �꾧났: {{ Book.major }} <br /> - # �몃��ы빆: {{Book.type}} + # �몃��ы빆: {{ Book.type }} + <br /> + # 留ㅻЪ: {{ Book.stock }} <br /> - # 留ㅻЪ: {{Book.stock}} </div> </md-card-header-text> <md-card-media md-medium> @@ -52,7 +57,11 @@ </md-card-media> </md-card-header> <md-card-actions> - <md-button class="md-raised md-accent">Sell</md-button> + <md-button + class="md-raised md-accent" + v-on:click="goSellPage(Book._id)" + >Sell</md-button + > <md-button class="md-raised md-primary">Buy Now</md-button> </md-card-actions> </md-card> @@ -60,15 +69,21 @@ </div> <!-- ============================================= --> <div> - <md-speed-dial :class="bottomPosition" style="marginRight:20%; marginBottom:8%"> + <md-speed-dial + :class="bottomPosition" + style="marginRight:20%; marginBottom:8%" + > <md-button class="md-fab md-primary" v-on:click="active = true"> <img src="../assets/icon-add.svg" /> </md-button> </md-speed-dial> </div> - <!-- =============�쒗룷�곗쫰 submit �묒떇 ================== --> + <!-- ============= �먮ℓ�꾩꽌 submit �묒떇 ================== --> <div> - <md-dialog :md-active.sync="active" style="width : 500px; height: 1000px "> + <md-dialog + :md-active.sync="active" + style="width : 500px; height: 1000px " + > <md-dialog-title>�먮ℓ�꾩꽌 �깅줉</md-dialog-title> <md-field class="select"> <label>梨낆젣紐�</label> @@ -87,7 +102,9 @@ <md-input v-model="submit.src"></md-input> </md-field> <md-dialog-actions> - <md-button class="md-primary" v-on:click="active = false">Close</md-button> + <md-button class="md-primary" v-on:click="active = false" + >Close</md-button + > <md-button class="md-primary" v-on:click="Register">Submit</md-button> </md-dialog-actions> </md-dialog> @@ -96,98 +113,91 @@ </div> </template> - - <script> -import Vue from 'vue' -import VueMaterial from 'vue-material' -import Multiselect from 'vue-multiselect' -import 'vue-material/dist/vue-material.min.css' -import 'vue-material/dist/theme/default.css' -Vue.use(VueMaterial) +import Vue from "vue"; +import VueMaterial from "vue-material"; +import Multiselect from "vue-multiselect"; +import "vue-material/dist/vue-material.min.css"; +import "vue-material/dist/theme/default.css"; +Vue.use(VueMaterial); export default { - components: { Multiselect }, - name: 'MaterialIcons', - data() { - return { - bottomPosition: 'md-bottom-right', - active : false, - SearchResult : false, - grade: null, - major: null, - type: null, - option1: ['1�숇뀈','2�숇뀈','3�숇뀈','4�숇뀈'], - option2: ['�뚰봽�몄썾�댄븰怨�','誘몃뵒�댄븰怨�','寃쎌젣�숆낵'], - option3: ['�꾧났 �꾩닔', '�꾧났 �좏깮', '援먯뼇�좏깮','湲곗큹怨쇰ぉ'], - Books : [ - ], - submit:{ - title : "", - grade: "", - major : "", - src : "", - } - }; + components: { Multiselect }, + name: "MaterialIcons", + data() { + return { + bottomPosition: "md-bottom-right", + active: false, + SearchResult: false, + grade: null, + major: null, + type: null, + option1: ["1�숇뀈", "2�숇뀈", "3�숇뀈", "4�숇뀈"], + option2: ["�뚰봽�몄썾�댄븰怨�", "誘몃뵒�댄븰怨�", "寃쎌젣�숆낵"], + option3: ["�꾧났 �꾩닔", "�꾧났 �좏깮", "援먯뼇�좏깮", "湲곗큹怨쇰ぉ"], + Books: [], + submit: { + title: "", + grade: "", + major: "", + src: "", + stock: 0, + seller: [] + } + }; + }, + created() { + this.$http.get("/api/books").then(response => { + this.Books = response.data; + console.log("Success"); + console.log(this.Books); + }); + }, + methods: { + Search: function() { + if (this.grade !== null && this.major !== null && this.type !== null) { + this.SearchResult = true; + console.log(this.SearchResult); + } else { + alert("寃��됲븷 移댄뀒怨좊━瑜� �꾨� �낅젰�댁<�몄슂"); + } }, - created() { - this - .$http - .get('/api/books') - .then(response => { - this.Books = response.data; - console.log("Success") - console.log(this.Books) - }) - }, - methods:{ - Search: function(){ - if(this.grade !== null && this.major !== null && this.type !== null) - { - this.SearchResult = true; - console.log(this.SearchResult); - } - else - { - alert("寃��됲븷 移댄뀒怨좊━瑜� �꾨� �낅젰�댁<�몄슂") - } - - }, - Register(){ - this.$http - .post("/api/books", this.submit) - .then(res => { - console.log("Sumit Success"); - }) - .catch(err => { - console.log("Submit failed"); - }); - this.active = false; + Register() { + this.$http + .post("/api/books", this.submit) + .then(res => { + console.log("Submit Success"); + }) + .catch(err => { + console.log("Submit failed"); + }); + this.active = false; + }, + goSellPage(bookId) { + this.$router.push({ name: "BookSearchPageSell", params: { id: bookId } }); } -} + } }; </script> - -<style lang='css'> -html,body { - text-align: center; - margin:0; - width:100%; - font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; - justify-content: center; - +<style lang="css"> +html, +body { + text-align: center; + margin: 0; + width: 100%; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; + justify-content: center; } .search { - margin-Bottom: 0.5%; + margin-bottom: 0.5%; } .select { - - text-align: center; - margin-Top: 2%; + margin: 15px; + text-align: center; + margin-top: 2%; } -.button{ - margin-top: 70px; +.button { + margin-top: 70px; } </style> -<style src="vue-multiselect/dist/vue-multiselect.min.css"> -</style> \ No newline at end of file +<style src="vue-multiselect/dist/vue-multiselect.min.css"></style> diff --git a/frontend/src/components/Buy.vue b/frontend/src/components/Buy.vue new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/frontend/src/components/Sell.vue b/frontend/src/components/Sell.vue new file mode 100644 index 0000000000000000000000000000000000000000..21d7b157a341b9652bb4e0dad3fd11672f39c6a1 --- /dev/null +++ b/frontend/src/components/Sell.vue @@ -0,0 +1,102 @@ +<template> + <div> + <md-card + style="width: 50%; margin: 4px; marginTop:100px; display: inline-block; vertical-align: top;" + > + <md-card-header> + <md-card-header-text> + <div class="md-title"> + {{ book.title }} + <br /> + <br /> + </div> + <div class="md-subhead" style="text-align:left; font-weight:bold;"> + # �숇뀈: {{ book.grade }} + <br /> + # �꾧났: {{ book.major }} + <br /> + # �몃��ы빆: {{ book.type }} + <br /> + # 留ㅻЪ: {{ book.stock }} + <br /> + </div> + </md-card-header-text> + <md-card-media md-medium> + <img v-bind:src="book.src" /> + </md-card-media> + </md-card-header> + </md-card> + + <md-card + style="width: 50%; margin: 4px; marginTop:100px; display: inline-block; vertical-align: top;" + > + <md-card-header> + <div class="md-title"> + �� 梨낆쓣 �먮ℓ�섏떆寃좎뒿�덇퉴? + </div> + </md-card-header> + <md-card-actions> + <md-button class="md-raised md-primary" v-on:click="sellBook" + >�먮ℓ</md-button + > + </md-card-actions> + </md-card> + </div> +</template> + +<script> +import Vue from "vue"; +import VueMaterial from "vue-material"; +import Multiselect from "vue-multiselect"; +import "vue-material/dist/vue-material.min.css"; +import "vue-material/dist/theme/default.css"; +Vue.use(VueMaterial); + +export default { + data() { + return { + book: {}, + userId: "" + }; + }, + created() { + var id = this.$route.params.id; + this.$http.get(`/api/books/${id}`).then(response => { + this.book = response.data; + }); + // this.$http.get("/api/login/getUserId").then(response => { + // console.log("getUserIDstart"); + // this.userId = response.data; + // }); + }, + methods: { + getId() { + this.$http.get("/api/login/getUserId").then(response => { + console.log("rd" + response.data); + this.userId = response.data; + }); + }, + sellBook() { + var id = this.$route.params.id; + this.getId(); + console.log("user:" + this.userId); + this.$http + .post(`/api/books/${id}`, { + userId: this.userId + }) + .then( + response => { + alert("�먮ℓ ��湲곗뿴�� �깅줉�섏��듬땲��."); + //this.$router.push("home"); + }, + error => { + alert(error.response.data.error); + } + ) + .catch(error => { + alert(error); + }); + } + } +}; +</script> diff --git a/frontend/src/components/login/Login.vue b/frontend/src/components/login/Login.vue index 9d27c96a941bea1b2f663017007b7e7af519d7c4..a1faac8c63b356af927f02776dcf184445e4b642 100644 --- a/frontend/src/components/login/Login.vue +++ b/frontend/src/components/login/Login.vue @@ -1,7 +1,7 @@ <template> <div id="login"> <md-button class="md-primary" v-on:click="active = true">Login</md-button> - <md-dialog :md-active.sync="active" style="width: 500px; height: 1000px"> + <md-dialog :md-active.sync="active" style="width: 500px; height: 500px"> <md-dialog-title>Login</md-dialog-title> <md-field class="select"> <label>ID</label> @@ -47,7 +47,6 @@ export default { response => { //濡쒓렇�� �깃났 alert("success login"); - //this.$router.push("Logout"); this.active = false; location.reload(); }, diff --git a/frontend/src/components/login/SignUp.vue b/frontend/src/components/login/SignUp.vue index a7118e3575df16c42d80ab83a3b81410576b072f..01ac07dfe52d6c9f13c939d24bf029faf3fe77ad 100644 --- a/frontend/src/components/login/SignUp.vue +++ b/frontend/src/components/login/SignUp.vue @@ -33,7 +33,7 @@ </div> </template> -<style> +<style scoped> .select { margin: 15px; display: inline-flex; diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index adf5c4580f95ca29cd94d0361611c4f664f4493f..f483827eac54ac23aeeb9a6212f5a384659ac275 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -8,6 +8,8 @@ import BookSearchPage from "@/components/BookSearchPage"; import Login from "@/components/login/Login"; import Logout from "@/components/login/Logout"; import SignUp from "@/components/login/SignUp"; +import Buy from "@/components/Buy"; +import Sell from "@/components/Sell"; export default new Router({ mode: "history", @@ -47,6 +49,26 @@ export default new Router({ path: "/signUp", name: "SignUp", component: SignUp + }, + { + path: "/BookSearchPage/buy/:id", + name: "BookSearchPageBuy", + component: Buy + }, + { + path: "/home/buy/:id", + name: "HomeBuy", + component: Buy + }, + { + path: "/BookSearchPage/sell/:id", + name: "BookSearchPageSell", + component: Sell + }, + { + path: "/home/sell/:id", + name: "HomeSell", + component: Sell } ] });