mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/exchange-2.0.git
synced 2026-08-19 04:23:55 +00:00
1688 admin work flow clean up and call api
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class WorkflowTimestamp extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'workflow_timestamps';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'node',
|
||||
'seconds',
|
||||
'userId',
|
||||
'session_id'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'timestamp' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the user that owns the workflow timestamp.
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'userId');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateWorkflowTimestampsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('workflow_timestamps', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('node');
|
||||
$table->integer('seconds');
|
||||
$table->unsignedBigInteger('userId');
|
||||
$table->string('session_id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('workflow_timestamps');
|
||||
}
|
||||
}
|
||||
+296
-306
@@ -1,120 +1,119 @@
|
||||
<template>
|
||||
<div class="row justify-content-center align-items-center text-center" style="min-height: 80vh;">
|
||||
<div class="col">
|
||||
<div v-if="currentQuestion">
|
||||
<h2>{{ currentQuestion.text }}</h2>
|
||||
<div v-if="currentQuestionId === 'fill_po'">
|
||||
<div class="box">
|
||||
<div v-for="(order, index) in orderNumbers" :key="index" class="order">
|
||||
<p>{{ order }}</p>
|
||||
</div>
|
||||
Total: CNY
|
||||
</div>
|
||||
<button @click="selectOrder(order, 'edit')" class="btn btn-primary">Edit PO</button>
|
||||
</div>
|
||||
<div v-else-if="currentQuestionId === '1688'">
|
||||
<div>Login Information</div>
|
||||
<login-form-component></login-form-component>
|
||||
<button @click="selectOrder(order, 'issue_login')" class="btn btn-primary">Login Issue</button>
|
||||
<button @click="selectOrder(order, 'dummy_login')" class="btn btn-primary">Login Successful</button>
|
||||
</div>
|
||||
<div v-else-if="currentQuestionId === 'login_successful'">
|
||||
<div>Order Information</div>
|
||||
<button @click="selectOrder(order, 'error_order')" class="btn btn-primary">Can't verify order?</button>
|
||||
<button @click="selectOrder(order, 'verify_order')" class="btn btn-primary">Order Verified</button>
|
||||
</div>
|
||||
<div v-else-if="currentQuestionId === 'order_verify'">
|
||||
<div>Order Amount</div>
|
||||
<div class="box">
|
||||
<div v-for="(order, index) in orderNumbers" :key="index" class="order">
|
||||
<input v-model="orderNumbers[index]" class="form-control" />
|
||||
</div>
|
||||
CNY
|
||||
</div>
|
||||
<button @click="selectOrder(order, 'yes_order')" class="btn btn-primary">Yes</button>
|
||||
<button @click="selectOrder(order, 'back_order')" class="btn btn-primary">Back</button>
|
||||
</div>
|
||||
<div v-else-if="currentQuestionId === 'approve_po'">
|
||||
<div class="box">
|
||||
<div v-for="(order, index) in orderNumbers" :key="index" class="order">
|
||||
<p>{{ order }}</p>
|
||||
</div>
|
||||
Total: CNY
|
||||
</div>
|
||||
<button @click="selectOrder(order, 'approve')" class="btn btn-primary">Approve PO</button>
|
||||
<button @click="selectOrder(order, 'edit')" class="btn btn-primary">Edit PO</button>
|
||||
<button @click="selectOrder(order, 'reject')" class="btn btn-primary">Reject PO</button>
|
||||
</div>
|
||||
<div v-else-if="currentQuestionId === 'edit_po'">
|
||||
<div class="box">
|
||||
<div v-for="(order, index) in orderNumbers" :key="index" class="order">
|
||||
<input v-model="orderNumbers[index]" class="form-control" />
|
||||
</div>
|
||||
<button @click="addOrder" class="btn btn-primary">Add Order</button>
|
||||
<div>Total: CNY</div>
|
||||
</div>
|
||||
<button @click="issueOthers" class="btn btn-primary">Issue?</button>
|
||||
<button @click="saveOrders" class="btn btn-primary">Done</button>
|
||||
</div>
|
||||
<div v-else-if="currentQuestionId === '1688_submit'">
|
||||
<div class="box">
|
||||
<h3>Upload English PO</h3>
|
||||
<input type="file" id="image-upload" class="image-upload">
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Upload China PO</h3>
|
||||
<input type="file" id="image-upload" class="image-upload">
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Upload bank slip</h3>
|
||||
<input type="file" id="image-upload" class="image-upload">
|
||||
</div>
|
||||
<button @click="nextorder" class="btn btn-primary">Proceed to next order</button>
|
||||
<button @click="submit_issue" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
<div v-else-if="currentQuestionId === 'po_others'">
|
||||
<div class="box">
|
||||
<h3>What issue did you encounter?</h3>
|
||||
<input type="text" id="issue" class="text-box" placeholder="Describe the issue...">
|
||||
<div class="upload-text">Upload an image if needed</div>
|
||||
<input type="file" id="image-upload" class="image-upload">
|
||||
</div>
|
||||
<button @click="issueOthers" class="btn btn-primary">Back</button>
|
||||
<button @click="submit" class="btn btn-primary">Submit issue</button>
|
||||
</div>
|
||||
<div v-else-if="currentQuestionId === '1688_others'">
|
||||
<div class="box">
|
||||
<h3>What issue did you encounter?</h3>
|
||||
<input type="text" id="issue" class="text-box" placeholder="Describe the issue...">
|
||||
<div class="upload-text">Upload an image if needed</div>
|
||||
<input type="file" id="image-upload" class="image-upload">
|
||||
</div>
|
||||
<button @click="issue1688" class="btn btn-primary">Back</button>
|
||||
<button @click="submit" class="btn btn-primary">Submit issue</button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="answer-container">
|
||||
<div v-for="(answer, index) in currentQuestion.answers" :key="index" class="answer-item">
|
||||
<button @click="selectAnswer(answer.next)" class="btn btn-primary">
|
||||
{{ answer.text }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="m-b-50" :class="{ 'text-success': timer }">{{ formattedTime }}</h1>
|
||||
<div v-if="isLoading" class="row">
|
||||
<div class="col">
|
||||
<loading-component></loading-component>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="readyToWork">
|
||||
<h1>Are you ready to work today?</h1>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button @click="startQuiz" class="btn btn-primary">Yes</button>
|
||||
<button @click="readyToWork = !readyToWork" class="btn btn-primary">No</button>
|
||||
<div v-else class="row">
|
||||
<div class="col">
|
||||
<div v-if="currentQuestion && Object.keys(currentQuestion).length">
|
||||
<h2 v-if="currentQuestion.text">{{ currentQuestion.text }}</h2>
|
||||
|
||||
<div v-if="currentQuestionId === '1688'">
|
||||
<h1>Login Information</h1>
|
||||
<div v-if="externalApiResponse.data"
|
||||
class="row bg-master-light m-t-15 m-b-15 rounded padding-30">
|
||||
<div class="col">
|
||||
<h3>
|
||||
<span class="bold d-inline-block m-r-15">ORDER Marking: </span>
|
||||
<a :href="route('booking.details', externalApiResponse.data.booking_marking)"
|
||||
target="_blank">{{ externalApiResponse.data.booking_marking }}</a>
|
||||
</h3>
|
||||
<h3>
|
||||
<span class="bold d-inline-block m-r-15">1688 LOGIN ID/EMAIL/PHONE: </span>
|
||||
{{ externalApiResponse.data.account_no }}
|
||||
</h3>
|
||||
<h3>
|
||||
<span class="bold d-inline-block m-r-15">1688 LOGIN PASSWORD: </span>
|
||||
{{ externalApiResponse.data.holder_name }}
|
||||
</h3>
|
||||
<h3>
|
||||
<span class="bold d-inline-block m-r-15">ALIPAY 6-DIGIT PAYMENT PIN: </span>
|
||||
{{ externalApiResponse.data.pin }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="row bg-danger-light m-t-15 m-b-15 rounded padding-30">
|
||||
<div class="col">
|
||||
<h1 class="text-white">Api Failed. Please contact Tech Support</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="currentQuestionId === 'approve_po'">
|
||||
<div v-if="externalApiResponse.data" class="row">
|
||||
<div class="col">
|
||||
<h3>
|
||||
<span class="bold d-inline-block m-r-15">ORDER Marking: </span>
|
||||
<a :href="route('booking.details', externalApiResponse.data.marking)"
|
||||
target="_blank">{{ externalApiResponse.data.marking }}</a>
|
||||
</h3>
|
||||
<div class="row b-a b-primary padding-30 bg-white m-t-25">
|
||||
<div class="col">
|
||||
<purchase-order-form-component :data="externalApiResponse.data"
|
||||
:section="section"></purchase-order-form-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="row bg-danger-light m-t-15 m-b-15 rounded padding-30">
|
||||
<div class="col">
|
||||
<h1 class="text-white">Api Failed. Please contact Tech Support</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="currentQuestionId === 'fill_po'">
|
||||
<div v-if="externalApiResponse.data" class="row">
|
||||
<div class="col">
|
||||
<h3>
|
||||
<span class="bold d-inline-block m-r-15">ORDER Marking: </span>
|
||||
<a :href="route('booking.details', externalApiResponse.data.marking)"
|
||||
target="_blank">{{ externalApiResponse.data.marking }}</a>
|
||||
</h3>
|
||||
<div class="row b-a b-primary padding-30 bg-white m-t-25">
|
||||
<div class="col">
|
||||
<purchase-order-form-component :data="externalApiResponse.data"
|
||||
section="section"></purchase-order-form-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="row bg-danger-light m-t-15 m-b-15 rounded padding-30">
|
||||
<div class="col">
|
||||
<h1 class="text-white">Api Failed. Please contact Tech Support</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" v-if="currentQuestion.answers">
|
||||
<div class="col">
|
||||
<div class="w-100 d-block text-center">
|
||||
<button v-for="(answer, index) in currentQuestion.answers" :key="index"
|
||||
@click="selectAnswer(answer.next)"
|
||||
class="btn btn-lg btn-primary d-inline-block rounded fs-20"
|
||||
style="margin: 15px; padding: 15px 40px; min-width: 210px;">
|
||||
{{ answer.text }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="row bg-danger-light m-t-15 m-b-15 rounded padding-30">
|
||||
<div class="col">
|
||||
<h1 class="text-white">"{{ currentQuestionId }}" is empty. Please contact Tech Support
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-lg btn-primary d-inline-block rounded fs-20"
|
||||
style="margin: 15px; padding: 15px 40px; min-width: 210px;"
|
||||
@click="selectAnswer('refresh_page')">Refresh Page</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<h1>Come back when you are ready to work</h1>
|
||||
<button onClick="window.location.reload();" class="btn btn-primary">Refresh Page</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -123,243 +122,234 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'QuizApp',
|
||||
data() {
|
||||
return {
|
||||
section: 'initial_section',
|
||||
questions: {
|
||||
1: {
|
||||
text: 'What will you work on?',
|
||||
answers: [
|
||||
{ text: '1688', next: '1688' },
|
||||
{ text: 'Approve PO', next: 'approve_po' },
|
||||
{ text: 'Fill PO', next: 'fill_po' }
|
||||
]
|
||||
},
|
||||
'1688': {},
|
||||
'issue_login': {
|
||||
text: 'Login Issues',
|
||||
answers: [
|
||||
{ text: 'Need TAC', next: 'issue_submit'},
|
||||
{ text: 'Wrong login details', next: 'issue_submit'},
|
||||
{ text: 'Others', next: 'po_others'},
|
||||
{ text: 'Order Cancelled', next: 'refund_request'},
|
||||
"0": {
|
||||
"text": "Are you ready to work today?",
|
||||
"answers": [
|
||||
{ "text": "Yes", "next": "start_work" },
|
||||
{ "text": "No", "next": "no_work" }
|
||||
]
|
||||
},
|
||||
'login_successful': {},
|
||||
'issue_order': {
|
||||
answers: [
|
||||
{ text: 'Amount not found', next: 'issue_submit'},
|
||||
{ text: 'Plus Member', next: 'issue_submit'},
|
||||
{ text: 'Others', next: 'po_others'},
|
||||
{ text: 'Customer Did not verify 1688 account', next: 'issue_submit'},
|
||||
{ text: 'WorldFirst account linked another account', next: 'issue_submit'},
|
||||
{ text: 'Back', next: 'login_successful'},
|
||||
"start_work": {
|
||||
"text": "What will you work on?",
|
||||
"answers": [
|
||||
{ "text": "1688", "next": "1688" },
|
||||
{ "text": "Approve PO", "next": "approve_po" },
|
||||
{ "text": "Fill PO", "next": "fill_po" }
|
||||
]
|
||||
},
|
||||
'order_verify': {},
|
||||
'order_verification': {
|
||||
text: 'Are You Sure this is the correct amount?',
|
||||
answers: [
|
||||
{text: 'Yes', next: 'proceed_order'},
|
||||
{text: 'No', next: 'insufficient_order'}
|
||||
"no_work": {
|
||||
"text": "Come back when you are ready to work",
|
||||
"answers": [
|
||||
{ "text": "Refresh Page", "next": "refresh_page" }
|
||||
]
|
||||
},
|
||||
'proceed_order': {
|
||||
text: 'Please proceed the order on 1688',
|
||||
answers: [
|
||||
{text: 'Got Issue', next: '1688_order_issue'},
|
||||
{text: 'Done', next: '1688_submit'}
|
||||
"1688": {
|
||||
"load_api": this.route("api.admin_work_flow.fetch_oldest_order"),
|
||||
"answers": [
|
||||
{ "text": "Login Issue", "next": "login_issue" },
|
||||
{ "text": "Login Successful", "next": "login_successful" }
|
||||
]
|
||||
},
|
||||
'1688_order_issue': {
|
||||
answers: [
|
||||
{text: 'Wrong Pin Number', next: '1688_issue_submit'},
|
||||
{text: 'Not Enough Stock', next: '1688_issue_submit'},
|
||||
{text: 'Others', next: '1688_others'},
|
||||
{text: 'No CrossBoarder', next: '1688_issue_submit'},
|
||||
{text: 'AngPau', next: '1688_issue_submit'}
|
||||
"login_issue": {
|
||||
"text": "Login Issues",
|
||||
"answers": [
|
||||
{ "text": "Need TAC", "next": "issue_submit" },
|
||||
{ "text": "Wrong login details", "next": "issue_submit" },
|
||||
{ "text": "Others", "next": "po_others" },
|
||||
{ "text": "Order Cancelled", "next": "refund_request" }
|
||||
]
|
||||
},
|
||||
'1688_others': {},
|
||||
'1688_submit': {},
|
||||
'1688_issue_submit': {
|
||||
text: 'Issue has been submitted',
|
||||
answers: [
|
||||
{ text: 'Stop Working', next: 'stop_working'},
|
||||
{ text: 'Next Order', next: '1688'}
|
||||
"login_successful": {},
|
||||
"issue_order": {
|
||||
"answers": [
|
||||
{ "text": "Amount not found", "next": "issue_submit" },
|
||||
{ "text": "Plus Member", "next": "issue_submit" },
|
||||
{ "text": "Others", "next": "po_others" },
|
||||
{ "text": "Customer Did not verify 1688 account", "next": "issue_submit" },
|
||||
{ "text": "WorldFirst account linked another account", "next": "issue_submit" },
|
||||
{ "text": "Back", "next": "login_successful" }
|
||||
]
|
||||
},
|
||||
'refund_request': {
|
||||
text: 'Refund Request sent',
|
||||
answers: [
|
||||
{ text: 'Stop Working', next: 'stop_working' },
|
||||
{ text: 'Next PO', next: 'approve_po' }
|
||||
"order_verify": {},
|
||||
"order_verification": {
|
||||
"text": "Are You Sure this is the correct amount?",
|
||||
"answers": [
|
||||
{ "text": "Yes", "next": "proceed_order" },
|
||||
{ "text": "No", "next": "insufficient_order" }
|
||||
]
|
||||
},
|
||||
'approve_po': {},
|
||||
'fill_po': {},
|
||||
'po_filled': {
|
||||
text: 'PO Filled',
|
||||
answers: [
|
||||
{ text: 'Stop Working', next: 'stop_working' },
|
||||
{ text: 'Next PO', next: 'approve_po' }
|
||||
"proceed_order": {
|
||||
"text": "Please proceed the order on 1688",
|
||||
"answers": [
|
||||
{ "text": "Got Issue", "next": "1688_order_issue" },
|
||||
{ "text": "Done", "next": "1688_submit" }
|
||||
]
|
||||
},
|
||||
'submit_po' : {},
|
||||
'po_approved': {
|
||||
text: 'PO Approved',
|
||||
answers: [
|
||||
{ text: 'Stop Working', next: 'stop_working' },
|
||||
{ text: 'Next PO', next: 'approve_po' }
|
||||
"1688_order_issue": {
|
||||
"answers": [
|
||||
{ "text": "Wrong Pin Number", "next": "1688_issue_submit" },
|
||||
{ "text": "Not Enough Stock", "next": "1688_issue_submit" },
|
||||
{ "text": "Others", "next": "1688_others" },
|
||||
{ "text": "No CrossBoarder", "next": "1688_issue_submit" },
|
||||
{ "text": "AngPau", "next": "1688_issue_submit" }
|
||||
]
|
||||
},
|
||||
'edit_po': {},
|
||||
'po_others': {},
|
||||
'reject_po': {
|
||||
text: 'PO Rejected',
|
||||
answers: [
|
||||
{ text: 'Issue', next: 'issue_po' },
|
||||
{ text: 'Back', next: 'approve_po' }
|
||||
"1688_others": {},
|
||||
"1688_submit": {},
|
||||
"1688_issue_submit": {
|
||||
"text": "Issue has been submitted",
|
||||
"answers": [
|
||||
{ "text": "Stop Working", "next": "stop_working" },
|
||||
{ "text": "Next Order", "next": "1688" }
|
||||
]
|
||||
},
|
||||
'issue_po': {
|
||||
answers: [
|
||||
{ text: 'Sensitive Goods', next: 'issue_submit'},
|
||||
{ text: 'Others', next: 'po_others'},
|
||||
{ text: 'Stop Working', next: 'stop_working'},
|
||||
{ text: 'Next PO', next: 'approve_po'}
|
||||
"refund_request": {
|
||||
"text": "Refund Request sent",
|
||||
"answers": [
|
||||
{ "text": "Stop Working", "next": "stop_working" },
|
||||
{ "text": "Next PO", "next": "approve_po" }
|
||||
]
|
||||
},
|
||||
'issue_submit': {
|
||||
text: 'Issue has been submitted',
|
||||
answers: [
|
||||
{ text: 'Stop Working', next: 'stop_working'},
|
||||
{ text: 'Next Order', next: 'approve_po'}
|
||||
"approve_po": {
|
||||
// "text": "Order Number",
|
||||
"load_api": this.route("api.admin_work_flow.fetch_pending_approve_po"),
|
||||
"answers": [
|
||||
{ "text": "Approve", "next": "po_approved" },
|
||||
{ "text": "Edit PO", "next": "edit_po" },
|
||||
{ "text": "Reject", "next": "reject_po" }
|
||||
]
|
||||
},
|
||||
'1688_issue_submitted': {
|
||||
text: 'Issue has been submitted',
|
||||
answers: [
|
||||
{ text: 'Stop Working', next: 'stop_working'},
|
||||
{ text: 'Next Order', next: '1688'}
|
||||
"fill_po": {
|
||||
// "text": "Order Number",
|
||||
"load_api": this.route("api.admin_work_flow.fetch_pending_fill_po"),
|
||||
"answers": [
|
||||
{ "text": "Approve", "next": "po_approved" },
|
||||
{ "text": "Edit PO", "next": "edit_po" },
|
||||
{ "text": "Reject", "next": "reject_po" }
|
||||
]
|
||||
},
|
||||
'stop_working': {
|
||||
text: 'Thank you for your work!',
|
||||
"po_filled": {
|
||||
"text": "PO Filled",
|
||||
"answers": [
|
||||
{ "text": "Stop Working", "next": "stop_working" },
|
||||
{ "text": "Next PO", "next": "approve_po" }
|
||||
]
|
||||
},
|
||||
"submit_po": {},
|
||||
"po_approved": {
|
||||
"text": "PO Approved",
|
||||
"answers": [
|
||||
{ "text": "Stop Working", "next": "stop_working" },
|
||||
{ "text": "Next PO", "next": "approve_po" }
|
||||
]
|
||||
},
|
||||
"edit_po": {},
|
||||
"po_others": {},
|
||||
"reject_po": {
|
||||
"text": "PO Rejected",
|
||||
"answers": [
|
||||
{ "text": "Issue", "next": "issue_po" },
|
||||
{ "text": "Back", "next": "approve_po" }
|
||||
]
|
||||
},
|
||||
"issue_po": {
|
||||
"answers": [
|
||||
{ "text": "Sensitive Goods", "next": "issue_submit" },
|
||||
{ "text": "Others", "next": "po_others" },
|
||||
{ "text": "Stop Working", "next": "stop_working" },
|
||||
{ "text": "Next PO", "next": "approve_po" }
|
||||
]
|
||||
},
|
||||
"issue_submit": {
|
||||
"text": "Issue has been submitted",
|
||||
"answers": [
|
||||
{ "text": "Stop Working", "next": "stop_working" },
|
||||
{ "text": "Next Order", "next": "approve_po" }
|
||||
]
|
||||
},
|
||||
"1688_issue_submitted": {
|
||||
"text": "Issue has been submitted",
|
||||
"answers": [
|
||||
{ "text": "Stop Working", "next": "stop_working" },
|
||||
{ "text": "Next Order", "next": "1688" }
|
||||
]
|
||||
},
|
||||
"stop_working": {
|
||||
"text": "Thank you for your work!",
|
||||
"answers": [
|
||||
{ "text": "Refresh Page", "next": "refresh_page" }
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
currentQuestionId: null,
|
||||
readyToWork: true,
|
||||
orderNumbers: ['Order 123', 'Order 456', 'Order 789']
|
||||
isLoading: false,
|
||||
externalApiResponse: { data: null },
|
||||
timer: null,
|
||||
elapsedTime: 0,
|
||||
interval: 1000,
|
||||
sessionId: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
currentQuestion() {
|
||||
return this.questions[this.currentQuestionId];
|
||||
currentQuestion() { return this.questions[this.currentQuestionId] || {}; },
|
||||
formattedTime() {
|
||||
const hours = String(Math.floor(this.elapsedTime / 3600)).padStart(2, '0');
|
||||
const minutes = String(Math.floor((this.elapsedTime % 3600) / 60)).padStart(2, '0');
|
||||
const seconds = String(this.elapsedTime % 60).padStart(2, '0');
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.currentQuestionId = 0;
|
||||
if (this.sessionId == null) {
|
||||
this.sessionId = this.generateSessionId();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
startQuiz() {
|
||||
this.currentQuestionId = 1;
|
||||
},
|
||||
startTimer() { this.timer = setInterval(() => this.elapsedTime++, this.interval); },
|
||||
stopTimer() { clearInterval(this.timer); this.timer = null; },
|
||||
startWork() { this.startTimer(); console.log("work is started"); },
|
||||
endWork() { this.stopTimer(); console.log("work is ended"); },
|
||||
selectAnswer(nextQuestionId) {
|
||||
if (nextQuestionId === 'refresh_page') return window.location.reload();
|
||||
if (!Object.keys(this.questions[nextQuestionId]).length) this.endWork();
|
||||
if (nextQuestionId === 'start_work') this.startWork();
|
||||
if (nextQuestionId === 'stop_work') this.stopTimer();
|
||||
this.currentQuestionId = nextQuestionId;
|
||||
},
|
||||
selectOrder(order, action) {
|
||||
if (action === 'approve') {
|
||||
this.currentQuestionId = 'po_approved';
|
||||
} else if (action === 'edit') {
|
||||
this.currentQuestionId = 'edit_po';
|
||||
} else if (action === 'reject') {
|
||||
this.currentQuestionId = 'reject_po';
|
||||
} else if (action == 'issue_login') {
|
||||
this.currentQuestionId = 'issue_login'
|
||||
} else if (action == 'dummy_login') {
|
||||
this.currentQuestionId = 'login_successful'
|
||||
} else if (action == 'error_order') {
|
||||
this.currentQuestionId = 'issue_order'
|
||||
} else if (action == 'verify_order') {
|
||||
this.currentQuestionId = 'order_verify'
|
||||
} else if (action == 'back_order') {
|
||||
this.currentQuestionId = 'login_successful'
|
||||
} else if (action == 'yes_order') {
|
||||
this.currentQuestionId = 'order_verification'
|
||||
}
|
||||
},
|
||||
addOrder() {
|
||||
this.orderNumbers.push('');
|
||||
},
|
||||
saveOrders() {
|
||||
alert('Orders have been saved: ' + this.orderNumbers.join(', '));
|
||||
this.currentQuestionId = 'po_filled';
|
||||
},
|
||||
nextorder() {
|
||||
this.currentQuestionId = '1688';
|
||||
},
|
||||
issueOthers(){
|
||||
this.currentQuestionId = 'issue_po';
|
||||
},
|
||||
issue1688() {
|
||||
this.currentQuestionId = '1688_order_issue';
|
||||
},
|
||||
submit_issue() {
|
||||
this.currentQuestionId = '1688_issue_submitted';
|
||||
},
|
||||
submit() {
|
||||
|
||||
}
|
||||
// call api to recorrd timestamp
|
||||
var logBody = {
|
||||
'node': nextQuestionId,
|
||||
'seconds': this.elapsedTime,
|
||||
'userId': this.$store.getters.getUserId,
|
||||
'session_id': this.sessionId,
|
||||
};
|
||||
this.callApi(this.route('api.admin_work_flow.add_workflow_timestamp'), 'post', 'section', logBody, false, false);
|
||||
|
||||
if (this.questions[nextQuestionId]?.load_api) this.callApi(this.questions[nextQuestionId].load_api, 'get', 'section');
|
||||
},
|
||||
generateSessionId() {
|
||||
return 'xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
},
|
||||
callApi(url, method, section, parameters = null, showLoadingAnimation = true, storeResponseBody = true) {
|
||||
if (showLoadingAnimation) this.isLoading = true;
|
||||
this.$store.dispatch('crudRequest', { endpoint: url, method, parameters: parameters }).then(response =>
|
||||
response.json().then(data => ({ data, ok: response.ok, status: response.status }))
|
||||
).then(apiResponse => {
|
||||
if (storeResponseBody) this.externalApiResponse.data = apiResponse.data;
|
||||
if (apiResponse.ok) this.successHandler(apiResponse.data);
|
||||
else this.errorHandler(apiResponse.data, apiResponse.status);
|
||||
if (showLoadingAnimation) this.isLoading = false;
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.box {
|
||||
border: 1px solid #ddd;
|
||||
padding: 20px;
|
||||
margin-top: 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.order {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.image-upload {
|
||||
width: 80%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.text-box {
|
||||
width: 80%;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin: 5px;
|
||||
font-size: 18px; /* Adjust the font size */
|
||||
padding: 12px 24px; /* Adjust the padding */
|
||||
border-radius: 4px; /* Optional: adjust border radius */
|
||||
}
|
||||
|
||||
.answer-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.answer-item {
|
||||
margin: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
use App\Classes\Exceptions\RequestValidationException;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use App\Http\Resources\BookingResource;
|
||||
use App\Models\Booking;
|
||||
use App\Models\WorkflowTimestamp;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
Route::group(['prefix' => 'admin-work-flow', 'as' => 'admin_work_flow.', 'namespace' => 'AdminWorkFlow'], function () {
|
||||
|
||||
Route::get('/fetch-oldest-order', function () {
|
||||
// currenly, using service id to hardcode fetch
|
||||
// todo-new: pls confirm need to include 1688 vip orders
|
||||
$booking = Booking::where('service_id', 4)
|
||||
->where('status', ApprovalStatus::APPROVED)
|
||||
// ->latest()
|
||||
->first();
|
||||
|
||||
if (!$booking) return response()->json(['error' => 'No booking found'], 404);
|
||||
|
||||
$bank = $booking->bank;
|
||||
|
||||
return response()->json([
|
||||
'passwords' => $bank->holder_name ?? null,
|
||||
'account_no' => $bank->account_no ?? null,
|
||||
'pin' => $bank->bank_branch ?? null,
|
||||
'holder_name' => $bank->holder_name ?? null,
|
||||
'booking_marking' => $booking->marking ?? null,
|
||||
]);
|
||||
})->name('fetch_oldest_order');
|
||||
|
||||
|
||||
|
||||
Route::post('/add-workflow-timestamp', function (Request $request) {
|
||||
$validator = Validator::make($request->all(), [
|
||||
'node' => 'required|string',
|
||||
'seconds' => 'required|integer',
|
||||
'userId' => 'required|integer|exists:users,id',
|
||||
'session_id' => 'required|string',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) throw new RequestValidationException($validator->messages()->first());
|
||||
|
||||
$workflowTimestamp = WorkflowTimestamp::create($request->only('node', 'seconds', 'userId', 'session_id'));
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Workflow timestamp created successfully',
|
||||
'data' => $workflowTimestamp
|
||||
], 201);
|
||||
})->name('add_workflow_timestamp');
|
||||
|
||||
|
||||
|
||||
Route::get('/fetch-pending-approved-po', function () {
|
||||
// currenly, using service id to hardcode fetch
|
||||
// todo-new: pls confirm need to include 1688 vip orders
|
||||
$booking = Booking::with('transactions')
|
||||
->where('service_id', 4)
|
||||
->where('status', ApprovalStatus::APPROVED)
|
||||
->whereHas('transactions', fn ($query) => $query->where('type', TransactionType::PURCHASE_ORDER)->where('status', '<', ApprovalStatus::APPROVED))
|
||||
// ->latest()
|
||||
->first();
|
||||
|
||||
if (!$booking) return response()->json(['error' => 'No booking found'], 404);
|
||||
|
||||
return response()->json(new BookingResource($booking));
|
||||
})->name('fetch_pending_approve_po');
|
||||
|
||||
|
||||
|
||||
Route::get('/fetch-pending-fill-po', function () {
|
||||
// currenly, using service id to hardcode fetch
|
||||
// todo-new: pls confirm need to include 1688 vip orders
|
||||
$booking = Booking::with('transactions')
|
||||
->where('service_id', 4)
|
||||
->where('status', ApprovalStatus::APPROVED)
|
||||
->whereDoesntHave('transactions', fn ($query) => $query->where('type', TransactionType::PURCHASE_ORDER))
|
||||
// ->latest()
|
||||
->first();
|
||||
|
||||
if (!$booking) return response()->json(['error' => 'No booking found'], 404);
|
||||
|
||||
return response()->json(new BookingResource($booking));
|
||||
})->name('fetch_pending_fill_po');
|
||||
|
||||
});
|
||||
@@ -76,5 +76,7 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function
|
||||
// require __DIR__ . '/rate.php';
|
||||
// require __DIR__ . '/receipt.php';
|
||||
|
||||
require __DIR__ . '/admin_work_flow.php';
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user