@@ -1,10 +0,0 @@ | |||
<?php | |||
namespace App\Http\Controllers; | |||
use Illuminate\Http\Request; | |||
class Transaction extends Controller | |||
{ | |||
// | |||
} |
@@ -0,0 +1,24 @@ | |||
<?php | |||
namespace App\Http\Controllers; | |||
use Illuminate\Http\Request; | |||
use App\Models\Order; | |||
use App\Models\Service; | |||
use Illuminate\Support\Facades\Auth; | |||
use Illuminate\Support\Facades\Log; | |||
class TransactionController extends Controller | |||
{ | |||
//THis should also reduce user's available credits | |||
public function newOrder(Request $request) { | |||
$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'; | |||
$order->save(); | |||
} | |||
} |
@@ -87,7 +87,7 @@ class UserController extends Controller | |||
public function getOrders(Request $request) { | |||
/* Log::debug(Auth::user()->orders()->service_name); */ | |||
return Auth::user()->orders()->with('service')->withCasts(['updated_at' | |||
=> 'datetime:d-m-Y'])->get(); | |||
=> 'datetime:d-m-Y'])->latest()->get(); | |||
} | |||
public function changeName(Request $request) { | |||
@@ -20,6 +20,8 @@ class CreateServicesTable extends Migration | |||
$table->string('name'); | |||
$table->string('type')->nullable(); | |||
$table->string('site'); | |||
$table->string('supplier')->nullable(); | |||
$table->string('supplier_link')->nullable(); | |||
$table->string('modifier')->default(''); | |||
$table->integer('maximum'); | |||
$table->integer('minimum'); | |||
@@ -28,7 +28,8 @@ | |||
</div> | |||
<PastOrders :orders="orders" v-else-if="active === '#orders'" id="main"> | |||
</PastOrders> | |||
<NewOrder :token="token" v-else-if="active === '#new-order'" id="main"> | |||
<NewOrder :token="token" :credits="user.credits" v-else-if="active === | |||
'#new-order'" id="main" @updateUser='updateUser'> | |||
</NewOrder> | |||
<div id="main" v-else-if="active === '#exit'"> | |||
<section class="logout-pane"> | |||
@@ -61,15 +62,28 @@ import NewOrder from './services.vue' | |||
/* }) */ | |||
/* } */ | |||
function updateUser() { | |||
fetch("/panel/user", { | |||
method: 'GET', | |||
headers: {'Content-Type': 'application/json', | |||
'Accept': 'application/json', | |||
'X-XSRF-TOKEN': this.token}, | |||
}).then(response => { | |||
return response.json() | |||
}).then(data => { | |||
this.user = data | |||
}) | |||
} | |||
export default { | |||
components: { | |||
Sidebar, Settings, PastOrders, NewOrder | |||
}, | |||
data() { | |||
return {active: window.location.hash, user: '', | |||
token: '', orders: '', loading: true} | |||
return {active: window.location.hash, user: null, | |||
token: null, orders: null, loading: true} | |||
}, | |||
methods: {}, | |||
methods: {updateUser}, | |||
created() { | |||
fetch("/panel/services", { | |||
method: 'GET', | |||
@@ -78,7 +92,15 @@ export default { | |||
'X-XSRF-TOKEN': this.token} | |||
}).then(response => { | |||
response.json().then(data => {this.services = data; this.loading = false}) | |||
}) | |||
}).then( | |||
fetch("/panel/services", { | |||
method: 'GET', | |||
headers: {'Content-Type': 'application/json', | |||
'Accept': 'application/json', | |||
'X-XSRF-TOKEN': this.token} | |||
}).then(response => { | |||
response.json().then(data => {this.services = data; this.loading = false}) | |||
})) | |||
} | |||
} | |||
</script> |
@@ -3,9 +3,9 @@ | |||
<div class="services-menu"> | |||
<button class="selected">Services</button> | |||
<button>Credits</button> | |||
<div class="menu-slider"> | |||
<div></div></div> | |||
<div 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> | |||
@@ -13,8 +13,8 @@ | |||
<ServicePane :site="'twitter'" :services="services" @select="select"></ServicePane> | |||
<ServicePane :site="'tiktok'" :services="services" @select="select"></ServicePane> | |||
<div id="overlay" v-if="selected"> | |||
<div class="overlay-item"> | |||
<img @click="selected = null" class="cancel icon" src="../../images/cancel-icon2.svg" alt=""/> | |||
<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=""> | |||
@@ -34,9 +34,14 @@ | |||
</select></div> | |||
</template> | |||
<h4>URL</h4> | |||
<div><input required type="url" id="url"></div> | |||
<div><input required type="url" id="url" v-model="url"></div> | |||
<button @click="buyService" :disabled="paying">Submit<loading v-if="paying"></loading></button> | |||
<p></p> | |||
<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=""> | |||
<h3>Success!</h3> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -47,6 +52,7 @@ import ServicePane from './service-pane.vue' | |||
import Loading from '../icons/loading.vue' | |||
function select(service) { | |||
this.completed = false | |||
this.selected = service | |||
} | |||
@@ -55,17 +61,47 @@ function cost() { | |||
} | |||
function buyService() { | |||
if (!this.url) { | |||
document.getElementById('overlay-error').textContent = "You must provide a URL." | |||
return | |||
} | |||
this.paying = true | |||
return | |||
let note = '' | |||
let country = document.getElementById('country') | |||
if (country) { | |||
note = JSON.stringify({'location': country.value}) | |||
} | |||
fetch('/panel/orders', { | |||
method: 'POST', | |||
headers: {'Content-Type': 'application/json', | |||
'Accept': 'application/json', | |||
'X-XSRF-TOKEN': this.token}, | |||
body: JSON.stringify({'service': this.selected.id, | |||
'quantity': this.amount, 'url': this.url, 'note': note}), }).then( | |||
response => { | |||
if (response.ok) { | |||
document.getElementById('overlay-error').textContent = `Success!` | |||
this.completed = true | |||
this.$emit('updateUser') | |||
} else { | |||
document.getElementById('overlay-error').textContent = `Error | |||
${response.status}: ${response.statusText}` | |||
} | |||
this.paying = false | |||
} | |||
) | |||
} | |||
export default { | |||
data() { | |||
return {servicePane: true, services: null, selected: null, amount: 0, | |||
paying: false } | |||
paying: false, url: '', completed: false} | |||
}, | |||
components: {ServicePane, Loading}, | |||
props: ['token'], | |||
props: ['token', 'credits'], | |||
created() { | |||
fetch("/panel/services", { | |||
method: 'GET', | |||
@@ -77,6 +113,7 @@ export default { | |||
}) | |||
}, | |||
methods: {select, buyService}, | |||
computed: {cost} | |||
computed: {cost}, | |||
emits: ['updateUser'] | |||
} | |||
</script> |
@@ -16,7 +16,7 @@ | |||
<section class="change-password-pane"> | |||
<h4>Change Password</h4> | |||
<h5>Current Password</h5><input name="current_passowrd" id="current_password" type="password"> | |||
<h5>New Password</h5><input id="new_password" name="passowrd" type="password"> | |||
<h5>New Password</h5><input id="new_password" name="password" type="password"> | |||
<h5>Confirm Password</h5><input id="confirm_password" name="confirm_passowrd" type="password"> | |||
<button @click="changePassword">Save<img class="loading-icon" src="../../images/loading-white.svg" alt=""></button> | |||
<span></span> | |||
@@ -1132,9 +1132,20 @@ main.panel { | |||
width: 100%; | |||
} | |||
p { | |||
margin-top: 2em; | |||
text-align: center; | |||
} | |||
} | |||
button .loading-icon { | |||
display: inline; | |||
height: 1.5em; | |||
} | |||
#panel #main .credits-display { | |||
text-align: center; | |||
margin: 1em; | |||
color: vars.getColor('brand-orange'); | |||
} |
@@ -3,6 +3,7 @@ | |||
use Illuminate\Support\Facades\Route; | |||
use App\Http\Controllers\UserController; | |||
use App\Http\Controllers\ServiceController; | |||
use App\Http\Controllers\TransactionController; | |||
use Illuminate\Foundation\Auth\EmailVerificationRequest; | |||
use Illuminate\Http\Request; | |||
use Illuminate\Support\Facades\Auth; | |||
@@ -81,3 +82,7 @@ Route::post('/panel/change-password', [UserController::class, | |||
Route::get('/reset-email', [UserController::class, | |||
'resetEmail'])->name('reset-email'); | |||
Route::post('/panel/orders', [TransactionController::class, | |||
'newOrder'])->middleware([ 'auth', 'verified' ]); | |||