diff --git a/backend/models/Book.js b/backend/models/Book.js index 9756ebe2a3ae764abfefb29ee9d60fa046d74680..38d9357fd9cea6813f1e7176b69e2884059db566 100644 --- a/backend/models/Book.js +++ b/backend/models/Book.js @@ -9,40 +9,9 @@ const BookSchema = new Schema({ 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, - stock, - seller: [] - } = Book_info; - - const Book = new this({ - title, - grade, - major, - type, - src, - stock, - seller: [] - }); - // return the Promise - return Book.save(); -}; - autoInc.initialize(mongoose.connection); BookSchema.plugin(autoInc.plugin, "Book"); diff --git a/backend/routes/books.js b/backend/routes/books.js index 93d3421c6fa1696bd0c74d5b6ccfc7ca5d658fff..4026b74f8eba9da0e5d26e86ab7b82af53b4100d 100644 --- a/backend/routes/books.js +++ b/backend/routes/books.js @@ -1,8 +1,5 @@ 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"); // 梨� 紐⑸줉 遺덈윭�ㅺ린 @@ -28,47 +25,4 @@ router.get("/:id", function(req, res) { }); }); -// 梨� 異붽� -router.post("/", function(req, res) { - console.log("Post start"); - const Book_info = req.body; - - Book.create(Book_info) - .then(result => { - if (result) res.json({ result: true }); - else res.json({ result: false }); - }) - .catch(function(error) { - console.log(error); - }); -}); - -// 梨� 援щℓ 諛� �먮ℓ -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); - if (req.body.isBuyer === true) { - // var soldbook = book.seller.shift(); - // book.stock--; - // book.save(); - console.log(book.seller); - var temp = book.seller.find(element => element.on_transaction === false); - // book.seller.find( - // element => element.on_transaction === false - // ).on_transaction = true; - // book.save(); - res.json({ result: temp }); - return; - } - 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/emails.js b/backend/routes/emails.js index da0be3ca25f42a5ae1a678db1be5d8c22e9a441f..77ff9232775fca0218f05d4a159b9bd30b329137 100644 --- a/backend/routes/emails.js +++ b/backend/routes/emails.js @@ -8,6 +8,9 @@ router.post("/", function(req, res, next) { let bookTitle = req.body.bookTitle; let buyerPhoneNumber = req.body.buyerPhoneNumber; + console.log(sellerEmail); + console.log(bookTitle); + console.log(buyerPhoneNumber); let transporter = nodemailer.createTransport({ service: "gmail", auth: { @@ -33,6 +36,7 @@ router.post("/", function(req, res, next) { console.log(error); } else { console.log("Email sent: " + info.response); + res.send({ result: 1 }); } }); }); diff --git a/backend/routes/login.js b/backend/routes/login.js index 1b4447fd535ba1e447dd77caf0a47fe16038c6ad..80e20cb3a928817d526277b22d1b0d8bc82e91b6 100644 --- a/backend/routes/login.js +++ b/backend/routes/login.js @@ -68,19 +68,26 @@ router.get("/getUserId", function(req, res) { } }); -router.post("/getUserInfo", function(req, res) { +router.post("/getUserInfo", async (req, res) => { console.log("getUserInfo start"); - var getInfoId = req.body.userId; - console.log(getInfoId); - User.findOne({ id: getInfoId }, function(err, user) { - if (err) { - res.send(err); + var getBuyerInfoId = req.body.buyerId; + var getSellerInfoId = req.body.sellerId; + + try { + const buyer = await User.findOne({ id: getBuyerInfoId }); + const seller = await User.findOne({ id: getSellerInfoId }); + + if (!buyer) { + return res.status(404).json({ error: "Buyer not found" }); } - if (!user) { - return res.status(404).json({ error: "user not found" }); + if (!seller) { + return res.status(404).json({ error: "seller not found" }); } - res.json(user); - }); + + res.json({ buyer: buyer, seller: seller }); + } catch (err) { + res.json({ error: err.message }); + } }); module.exports = router; diff --git a/backend/routes/transaction.js b/backend/routes/transaction.js index ad402d3cdf3e603d535f11831e7a24a8bfa55138..d657063d78f2a9c05151b08bd7fdc63f842e2207 100644 --- a/backend/routes/transaction.js +++ b/backend/routes/transaction.js @@ -1,6 +1,8 @@ const express = require("express"); const router = express.Router(); const Transaction = require("../models/transaction"); +const User = require("../models/user"); +const Book = require("../models/Book"); router.get("/", function(req, res) { console.log("Get transaction start"); @@ -13,24 +15,121 @@ router.get("/", function(req, res) { }); }); -router.post("/", function(req, res) { - console.log("Post transaction start"); - var transaction = new Transaction(); - transaction.buyerId = req.body.buyerId; - console.log(req.body.buyerId); - transaction.sellerId = req.body.sellerId; - console.log(req.body.sellerId); - transaction.bookTitle = req.body.bookTitle; - transaction.on_transaction = true; - - transaction.save(function(err) { - if (err) { - console.error(err); - res.json({ result: 0 }); - return; - } - res.json({ result: 1 }); - }); +router.post("/cancel", async (req, res) => { + console.log("POST - cancel start"); + var sess = req.session; + var req_bookTitle = req.body.bookTitle; + var userId = sess.userid; + + try { + await Transaction.findOne( + { + bookTitle: req_bookTitle, + $or: [{ buyerId: userId }, { sellerId: userId }] + }, + function(err, transaction) { + if (err) { + console.error(err); + return; + } + transaction.buyerId = ""; + transaction.on_transaction = false; + transaction.save(); + res.json({ result: true }); + } + ); + } catch (err) { + res.json({ error: err.message }); + } +}); + +router.post("/success", async (req, res) => { + console.log("POST - success start"); + var sess = req.session; + var req_bookTitle = req.body.bookTitle; + var userId = sess.userid; + + try { + await Transaction.remove( + { + bookTitle: req_bookTitle, + $or: [{ buyerId: userId }, { sellerId: userId }] + }, + function(err, transaction) { + if (err) { + console.error(err); + return; + } + Book.findOne({ title: req_bookTitle }, function(err, book) { + if (err) { + console.error(err); + return; + } + book.stock--; + book.save(); + }); + // transaction.on_transaction = ""; + // transaction.save(); + res.json({ result: true }); + } + ); + } catch (err) { + res.json({ error: err.message }); + } +}); + +router.post("/buy", async (req, res) => { + console.log("POST - buy start"); + var sess = req.session; + var req_bookTitle = req.body.bookTitle; + buyerId = sess.userid; + + try { + await Transaction.findOne({ bookTitle: req_bookTitle }, function( + err, + transaction + ) { + if (err) { + console.error(err); + return; + } + transaction.buyerId = buyerId; + transaction.on_transaction = true; + transaction.save(); + res.json({ buyerId: buyerId, sellerId: transaction.sellerId }); + }); + } catch (err) { + res.json({ error: err.message }); + } +}); + +router.post("/sell", async (req, res) => { + console.log("POST - sell start"); + var sess = req.session; + var bookTitle = req.body.bookTitle; + sellerId = sess.userid; + console.log(sellerId); + + try { + await Book.findOne({ title: bookTitle }, function(err, book) { + if (err) { + console.error(err); + return; + } + + var transaction = new Transaction(); + transaction.sellerId = sellerId; + transaction.buyerId = ""; + transaction.bookTitle = book.title; + transaction.on_transaction = false; + book.stock++; + transaction.save(); + book.save(); + res.json({ result: true }); + }); + } catch (err) { + res.json({ error: err.message }); + } }); module.exports = router; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 25cd8f73ad80f8dd242c7d0b1ffa9b430e61a93c..448b3aacf67683f11d68a37e6f5e518581f0757a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11802,6 +11802,11 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "vuelidate": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/vuelidate/-/vuelidate-0.7.4.tgz", + "integrity": "sha512-QHZWYOL325Zo+2K7VBNEJTZ496Kd8Z31p85aQJFldKudUUGBmgw4zu4ghl4CyqPwjRCmqZ9lDdx4FSdMnu4fGg==" + }, "vuetify": { "version": "2.1.11", "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-2.1.11.tgz", diff --git a/frontend/package.json b/frontend/package.json index d38d1cfe12e5db39f588ae2f9f98f4f353aa3a76..d611624606f58006e5c1307d7a811310680d3b33 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,7 +15,8 @@ "vue": "^2.5.2", "vue-material": "^1.0.0-beta-11", "vue-multiselect": "^2.1.6", - "vue-router": "^3.0.1" + "vue-router": "^3.0.1", + "vuelidate": "^0.7.4" }, "devDependencies": { "autoprefixer": "^7.1.2", diff --git a/frontend/src/components/BookSearchPage.vue b/frontend/src/components/BookSearchPage.vue index 1aea2370741cd5aea85ec8e6de47998fe3bf6ddd..2f2e00d598716ba59a2ddebddee09b8b9c7b4792 100644 --- a/frontend/src/components/BookSearchPage.vue +++ b/frontend/src/components/BookSearchPage.vue @@ -94,7 +94,7 @@ </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="Register">Submit</md-button> + <md-button class="md-primary">Submit</md-button> </md-dialog-actions> </md-dialog> <!-- ============================================== --> @@ -139,23 +139,11 @@ export default { this.Books = response.data; console.log("Success"); console.log(this.Books); - }); }, methods: { Search: function() { - this.SearchResult = true; - }, - Register() { - this.$http - .post("/api/books", this.submit) - .then(res => { - console.log("Submit Success"); - }) - .catch(err => { - console.log("Submit failed"); - }); - this.active = false; + this.SearchResult = true; }, goBuyPage(bookId) { this.$router.push({ name: "BookSearchPageBuy", params: { id: bookId } }); diff --git a/frontend/src/components/Buy.vue b/frontend/src/components/Buy.vue index 9515470c42e14573f802f84806f9eea593f2af1b..2e0c10755ece72e16a38c73ff22a6f5b3bf8a2cd 100644 --- a/frontend/src/components/Buy.vue +++ b/frontend/src/components/Buy.vue @@ -66,71 +66,43 @@ export default { }, methods: { buyBook() { - this.$http.get("/api/login/getUserId").then(response => { - console.log("rd" + response.data); - this.userId = response.data; - var id = this.$route.params.id; - console.log("user:" + this.userId); - this.$http - .post(`/api/books/${id}`, { - userId: this.userId, - isBuyer: true - }) - .then( - res => { - console.log(res.data); - this.sellerId = res.data.result.seller_id; - this.$http - .post("/api/transaction", { - buyerId: this.userId, - sellerId: this.sellerId, - bookTitle: this.book.title - }) - .then(response => { - console.log("buy.vue-transaction post"); - alert("援щℓ�� �깃났�섏��듬땲��. �먮ℓ�먯뿉寃� 硫붿씪�� 蹂대깄�덈떎."); - this.sendEmail(); - }); - }, - error => { - alert(error.response.data.error); - } - ) - .catch(error => { - alert(error); - }); - }); - }, - sendEmail() { - console.log("sendEmail start"); this.$http - .post("/api/login/getUserInfo", { - userId: this.userId // buyer + .post("/api/transaction/buy", { + bookTitle: this.book.title }) .then(response => { - this.buyer = response.data; + alert("援щℓ�� �깃났�섏��듬땲��. �먮ℓ�먯뿉寃� 硫붿씪�� 蹂대깄�덈떎."); + this.buyerId = response.data.buyerId; + this.sellerId = response.data.sellerId; + this.sendEmail(); + }) + .catch(error => { + alert(error); }); - + }, + sendEmail() { + console.log("sendEmail start"); this.$http .post("/api/login/getUserInfo", { - userId: this.sellerId + buyerId: this.buyerId, // buyer + sellerId: this.sellerId }) .then(response => { - this.seller = response.data; + this.buyer = response.data.buyer; + this.seller = response.data.seller; + this.$http + .post("/api/emails", { + sellerEmail: this.seller.email, + bookTitle: this.book.title, + buyerPhoneNumber: this.buyer.phonenumber + }) + .then(response => { + alert("�대찓�� �꾩넚 �꾨즺"); + }), + error => { + alert(error.response.data.error); + }; }); - - this.$http - .post("/api/emails", { - sellerEmail: this.seller.email, - bookTitle: this.book.title, - buyerPhoneNumber: this.buyer.phonenumber - }) - .then(response => { - alert("�대찓�� �꾩넚 �꾨즺"); - }), - error => { - alert(error.response.data.error); - }; } } }; diff --git a/frontend/src/components/Sell.vue b/frontend/src/components/Sell.vue index 7c1bcc8d565c22d1ad1cbffa4c68dc0089c3b903..ae27fd107a0f76e49e76392abbbc010d073ca05a 100644 --- a/frontend/src/components/Sell.vue +++ b/frontend/src/components/Sell.vue @@ -63,28 +63,16 @@ export default { }, methods: { sellBook() { - this.$http.get("/api/login/getUserId").then(response => { - console.log("rd" + response.data); - this.userId = response.data; - var id = this.$route.params.id; - 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); - }); - }); + this.$http + .post("/api/transaction/sell", { + bookTitle: this.book.title + }) + .then(response => { + alert("�먮ℓ ��湲곗뿴�� �깅줉�섏��듬땲��."); + }) + .catch(error => { + alert(error); + }); } } }; diff --git a/frontend/src/components/home_hotlist/Hotlist.vue b/frontend/src/components/home_hotlist/Hotlist.vue index 53c2b6571ef5fc40e7144a1a4e5636c289755de2..4e609742b888628e6c77be6567467dab2dc3a02e 100644 --- a/frontend/src/components/home_hotlist/Hotlist.vue +++ b/frontend/src/components/home_hotlist/Hotlist.vue @@ -1,7 +1,6 @@ <template> <div> <md-table v-model="users" md-sort="title" md-sort-order="asc" md-card md-fixed-header> - <md-table-row slot="md-table-row" slot-scope="{ item }" style="margin-top:100px"> <md-table-cell md-label="�ш퀬" md-sort-by="stock" md-numeric> {{ @@ -19,13 +18,12 @@ }} </md-table-cell> <md-table-cell> - <md-button class="md-primary md-raised">援щℓ</md-button> + <md-button class="md-primary md-raised" v-on:click="goBuyPage(item._id)">援щℓ</md-button> </md-table-cell> <md-table-cell> - <md-button class="md-raised md-accent">�먮ℓ</md-button> + <md-button class="md-raised md-accent" v-on:click="goSellPage(item._id)">�먮ℓ</md-button> </md-table-cell> </md-table-row> - </md-table> </div> </template> @@ -45,25 +43,28 @@ const searchByName = (items, term) => { export default { name: "TableSearch", data: () => ({ - users: [ - - ] + users: [] }), methods: { + goBuyPage(bookId) { + this.$router.push({ name: "HomeBuy", params: { id: bookId } }); + }, + goSellPage(bookId) { + this.$router.push({ name: "HomeSell", params: { id: bookId } }); + } }, created() { - this.$http.get("/api/books").then(response => { + this.$http.get("/api/books").then(response => { this.users = response.data; console.log("success"); console.log(this.users); - }); } }; </script> <style lang="scss" scoped> - .md-field { - max-width: 500px; - } +.md-field { + max-width: 500px; +} </style> diff --git a/frontend/src/components/login/Login.vue b/frontend/src/components/login/Login.vue index a1faac8c63b356af927f02776dcf184445e4b642..6ed1512e14363669779758ffe65fbfc13e30f9c5 100644 --- a/frontend/src/components/login/Login.vue +++ b/frontend/src/components/login/Login.vue @@ -1,43 +1,101 @@ <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: 500px"> - <md-dialog-title>Login</md-dialog-title> - <md-field class="select"> - <label>ID</label> - <md-input v-model="user.id" /> - </md-field> + + <md-dialog :md-active.sync="active" style="width: 500px; height: 500px"> + <md-dialog-title>Login</md-dialog-title> + <form novalidate @submit.prevent="validateUser"> + <md-content> + <md-field :class="getValidationClass('id')"> + <label>ID</label> + <md-input name="ID" id="ID" v-model="user.id" :disabled="sending" /> + <span class="md-error" v-if="!$v.user.id.required">The ID is required"</span> + <span class="md-error" v-else-if="!$v.user.id.minlength" + >�꾩씠�붾뒗 �ㅼ꽢 �먮━ �댁긽�댁뼱�� �⑸땲��.</span + > + </md-field> - <md-field class="select"> - <label>Password</label> - <md-input v-model="user.password" type="password" /> - </md-field> + <md-field :class="getValidationClass('password')"> + <label>Password</label> + <md-input v-model="user.password" type="password" :disabled="sending" /> + <span class="md-error" v-if="!$v.user.password.required" + >The Password is required</span + > + <span class="md-error" v-else-if="!$v.user.password.minlength" + >鍮꾨�踰덊샇�� �� �먮━ �댁긽�댁뼱�� �⑸땲��.</span + > + </md-field> - <md-button class="md-raised md-primary" v-on:click="login">Login</md-button> - <md-button class="md-primary" v-on:click="active = false">Close</md-button> - </md-dialog> + <md-button + class="md-raised md-primary" + type="submit" + :disabled="sending" + >Login</md-button + > + <md-button class="md-primary" v-on:click="active = false" + >Close</md-button + > + </md-content> + </form> + </md-dialog> + </form> </div> </template> <script> import Vue from "vue"; +import Vuelidate from "vuelidate"; import VueMaterial from "vue-material"; import "vue-material/dist/vue-material.min.css"; import "vue-material/dist/theme/default.css"; +import { validationMixin } from "vuelidate"; +import { required, minLength } from "vuelidate/lib/validators"; Vue.use(VueMaterial); +Vue.use(Vuelidate); export default { + name: "FormValidation", + mixins: [validationMixin], data: function() { return { active: false, user: { - id: "", - password: "" - } + id: null, + password: null + }, + sending: false }; }, + validations: { + user: { + id: { + required, + minLength: minLength(5) + } + , + password: { + required, + minLength: minLength(3) + } + } + }, methods: { + getValidationClass(fieldName) { + const field = this.$v.user[fieldName]; + if (field) { + return { + "md-invalid": field.$invalid && field.$dirty + }; + } + }, + validateUser() { + this.$v.$touch(); + if (!this.$v.$invalid) { + this.login(); + } + }, login: function(event) { + this.sending = true; console.log("login start"); this.$http .post("/api/login/checkLogin", { @@ -48,6 +106,7 @@ export default { //濡쒓렇�� �깃났 alert("success login"); this.active = false; + this.sending = false; location.reload(); }, error => { @@ -63,7 +122,7 @@ export default { }; </script> -<style scoped> +<style> .select { margin: 15px; display: inline-flex; diff --git a/frontend/src/components/login/SignUp.vue b/frontend/src/components/login/SignUp.vue index 958e483c7e2f4d7349b3de013ce724cf85b23d9f..77a90215892a86d85ea2c90637766b436af843df 100644 --- a/frontend/src/components/login/SignUp.vue +++ b/frontend/src/components/login/SignUp.vue @@ -3,33 +3,91 @@ <md-button class="md-primary" v-on:click="active = true">Sign Up</md-button> <md-dialog :md-active.sync="active" style="width:500px; height: 1000px"> <md-dialog-title>Sign Up</md-dialog-title> - <md-field class="select"> - <label>Name</label> - <md-input name="name" v-model="user.name" /> - </md-field> + <form novalidate @submit.prevent="validateUser"> + <md-content> + <md-field :class="getValidationClass('name')"> + <label>Name</label> + <md-input name="name" v-model="user.name" :disabled="sending" /> + <span class="md-error" v-if="!$v.user.name.required" + >The Name is required"</span + > + <span class="md-error" v-else-if="!$v.user.name.minlength" + >�대쫫�� �� �먮━ �댁긽�댁뼱�� �⑸땲��.</span + > + </md-field> - <md-field class="select"> - <label for="id">ID</label> - <md-input name="id" v-model="user.id" /> - </md-field> + <md-field :class="getValidationClass('id')"> + <label for="id">ID</label> + <md-input name="id" v-model="user.id" :disabled="sending" /> + <span class="md-error" v-if="!$v.user.id.required" + >The ID is required"</span + > + <span class="md-error" v-else-if="!$v.user.id.minlength" + >�꾩씠�붾뒗 �ㅼ꽢 �먮━ �댁긽�댁뼱�� �⑸땲��.</span + > + </md-field> - <md-field :md-toggle-password="true" class="select"> - <label for="password">Password</label> - <md-input name="password" v-model="user.password" type="password" /> - </md-field> + <md-field + :md-toggle-password="true" + :class="getValidationClass('password')" + > + <label for="password">Password</label> + <md-input + name="password" + v-model="user.password" + type="password" + :disabled="sending" + /> + <span class="md-error" v-if="!$v.user.password.required" + >The Password is required</span + > + <span class="md-error" v-else-if="!$v.user.password.minlength" + >鍮꾨�踰덊샇�� �� �먮━ �댁긽�댁뼱�� �⑸땲��.</span + > + </md-field> - <md-field class="select"> - <label for="email">Email</label> - <md-input name="email" v-model="user.email" /> - </md-field> + <md-field :class="getValidationClass('email')"> + <label for="email">Email</label> + <md-input + name="email" + type="email" + v-model="user.email" + :disabled="sending" + /> + <span class="md-error" v-if="!$v.user.email.required" + >The email is required</span + > + <span class="md-error" v-else-if="!$v.user.email.email" + >Invalid email</span + > + </md-field> - <md-field class="select"> - <label for="phonenumber">Phone Number</label> - <md-input name="phonenumber" v-model="user.phonenumber" /> - </md-field> + <md-field :class="getValidationClass('phonenumber')"> + <label for="phonenumber">Phone Number</label> + <md-input + name="phonenumber" + v-model="user.phonenumber" + :disabled="sending" + /> + <span class="md-error" v-if="!$v.user.phonenumber.required" + >The Phone Number is required</span + > + <span class="md-error" v-else-if="!$v.user.phonenumber.minlength" + >�대��� 踰덊샇�� 10�먮━ �댁긽�댁뼱�� �⑸땲��.</span + > + </md-field> - <md-button class="md-raised md-primary" v-on:click="signUp">Sign Up</md-button> - <md-button class="md-primary" v-on:click="active = false">Close</md-button> + <md-button + class="md-raised md-primary" + type="submit" + :disabled="sending" + >Sign Up</md-button + > + <md-button class="md-primary" v-on:click="active = false" + >Close</md-button + > + </md-content> + </form> </md-dialog> </div> </template> @@ -47,13 +105,17 @@ <script> import Vue from "vue"; - +import Vuelidate from "vuelidate"; import VueMaterial from "vue-material"; import "vue-material/dist/vue-material.min.css"; import "vue-material/dist/theme/default.css"; +import { validationMixin } from "vuelidate"; +import { required, minLength, email } from "vuelidate/lib/validators"; Vue.use(VueMaterial); +Vue.use(Vuelidate); export default { + mixins: [validationMixin], data: function() { return { user: { @@ -67,11 +129,48 @@ export default { active: false }; }, + validations: { + user: { + id: { + required, + minLength: minLength(5) + }, + password: { + required, + minLength: minLength(3) + }, + name: { + required, + minLength: minLength(2) + }, + email: { + required, + email + }, + phonenumber: { + required, + minLength: minLength(10) + } + } + }, methods: { + getValidationClass(fieldName) { + const field = this.$v.user[fieldName]; + if (field) { + return { + "md-invalid": field.$invalid && field.$dirty + }; + } + }, + validateUser() { + this.$v.$touch(); + if (!this.$v.$invalid) { + this.signUp(); + } + }, signUp: function(event) { this.$http .post("/api/login/signUp", { - //axios �ъ슜 user: this.user }) .then(response => { diff --git a/frontend/src/components/mainpage.vue b/frontend/src/components/mainpage.vue index 4d4b1dec674c685b657f26d88a74d4e68a26b771..58bf9f3807722ec84cb1bef47df655b80ba344c1 100644 --- a/frontend/src/components/mainpage.vue +++ b/frontend/src/components/mainpage.vue @@ -4,7 +4,10 @@ <div class="md-layout-item"> <img src="../../static/img/img2.jpg" /> </div> - <div class="md-layout-item" style="backgroundColor:#F2CB61; height:30px;">�댁쑄援�</div> + <div + class="md-layout-item" + style="backgroundColor:#F2CB61; height:30px;" + >2019 WebSysProject - Team 202</div> </div> </div> </template> \ No newline at end of file diff --git a/frontend/src/components/profilecomponent/buylist.vue b/frontend/src/components/profilecomponent/buylist.vue index a53f69ef04cb4e13d370d79317b515717371020b..445931b5dee178964825004bdec3161f112327fc 100644 --- a/frontend/src/components/profilecomponent/buylist.vue +++ b/frontend/src/components/profilecomponent/buylist.vue @@ -4,60 +4,105 @@ <span>Buylist</span> </md-toolbar> <md-list class="md-double-line" style="height : 230px"> - <md-list-item v-for="user in users" :key="user.title"> + <md-list-item + v-for="transaction in transactions" + :key="transaction._id" + v-if="transaction.buyerId == userId" + > <md-button class="md-icon-button md-raised" style="color:#1DDB16;backgroundColor:#1DDB16"> <img src="../../assets/book-open-flat.png" /> </md-button> <div class="md-list-item-text"> - <span> {{user.title}}</span> + <span> {{transaction.bookTitle}}</span> <span> 援щℓ ��湲곗쨷</span> + <span> �먮ℓ�� �꾩씠��: {{transaction.sellerId}}</span> </div> - <md-button class="md-icon-button md-raised md-accent"> + <md-button + class="md-icon-button md-raised md-accent" + v-on:click="cancelTransaction(transaction.bookTitle)" + > <img src="../../assets/x-512.png" /> </md-button> - <md-button class="md-icon-button md-raised md-primary"> + <md-button + class="md-icon-button md-raised md-primary" + v-on:click="successTransaction(transaction.bookTitle)" + > <img src="../../assets/check-icon.png" /> </md-button> </md-list-item> </md-list> - </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 { - name: 'SubheaderExample', +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 { + name: "SubheaderExample", data: () => ({ - users: [], + transactions: [], + userId: "" }), + computed: { + // buyerTransaction() { - v-for�� computed �덉벐硫� 肄붾뱶 鍮④컙�됰맖, �묐룞�� �� + // return this.transactions.filter(tran => { + // if(this.buyerId === this.userId) { + // return mov; + // } + // }) + // } + }, methods: { - + cancelTransaction(book_Title) { + this.$http + .post("/api/transaction/cancel", { + bookTitle: book_Title + }) + .then(response => { + alert("嫄곕옒瑜� 痍⑥냼�섏��듬땲��."); + location.reload(); + }) + .catch(error => { + alert(error); + }); + }, + successTransaction(book_Title) { + this.$http + .post("/api/transaction/success", { + bookTitle: book_Title + }) + .then(response => { + alert("援щℓ瑜� �뺤씤�⑸땲��."); + location.reload(); + }) + .catch(error => { + alert(error); + }); + } }, - - mounted: function () { - this.$http.get("/api/books").then(response => { - this.users = response.data; + + mounted: function() { + this.$http.get("/api/transaction").then(response => { + this.transactions = response.data; console.log("success"); - console.log(this.users); - }) + console.log(this.transactions); + }); + this.$http.get("/api/login/getUserId").then(response => { + this.userId = response.data; + }); } - } - - - +}; </script> <style lang="scss" scoped> - .viewport { - width: 100%; - display: inline-block; - vertical-align: top; - } +.viewport { + width: 100%; + display: inline-block; + vertical-align: top; +} </style> \ No newline at end of file diff --git a/frontend/src/components/profilecomponent/sellist.vue b/frontend/src/components/profilecomponent/sellist.vue index 938b92947ed5c7a153aa2ac973ec1209b0a6c42c..cb05be6bda95f453417f93208fa0c063ce69effd 100644 --- a/frontend/src/components/profilecomponent/sellist.vue +++ b/frontend/src/components/profilecomponent/sellist.vue @@ -4,60 +4,99 @@ <span>Sellist</span> </md-toolbar> <md-list class="md-double-line" style="height : 230px"> - <md-list-item v-for="user in users" :key="user.title"> - <md-button class="md-icon-button md-raised" style="color:#1DDB16;backgroundColor:#1DDB16"> + <md-list-item + v-for="transaction in transactions" + :key="transaction._id" + v-if="transaction.sellerId == userId" + > + <md-button + class="md-icon-button md-raised" + style="color:#1DDB16;backgroundColor:#1DDB16" + > <img src="../../assets/book-open-flat.png" /> </md-button> <div class="md-list-item-text"> - <span> {{user.title}}</span> - <span> �먮ℓ ��湲�</span> + <span> {{ transaction.bookTitle }}</span> + <span> �먮ℓ ��湲곗쨷</span> + <span> 援щℓ�� �꾩씠��: {{ transaction.buyerId }}</span> </div> - <md-button class="md-icon-button md-raised md-accent"> + <md-button + class="md-icon-button md-raised md-accent" + v-on:click="cancelTransaction(transaction.bookTitle)" + > <img src="../../assets/x-512.png" /> </md-button> - <md-button class="md-icon-button md-raised md-primary"> + <md-button + class="md-icon-button md-raised md-primary" + v-on:click="successTransaction(transaction.bookTitle)" + > <img src="../../assets/check-icon.png" /> </md-button> </md-list-item> </md-list> - </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 { - name: 'SubheaderExample', +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 { + name: "SubheaderExample", data: () => ({ - users: [], + transactions: [], + userId: "" }), methods: { - + cancelTransaction(book_Title) { + this.$http + .post("/api/transaction/cancel", { + bookTitle: book_Title + }) + .then(response => { + alert("嫄곕옒瑜� 痍⑥냼�섏��듬땲��."); + location.reload(); + }) + .catch(error => { + alert(error); + }); + }, + successTransaction(book_Title) { + this.$http + .post("/api/transaction/success", { + bookTitle: book_Title + }) + .then(response => { + alert("�먮ℓ瑜� �뺤씤�⑸땲��."); + location.reload(); + }) + .catch(error => { + alert(error); + }); + } }, - - mounted: function () { - this.$http.get("/api/books").then(response => { - this.users = response.data; + + mounted: function() { + this.$http.get("/api/transaction").then(response => { + this.transactions = response.data; console.log("success"); - console.log(this.users); - }) + console.log(this.transactions); + }); + this.$http.get("/api/login/getUserId").then(response => { + this.userId = response.data; + }); } - } - - - +}; </script> <style lang="scss" scoped> - .viewport { - width: 100%; - display: inline-block; - vertical-align: top; - } -</style> \ No newline at end of file +.viewport { + width: 100%; + display: inline-block; + vertical-align: top; +} +</style> diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index 4c3e91333a09ec55d480e1be0dba8286d7e7e04e..f63caabf23a87ce9865b12e7aaf9f551b2a158a7 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -24,7 +24,6 @@ export default new Router({ name: "home", component: home }, - { path: "/profile", name: "profile", @@ -35,21 +34,6 @@ export default new Router({ name: "bookindex", component: BookSearchPage }, - { - path: "/login", - name: "Login", - component: Login - }, - { - path: "/logout", - name: "Logout", - component: Logout - }, - { - path: "/signUp", - name: "SignUp", - component: SignUp - }, { path: "/BookSearchPage/buy/:id", name: "BookSearchPageBuy",