Merge branches 'frontend/input-validation' and 'master' of gitlab.com:CIEFWorldwideSdnBhd/exchange into frontend/input-validation

# Conflicts:
#	resources/assets/js/pages/booking/uploadUserBankSlip.vue
This commit is contained in:
Jack Goh
2018-07-31 15:00:08 +08:00
6 changed files with 404 additions and 282 deletions
@@ -46,7 +46,6 @@ class RegisterController extends Controller
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|name|max:255',
'marking' => 'required|max:255|unique:markings',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
@@ -61,6 +60,11 @@ class RegisterController extends Controller
*/
protected function create(Request $data)
{
$this->validate($data, [
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
]);
$marking = Marking::Where('email',$data['email'])->first();
if(!$marking){
+3 -3
View File
@@ -403,7 +403,7 @@ class BookingController extends Controller
}
$validator = Validator::make($request->all(), [
'file' => 'max:3072'
'file' => 'max:10000' // image size
]);
if($validator->fails())
@@ -497,7 +497,7 @@ class BookingController extends Controller
}
$validator = Validator::make($request->all(), [
'file' => 'max:3072'
'file' => 'max:10000'
]);
if($validator->fails())
@@ -767,7 +767,7 @@ class BookingController extends Controller
}
$validator = Validator::make($request->all(), [
'invoice_path' => 'max:3072'
'invoice_path' => 'max:10000'
]);
if($validator->fails())
@@ -32,7 +32,7 @@ class ChinaBankSlipController extends Controller
}
$validator = Validator::make($request->all(), [
'china_bank_slips' => 'max:3072'
'china_bank_slips' => 'max:10000'
]);
if($validator->fails()){
@@ -0,0 +1,33 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class ChangeDatatypeInBookingTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('bookings', function (Blueprint $table) {
$table->string('account_num')->nullable()->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('bookings', function (Blueprint $table) {
//
});
}
}
+15 -16
View File
@@ -5,65 +5,64 @@
<card :title="$t('register')">
<form @submit.prevent="register" @keydown="form.onKeydown($event)">
<!-- Marking -->
<div class="form-group row" :class="{'has-error': errors.has('marking') }">
<div class="form-group row">
<label class="col-md-3 col-form-label text-md-right">{{ $t('Marking') }}</label>
<div class="col-md-7">
<el-input v-model="form.marking" v-validate="'required|max:255'" type="text" name="marking" placeholder="Marking Number">
</el-input>
<span class="text-danger" v-if="errors.has('marking')">{{ errors.first('marking') }}<br/></span>
<input v-model="form.marking" :class="{ 'is-invalid': form.errors.has('marking') }" class="form-control" type="text" name="marking">
<has-error :form="form" field="marking"/>
</div>
</div>
<!-- Email -->
<div class="form-group row" :class="{'has-error': errors.has('email') }">
<div class="form-group row">
<label class="col-md-3 col-form-label text-md-right">{{ $t('email') }}</label>
<div class="col-md-7">
<el-input v-model="form.email" v-validate="'required|max:255'" type="email" name="email" placeholder="Email">
<el-input v-model="form.email" type="email" name="email" placeholder="Email">
</el-input>
<span class="text-danger" v-if="errors.has('email')">{{ errors.first('email') }}</span>
<has-error :form="form" field="email"/>
</div>
</div>
<!-- Password -->
<div class="form-group row" :class="{'has-error': errors.has('password') }">
<div class="form-group row">
<label class="col-md-3 col-form-label text-md-right">{{ $t('password') }}</label>
<div class="col-md-7">
<el-input v-if="password_visible" v-model="form.password" v-validate="'required|min:6|max:255'" type="text" name="password" placeholder="Password">
<el-input v-if="password_visible" v-model="form.password" type="text" name="password" placeholder="Password">
<template slot="append">
<el-button type="primary" @click="password_visible = !password_visible"><i class="fas fa-eye"></i></el-button>
</template>
</el-input>
<el-input v-else v-model="form.password" v-validate="'required|min:6|max:255'" type="password" name="password" placeholder="Password">
<el-input v-else v-model="form.password" type="password" name="password" placeholder="Password">
<template slot="append">
<el-button type="primary" @click="password_visible = !password_visible"><i class="fas fa-eye-slash"></i></el-button>
</template>
</el-input>
<span class="text-danger" v-if="errors.has('password')">{{ errors.first('password') }}</span>
<has-error :form="form" field="password"/>
</div>
</div>
<!-- Password Confirmation -->
<div class="form-group row" :class="{'has-error': errors.has('confirm_password') }">
<div class="form-group row">
<label class="col-md-3 col-form-label text-md-right">{{ $t('confirm_password') }}</label>
<div class="col-md-7">
<el-input v-if="password_confirmation_visible" v-model="form.password_confirmation" v-validate="'required|min:6|max:255'" type="text" name="password_confirmation" placeholder="Confirm Password">
<el-input v-if="password_confirmation_visible" v-model="form.password_confirmation" type="text" name="password_confirmation" placeholder="Confirm Password">
<template slot="append">
<el-button type="primary" @click="password_confirmation_visible = !password_confirmation_visible"><i class="fas fa-eye"></i></el-button>
</template>
</el-input>
<el-input v-else v-model="form.password_confirmation" v-validate="'required|min:6|max:255'" type="password" name="password_confirmation" placeholder="Confirm Password">
<el-input v-else v-model="form.password_confirmation" type="password" name="password_confirmation" placeholder="Confirm Password">
<template slot="append">
<el-button type="primary" @click="password_confirmation_visible = !password_confirmation_visible"><i class="fas fa-eye-slash"></i></el-button>
</template>
</el-input>
<span class="text-danger" v-if="errors.has('password_confirmation')">{{ errors.first('password_confirmation') }}<br/></span>
<has-error :form="form" field="password_confirmation"/>
</div>
</div>
<div class="form-group row">
<div class="col-md-7 offset-md-3 d-flex">
<!-- Submit Button -->
<v-button :loading="form.busy" :disabled="errors.any() || form.password=='' || form.password_confirmation=='' || form.email=='' || form.marking=='' ? true : false">
<v-button :loading="form.busy" :disabled="form.password=='' || form.password_confirmation=='' || form.email=='' || form.marking=='' ? true : false">
{{ $t('register') }}
</v-button>
@@ -1,98 +1,127 @@
<template>
<el-main>
<progress-track v-model="status"/>
<div align="center" v-if="booking.user_bankslip_path">
<h1 class="alert-heading">Your Bank Slip Has Been Rejected</h1>
<p>Reason : {{ booking.reject_reason }}</p>
<p>Please Reupload Your Bank Slip</p>
<hr>
</div>
<div v-else>
<h1>Waiting For Payment</h1>
</div>
<<<<<<< HEAD <progress-track v-model="status" />
<div align="center" v-if="booking.user_bankslip_path">
<h1 class="alert-heading">Your Bank Slip Has Been Rejected</h1>
<p>Reason : {{ booking.reject_reason }}</p>
<p>Please Reupload Your Bank Slip</p>
<hr>
</div>
<div v-else>
<h1>Waiting For Payment</h1>
</div>
=======
<progress-track v-model="status" />
<div align="center" v-if="booking.user_bankslip_path">
<h4 style="margin-top:5%">
Your Bankslip Has Been Rejected, Please Reupload Your Bankslip
<br> Reason : {{ booking.reject_reason }}
</h4>
<br>
<br>
</div>
<div v-else align="center">
<h1>Please Upload Bankslip</h1>
</div>
>>>>>>> 12fd1676189e5e62e226b96068bfba6afa4af8e5
<div class="row">
<table class="table table-striped">
<tbody>
<tr>
<td>Amount : </td>
<td><b>RMB {{ booking.amount }}</b></td>
</tr>
<tr>
<td>Bankin Amount : </td>
<td><b> MYR {{ booking.bankin_amount }}</b></td>
</tr>
<tr>
<td colspan="2">
<b>{{ bankDetail.company_name }}</b><br>
{{ bankDetail.bank_name }} : {{ bankDetail.acc_no }}
</td>
</tr>
</tbody>
</table>
</div>
<div class="row timer">
<div class="col">
<vue-countdown :countdownend="handleCoutdownend" :time="booking.timeout">
<template slot-scope="props">Time Remaining<br>{{ props.days }} days, {{ props.hours }} hours, {{ props.minutes }} minutes, {{ props.seconds }} seconds.</template>
</vue-countdown>
<div class="row">
<table class="table table-striped">
<tbody>
<tr>
<td>Amount : </td>
<td>
<b>RMB {{ booking.amount }}</b>
</td>
</tr>
<tr>
<td>Bankin Amount : </td>
<td>
<b> MYR {{ booking.bankin_amount }}</b>
</td>
</tr>
<tr>
<td colspan="2">
<b>{{ bankDetail.company_name }}</b>
<br> {{ bankDetail.bank_name }} : {{ bankDetail.acc_no }}
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- upload image -->
<div class="row upload">
<div class="col">
<el-upload :action="'/api/booking/' + booking_id + '/upload-user-bankslip'"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-error="uploadError"
accept=".jpeg, .jpg, .png, .bmp, .doc, .docx, .xls, .xlsx, .pdf"
list-type="picture-card" align="center">
<i class="el-icon-plus" />
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img :src="dialogImageUrl" width="100%" alt="">
</el-dialog>
<div class="row timer">
<div class="col">
<vue-countdown :countdownend="handleCoutdownend" :time="booking.timeout">
<template slot-scope="props">Time Remaining
<br>{{ props.days }} days, {{ props.hours }} hours, {{ props.minutes }} minutes, {{ props.seconds }} seconds.</template>
</vue-countdown>
</div>
</div>
</div>
<!-- upload image end -->
<div class="row bankinAmount">
<div class="col">
Bankin Amount (RM) :<br>
<el-form ref="user_slip_form" :model="user_slip_form" :rules="rules">
<el-form-item prop="transfer_amount">
<el-input class="transferAmountInput" v-model="user_slip_form.transfer_amount" type="text" placeholder="Transfer Amount"/>
</el-form-item>
<el-form-item>
<el-button :loading="loading" type="primary" @click="submitUserSlip('user_slip_form')">Submit</el-button>
<router-link :to="{ name: 'home' }" class="small ml-auto my-auto">
Upload Later
</router-link>
</el-form-item>
</el-form>
<!-- upload image -->
<div class="row upload">
<div class="col">
<!-- <el-upload :action="'/api/booking/' + booking_id + '/upload-user-bankslip'" :show-file-list="false" :on-preview="handlePictureCardPreview"
:on-remove="handleRemove" :on-error="uploadError" accept=".jpeg, .jpg, .png, .bmp, .doc, .docx, .xls, .xlsx, .pdf" list-type="picture-card"
align="center">
<i class="el-icon-plus" />
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img :src="dialogImageUrl" width="100%" alt="">
</el-dialog> -->
<el-upload class="avatar-uploader" :action="'/api/booking/' + booking_id + '/upload-user-bankslip'" :show-file-list="false"
:on-success="handleUploadSuccess" :before-upload="beforeFileUpload" algin="center">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</div>
</div>
<!-- upload image end -->
<div class="row bankinAmount">
<div class="col">
Bankin Amount (RM) :
<br>
<el-form ref="user_slip_form" :model="user_slip_form" :rules="rules">
<el-form-item prop="transfer_amount">
<el-input class="transferAmountInput" v-model="user_slip_form.transfer_amount" type="text" placeholder="Transfer Amount"
/>
</el-form-item>
<el-form-item>
<el-button :loading="loading" type="primary" @click="submitUserSlip('user_slip_form')">Submit</el-button>
<router-link :to="{ name: 'home' }" class="small ml-auto my-auto">
Upload Later
</router-link>
</el-form-item>
</el-form>
</div>
</div>
</div>
</el-main>
</template>
<style>
h1 {
margin-top:5%;
font-size:3vw;
text-align:center;
margin-bottom:3%;
}
.timer, .upload, .bankinAmount {
margin-top: 5%;
font-size: 3vw;
text-align: center;
margin-bottom: 3%;
}
.timer,
.upload,
.bankinAmount {
text-align: center;
}
.transferAmountInput {
width: 20%;
}
.row {
margin-bottom: 3%;
}
td:last-child {
text-align:center;
margin-bottom: 3%;
}
td:last-child {
text-align: center;
}
@media screen and (max-width: 767px) {
.transferAmountInput {
width: 60%;
@@ -101,210 +130,267 @@
font-size: 3.5vmin;
}
h1 {
font-size: 1em;
}
font-size: 1em;
}
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
<script>
import VueCountdown from '@xkeshi/vue-countdown'
import ProgressTrack from '~/components/ProgressTrack'
import axios from 'axios'
import VueCountdown from '@xkeshi/vue-countdown'
import ProgressTrack from '~/components/ProgressTrack'
import axios from 'axios'
export default {
middleware: ['auth'],
name: 'MyComponent',
components: {
'vue-countdown': VueCountdown,
'progress-track': ProgressTrack
},
data () {
return {
status: 2,
start: false,
loading: false,
dialogImageUrl: '',
dialogVisible: false,
booking_id: this.$route.params.id,
user_slip_form: {
transfer_amount: ''
},
booking: {
amount: '',
bankin_amount: '',
timeout: 1,
term : '123',
user_bankslip_path: null,
reject_reason: null,
},
rules: {
transfer_amount: [{
required: true,
message: 'Please input amount',
trigger: 'change'
}]
},
active_bank_setting: {
x1_bank_id: null,
x2_bank_id: null,
beneficiary_id: null
},
bankDetail: {}
}
},
beforeCreate () {
const loading = this.$loading({
lock: true,
text: 'Please wait..',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
axios.get('/api/booking/' + this.$route.params.id)
.then((response) => {
this.booking.amount = response.data.amount;
this.booking.bankin_amount = response.data.bia;
this.booking.timeout = response.data.timeout * 1000;
this.booking.term = response.data.term;
if (response.data.user_bankslip_path)
{
this.booking.user_bankslip_path = response.data.user_bankslip_path
this.booking.reject_reason = response.data.reject_reason
}
console.log(this.booking);
this.start = true;
if (this.booking.timeout < 0){
this.$message({
showClose: true,
message: 'Booking timeout, please make another booking.',
type: 'error',
duration: 30000
export default {
middleware: ['auth'],
name: 'MyComponent',
components: {
'vue-countdown': VueCountdown,
'progress-track': ProgressTrack
},
data() {
return {
status: 2,
start: false,
loading: false,
dialogImageUrl: '',
imageUrl: null,
dialogVisible: false,
booking_id: this.$route.params.id,
user_slip_form: {
transfer_amount: ''
},
booking: {
amount: '',
bankin_amount: '',
timeout: 1,
term: '123',
user_bankslip_path: null,
reject_reason: null,
},
rules: {
transfer_amount: [{
required: true,
message: 'Please input amount',
trigger: 'change'
}]
},
active_bank_setting: {
x1_bank_id: null,
x2_bank_id: null,
beneficiary_id: null
},
bankDetail: {}
}
},
beforeCreate() {
const loading = this.$loading({
lock: true,
text: 'Please wait..',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
})
this.$router.push({
name: 'home'
})
}
}).catch((error) => {
this.$router.push({
name: 'notfound'
})
console.log(error)
})
axios.get('/api/active-bank')
.then((response) => {
this.active_bank_setting = response.data;
var url = '';
if(this.booking.term === 'x1_cash' || this.booking.term === 'x1_cheque' ||this.booking.term === 'x1_ba'){
url = '/api/malaysia-bank/' + this.active_bank_setting.x1_bank_id;
}
else if(this.booking.term === 'x2_cash' || this.booking.term === 'x2_cheque' ||this.booking.term === 'x2_ba'){
url = '/api/malaysia-bank/' + this.active_bank_setting.x2_bank_id;
}
axios.get(url)
.then((response) => {
this.bankDetail = response.data;
loading.close()
})
.catch((error) => {
loading.close()
console.log(error);
axios.get('/api/booking/' + this.$route.params.id)
.then((response) => {
this.booking.amount = response.data.amount;
this.booking.bankin_amount = response.data.bia;
this.booking.timeout = response.data.timeout * 1000;
this.booking.term = response.data.term;
if (response.data.user_bankslip_path) {
this.booking.user_bankslip_path = response.data.user_bankslip_path
this.booking.reject_reason = response.data.reject_reason
}
console.log(this.booking);
this.start = true;
if (this.booking.timeout < 0) {
this.$message({
showClose: true,
message: 'Fetch data fail',
message: 'Booking timeout, please make another booking.',
type: 'error',
duration: 10000
duration: 30000
})
this.$router.push({
name: 'home'
})
}
}).catch((error) => {
this.$router.push({
name: 'notfound'
})
console.log(error)
})
axios.get('/api/active-bank')
.then((response) => {
this.active_bank_setting = response.data;
var url = '';
if (this.booking.term === 'x1_cash' || this.booking.term === 'x1_cheque' || this.booking.term === 'x1_ba') {
url = '/api/malaysia-bank/' + this.active_bank_setting.x1_bank_id;
} else if (this.booking.term === 'x2_cash' || this.booking.term === 'x2_cheque' || this.booking.term === 'x2_ba') {
url = '/api/malaysia-bank/' + this.active_bank_setting.x2_bank_id;
}
axios.get(url)
.then((response) => {
this.bankDetail = response.data;
loading.close()
})
.catch((error) => {
loading.close()
console.log(error);
this.$message({
showClose: true,
message: 'Fetch data fail',
type: 'error',
duration: 10000
});
});
})
.catch((error) => {
console.log(error);
this.$message({
showClose: true,
message: 'Fetch bank details fail',
type: 'error',
duration: 10000
});
})
.catch((error) => {
console.log(error);
});
},
methods: {
handleUploadSuccess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw);
this.$message({
showClose: true,
message: 'Fetch bank details fail',
type: 'error',
duration: 10000
});
});
},
methods: {
handleCoutdownend () {
this.$message({
showClose: true,
message: 'Booking timeout, please make another booking.',
type: 'error',
duration: 30000
})
this.$router.push({
name: 'home'
})
},
handleRemove (file, fileList) {
// console.log(file, fileList)
},
uploadError(file,fileList){
this.$message.warning(`Incorrect file format or file size too big.`)
},
handlePictureCardPreview (file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
submitUserSlip (formName) {
if ((this.user_slip_form.transfer_amount < 0) || isNaN(this.user_slip_form.transfer_amount)) {
this.$message({
message: 'Amount must be a number greater than 0',
type: 'warning'
message: 'Uploaded.',
type: 'success',
duration: 5000
})
return
}
this.loading = true
this.$refs[formName].validate((valid) => {
if (valid) {
let newConfirmation = {
amount: this.booking.amount,
term: this.term
},
beforeFileUpload(file) {
//const isJPG = file.type === 'image/jpeg';
const isLt10M = file.size / 10240 / 10240 < 2;
// if (!isJPG) {
// this.$message.error('Avatar picture must be JPG format!');
// }
if (!isLt10M) {
this.$message.error('File size can not exceed 10MB!');
}
} else {
this.loading = false
}
})
let newUserSlip = {
transfer_amount: this.user_slip_form.transfer_amount
}
axios.patch('/api/booking/' + this.booking_id + '/bankslip-amount/', newUserSlip)
.then((response) => {
console.log(response);
this.$message({
showClose: true,
message: 'Your bankinslip has been submitted, please wait admin to approve.',
type: 'success',
duration: 5000
showClose: true,
message: 'Uploading..',
type: 'success',
duration: 5000
})
// return isJPG && isLt2M;
return isLt10M;
},
handleCoutdownend() {
this.$message({
showClose: true,
message: 'Booking timeout, please make another booking.',
type: 'error',
duration: 30000
})
this.$router.push({
name: 'home'
name: 'home'
})
},
handleRemove(file, fileList) {
// console.log(file, fileList)
},
uploadError(file, fileList) {
this.$message.warning(`Incorrect file format or file size too big.`)
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
submitUserSlip(formName) {
if ((this.user_slip_form.transfer_amount < 0) || isNaN(this.user_slip_form.transfer_amount)) {
this.$message({
message: 'Amount must be a number greater than 0',
type: 'warning'
})
return
}
this.loading = true
this.$refs[formName].validate((valid) => {
if (valid) {
let newConfirmation = {
amount: this.booking.amount,
term: this.term
}
} else {
this.loading = false
}
})
let newUserSlip = {
transfer_amount: this.user_slip_form.transfer_amount
}
axios.patch('/api/booking/' + this.booking_id + '/bankslip-amount/', newUserSlip)
.then((response) => {
console.log(response);
})
.catch((error) => {
this.loading = false
this.$message({
showClose: true,
message: 'Please upload your bankin slip first.',
type: 'warning',
duration: 10000
})
console.log(error)
})
},
handleTimeExpire () {
alert('Booking expired')
},
startTimer () {
this.start = true;
this.$message({
showClose: true,
message: 'Your bankinslip has been submitted, please wait admin to approve.',
type: 'success',
duration: 5000
})
this.$router.push({
name: 'home'
})
})
.catch((error) => {
this.loading = false
this.$message({
showClose: true,
message: 'Please upload your bankin slip first.',
type: 'warning',
duration: 10000
})
console.log(error)
})
},
handleTimeExpire() {
alert('Booking expired')
},
startTimer() {
this.start = true;
}
}
}
}
</script>
</script>