From b37ece7d83a28359b4450910bdc9940ff6482106 Mon Sep 17 00:00:00 2001 From: Immanuel Onyeka <immanuel@onyeka.ca> Date: Wed, 2 Jun 2021 10:16:31 -0400 Subject: [PATCH] Add transaction page transitioning --- .../Controllers/TransactionController.php | 9 ++ .../2014_10_12_000000_create_users_table.php | 2 +- resources/js/panel/credits.vue | 3 + resources/js/panel/orders.vue | 2 +- resources/js/panel/panel.vue | 7 +- resources/js/panel/services.vue | 100 +++++++++++++----- resources/js/panel/sidebar.vue | 2 +- resources/scss/main.scss | 11 +- 8 files changed, 100 insertions(+), 36 deletions(-) create mode 100644 resources/js/panel/credits.vue diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 582e790..c66f950 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -12,13 +12,22 @@ class TransactionController extends Controller { //THis should also reduce user's available credits public function newOrder(Request $request) { + $user = Auth::user(); $order = new Order; + $order->service_id = $request->service; $order->user_id = Auth::user()->id; $order->quantity = $request->quantity; $order->url = $request->url; $order->note = $request->note ?: ''; $order->status = 'processing'; + + $cost = ceil($order->quantity*$order->service->price/1000); + $user->credits = $user->credits - $cost; + if ($cost > $user->credits) { + abort(520, 'Insufficient Credits'); + } + $user->save(); $order->save(); } } diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 045d00e..a234e76 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -21,7 +21,7 @@ class CreateUsersTable extends Migration $table->string('password'); $table->string('role'); $table->boolean('active')->default(true); - $table->bigInteger('credits')->default(0); + $table->unsignedBigInteger('credits')->default(0); $table->rememberToken(); $table->timestamps(); }); diff --git a/resources/js/panel/credits.vue b/resources/js/panel/credits.vue new file mode 100644 index 0000000..9ffb918 --- /dev/null +++ b/resources/js/panel/credits.vue @@ -0,0 +1,3 @@ +<template> +hello +</template> diff --git a/resources/js/panel/orders.vue b/resources/js/panel/orders.vue index f5ca992..a0f19b4 100644 --- a/resources/js/panel/orders.vue +++ b/resources/js/panel/orders.vue @@ -1,7 +1,7 @@ <template> <div> <section class="pending-pane"> - <div class="actions"><a class="new-order" href="#orders/new-order">New</a><a class="new-order" href="#orders/new">Add credits</a></div> + <div class="actions"><a class="new-order" href="#new-order">New</a><a class="new-order" href="#credits">Add credits</a></div> <h4>Pending Orders</h4> <ul> <template v-bind:key='order.id' v-for="order in orders"> diff --git a/resources/js/panel/panel.vue b/resources/js/panel/panel.vue index d5aca62..e245103 100644 --- a/resources/js/panel/panel.vue +++ b/resources/js/panel/panel.vue @@ -28,8 +28,8 @@ </div> <PastOrders :orders="orders" v-else-if="active === '#orders'" id="main"> </PastOrders> -<NewOrder :token="token" :credits="user.credits" v-else-if="active === -'#new-order'" id="main" @updateUser='getUser'> +<NewOrder :token="token" :active="active" :credits="user.credits" v-else-if="active === +'#new-order' || active === '#credits'" id="main" @update-user='getUser' @update-orders='getOrders'> </NewOrder> <div id="main" v-else-if="active === '#exit'"> <section class="logout-pane"> @@ -48,9 +48,6 @@ import Settings from './settings.vue' import PastOrders from './orders.vue' import NewOrder from './services.vue' -/* function getServices() { */ - -/* } */ function getServices() { return fetch("/panel/services", { method: 'GET', diff --git a/resources/js/panel/services.vue b/resources/js/panel/services.vue index 18e4225..7bafb8b 100644 --- a/resources/js/panel/services.vue +++ b/resources/js/panel/services.vue @@ -1,28 +1,44 @@ <template> <div> <div class="services-menu"> - <button class="selected">Services</button> - <button>Credits</button> - <div class="menu-slider"><div></div></div> + <a href="#new-order" :class="{selected: page == 'new-order'}">Services</a> + <a href="#credits" :class="{selected: page == 'credits'}">Credits</a> + <div :class="page" class="menu-slider"><div></div></div> </div> - <h4 class="credits-display">Credits: {{credits}}</h4> - <div class="services-legend"><h5>Name</h5> -<h5>Credits per 1000</h5><h5>Min Qt.</h5><h5>Max Qt.</h5></div> -<ServicePane :site="'youtube'" :services="services" @select="select"></ServicePane> -<ServicePane :site="'instagram'" :services="services" @select="select"></ServicePane> -<ServicePane :site="'twitter'" :services="services" @select="select"></ServicePane> -<ServicePane :site="'tiktok'" :services="services" @select="select"></ServicePane> -<div id="overlay" v-if="selected"> + <h4 class="credits-display">Credits: {{credits.toLocaleString('en')}}</h4> + + <template v-if="page == 'new-order'"> + + <div class="services-legend"> + <h5>Name</h5><h5>Credits per 1000</h5><h5>Min Qt.</h5><h5>Max Qt.</h5> + </div> + + <ServicePane :site="'youtube'" :services="services" + @select="select"></ServicePane> <ServicePane :site="'instagram'" + :services="services" @select="select"></ServicePane> <ServicePane + :site="'twitter'" :services="services" @select="select"></ServicePane> + <ServicePane :site="'tiktok'" :services="services" + @select="select"></ServicePane> + + <div id="overlay" v-if="selected"> + <div v-if="!completed" class="overlay-item"> - <img @click="completed = false; selected = null" class="cancel icon" src="../../images/cancel-icon2.svg" alt=""/> - <img v-if="selected.site == 'youtube'" class="icon" src="../../images/youtube-icon.svg" alt=""> - <img v-if="selected.site == 'instagram'" class="icon" src="../../images/instagram-icon.svg" alt=""> - <img v-if="selected.site == 'twitter'" class="icon" src="../../images/twitter.svg" alt=""> - <img v-if="selected.site == 'tiktok'" class="icon" src="../../images/tik-tok.svg" alt=""> + <img @click="completed = false; selected = null" class="cancel icon" + src="../../images/cancel-icon2.svg" alt=""/> + <img v-if="selected.site == 'youtube'" class="icon" + src="../../images/youtube-icon.svg" alt=""/> + <img v-if="selected.site == 'instagram'" class="icon" + src="../../images/instagram-icon.svg" alt=""/> + <img v-if="selected.site == 'twitter'" class="icon" + src="../../images/twitter.svg" alt=""/> + <img v-if="selected.site == 'tiktok'" class="icon" + src="../../images/tik-tok.svg" alt=""/> <h3>{{selected.name}}</h3> <h4>Cost: {{cost.toLocaleString('en')}}</h4> <h4>Quantity</h4> - <div><input required :min="selected.minimum" :max="selected.maximum" type="number" v-model="amount" id="selQty"><span> / {{selected.maximum.toLocaleString('en')}}</span></div> + <div><input required :min="selected.minimum" :max="selected.maximum" + type="number" v-model="amount" id="selQty"><span> / + {{selected.maximum.toLocaleString('en')}}</span></div> <template v-if="selected.modifier == 'location'"> <h4>Location</h4> <div><select required id="country" name=""> @@ -31,24 +47,36 @@ <option value="uk">United Kingdom</option> <option value="germany">Germany</option> <option value="france">France</option> - </select></div> + </select> + </div> </template> <h4>URL</h4> <div><input required type="url" id="url" v-model="url"></div> - <button @click="buyService" :disabled="paying">Submit<loading v-if="paying"></loading></button> + <button @click="buyService" :disabled="paying">Submit<loading + v-if="paying"></loading></button> <p id="overlay-error"></p> + </div> + <div class="overlay-item" v-else-if="completed"> - <img @click="completed = false; selected = null" class="cancel icon" src="../../images/cancel-icon2.svg" alt=""/> - <img class="icon" src="../../images/checked2.svg" alt=""> + <img @click="completed = false; selected = null" class="cancel icon" + src="../../images/cancel-icon2.svg" alt=""/> + <img class="icon" src="../../images/checked2.svg" alt=""/> <h3>Success!</h3> </div> -</div> + + </div> + + </template> + + <credits v-if="page == 'credits'"></credits> + </div> </template> <script> import ServicePane from './service-pane.vue' +import Credits from './credits.vue' import Loading from '../icons/loading.vue' function select(service) { @@ -64,7 +92,12 @@ function buyService() { if (!this.url) { document.getElementById('overlay-error').textContent = "You must provide a URL." return + } else if (Math.ceil(this.cost > this.credits)) { + document.getElementById('overlay-error').textContent = + 'Insuficient Credits' + return } + this.paying = true let note = '' let country = document.getElementById('country') @@ -85,23 +118,38 @@ function buyService() { document.getElementById('overlay-error').textContent = `Success!` this.completed = true this.$emit('updateUser') + this.$emit('updateOrders') + } else if (response.status == 520) { + document.getElementById('overlay-error').textContent = + 'Insuficient Credits' } else { document.getElementById('overlay-error').textContent = `Error ${response.status}: ${response.statusText}` } + this.paying = false } ) } +function page() { + switch (this.active) { + case '#new-order': + return 'new-order' + case '#credits': + return 'credits' + } + console.log(this.active) +} + export default { data() { return {servicePane: true, services: null, selected: null, amount: 0, paying: false, url: '', completed: false} }, - components: {ServicePane, Loading}, - props: ['token', 'credits'], + components: {ServicePane, Loading, Credits}, + props: ['token', 'credits', 'active'], created() { fetch("/panel/services", { method: 'GET', @@ -113,7 +161,7 @@ export default { }) }, methods: {select, buyService}, - computed: {cost}, - emits: ['updateUser'] + computed: {cost, page}, + emits: ['updateUser', 'updateOrders'] } </script> diff --git a/resources/js/panel/sidebar.vue b/resources/js/panel/sidebar.vue index 946e7e2..850537f 100644 --- a/resources/js/panel/sidebar.vue +++ b/resources/js/panel/sidebar.vue @@ -8,7 +8,7 @@ <a :class="{selected: active == '#orders'}" href="/panel#orders"> <svg fill="currentColor" enable-background="new 0 0 24 24" height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m16.12 1.929-10.891 5.576-4.329-2.13 10.699-5.283c.24-.122.528-.122.78 0z"/><path d="m23.088 5.375-11.082 5.49-4.15-2.045-.6-.305 10.903-5.575.6.304z"/><path d="m11.118 12.447-.012 11.553-10.614-5.539c-.3-.158-.492-.475-.492-.816v-10.688l4.498 2.216v3.896c0 .499.408.913.9.913s.9-.414.9-.913v-2.995l.6.292z"/><path d="m23.988 6.969-11.07 5.466-.012 11.553 11.094-5.793z"/></svg> </a> -<a :class="{selected: active == '#new-order'}" href="/panel#new-order"> +<a :class="{selected: active == '#new-order' || active == '#credits'}" href="/panel#new-order"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M12,2C6.486,2,2,6.486,2,12s4.486,10,10,10c5.514,0,10-4.486,10-10S17.514,2,12,2z M17,13h-4v4h-2v-4H7v-2h4V7h2v4h4V13z"></path></svg> </a> <a :class="{selected: active == '#settings'}" href="/panel#settings"> diff --git a/resources/scss/main.scss b/resources/scss/main.scss index 322e844..b8277bd 100644 --- a/resources/scss/main.scss +++ b/resources/scss/main.scss @@ -1003,12 +1003,13 @@ main.panel { margin-top: 1em; flex-flow: wrap; gap: 10px; - button { + a { width: 25%; font-size: 1.1rem; background: none; border: none; color: grey; + text-align: center; } .selected { color: black; @@ -1018,12 +1019,18 @@ main.panel { .menu-slider { width: 55%; div { - // margin-left: auto; + transition: all 0.2s; width: 50%; border-bottom: 2px solid black; + flex: 2; } } +.menu-slider.credits div { + // margin-left: auto; + transform: translateX(100%); +} + .services-pane { li { display: flex;