Adding Vue.js apps for reviews service

This commit is contained in:
Daniel
2020-11-19 12:41:11 +01:00
committed by Daniel Hutzel
parent 8f01bf911e
commit dae8e96fe1
13 changed files with 198 additions and 45 deletions

72
reviews/app/vue/app.js Normal file
View File

@@ -0,0 +1,72 @@
/* global Vue axios */ //> from vue.html
const $ = sel => document.querySelector(sel)
const GET = (url) => axios.get('/reviews'+url)
const PUT = (cmd,data) => axios.patch('/reviews'+cmd,data)
const POST = (cmd,data) => axios.post('/reviews'+cmd,data)
const reviews = new Vue ({
el:'#app',
data: {
list: [],
review: undefined,
message: {},
Ratings: Object.entries({
5 : '★★★★★',
4 : '★★★★',
3 : '★★★',
2 : '★★',
1 : '★',
}).reverse()
},
methods: {
search: ({target:{value:v}}) => reviews.fetch(v && '&$search='+v),
async fetch (etc='') {
const {data} = await GET(`/Reviews?${etc}`)
reviews.list = data.value
},
async inspect (eve) {
const review = reviews.review = reviews.list [eve.currentTarget.rowIndex-1]
const res = await GET(`/Reviews/${review.ID}/text/$value`)
review.text = res.data
reviews.message = {}
},
async newReview () {
reviews.review = {}
reviews.message = {}
setTimeout (()=> $('form > input').focus(), 111)
},
async submitReview () {
const review = reviews.review; review.rating = parseInt (review.rating) // REVISIT: Okra should be less strict
try {
if (!review.ID) {
const res = await POST(`/Reviews`,review)
reviews.ID = res.data.ID
} else {
console.trace()
await PUT(`/Reviews/${review.ID}`,review)
}
reviews.message = { succeeded: 'Your review was submitted successfully. Thanks.' }
} catch (e) {
reviews.message = { failed: e.response.data.error.message }
}
}
},
filters: {
stars: (r) => ('★'.repeat(Math.round(r))+'☆☆☆☆☆').slice(0,5),
datetime: (d) => d && new Date(d).toLocaleString(),
},
})
// initially fill list of my reviews
reviews.fetch()

View File

@@ -0,0 +1,62 @@
<!DOCTYPE html>
<html>
<head>
<title> Capire Reviews </title>
<link rel="stylesheet" href="https://unpkg.com/primitive-ui/dist/css/main.css">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<style>
.hovering tr:hover td { color:cyan; background: #123; cursor: pointer; }
.rating-stars { color:teal }
.succeeded { color:teal }
.failed { color:red }
textarea { line-height: 1.4em;}
</style>
</head>
<body class="small-container", style="margin-top: 70px;">
<div id='app'>
<h1> {{ document.title }} </h1>
<input type="text" placeholder="Search..." @input="search">
<table id='my-reviews' class="hovering">
<thead>
<th> Subject </th>
<th> Rating </th>
<th> Title </th>
<th> Date </th>
</thead>
<tr v-for="review in list" v-bind:id="review.ID" v-on:click="inspect">
<td>{{ review.subject }}</td>
<td class="rating-stars">{{ review.rating | stars }}</td>
<td>{{ review.title }}</td>
<td>{{ review.date | datetime }}</td>
</tr>
</table>
<button v-on:click="newReview()" class="round-button muted-button">Add Review...</button>
<form v-if="review" @submit.prevent="submitReview">
<input id="subject" type="text" v-model="review.subject" style="font-weight:bold; display:inline; width:20%">
<input type="text" v-model="review.title" style="font-weight:bold; display:inline; width:60%">
<select v-model="review.rating" style="font-weight:bold; display:inline; width:17%; float: right;">
<option v-for="option in Ratings" v-bind:value="option[0]"> {{ option[1] }} </option>
</select>
<textarea v-model="review.text" rows="9"></textarea>
<input type="submit" value="Submit" class="round-button muted-button">
<span class="succeeded"> {{ message.succeeded }} </span>
<span class="failed"> {{ message.failed }} </span>
</form>
<div v-else style="margin-top: 2em;">
( click on a row to see details... )
</div>
</div>
</body>
<script src="app.js"></script>
</html>