From 3c24c0e9ef8819e5fb3a7695b99734f49bae574c Mon Sep 17 00:00:00 2001 From: twotalesanimation <80506065+twotalesanimation@users.noreply.github.com> Date: Tue, 30 Dec 2025 00:09:14 +0200 Subject: [PATCH] everything semi working before sample implementation --- .../Controllers/CustomOrderController.php | 186 ++++++-- app/Http/Controllers/OrderController.php | 130 ++++-- app/Models/CustomOrder.php | 3 + public/css/styles.css | 34 +- resources/views/account/orders.blade.php | 17 +- resources/views/account/profile.blade.php | 11 +- resources/views/cart.blade.php | 13 +- resources/views/checkout.blade.php | 8 +- resources/views/components/footer.blade.php | 14 +- .../views/components/product-card.blade.php | 2 +- .../views/custom-orders/create.blade.php | 23 +- .../custom-orders/deposit-success.blade.php | 170 ++++--- resources/views/custom-orders/index.blade.php | 8 +- resources/views/custom-orders/show.blade.php | 23 +- resources/views/fabrics.blade.php | 20 +- resources/views/home.blade.php | 10 +- resources/views/murals.blade.php | 6 +- resources/views/order-history.blade.php | 9 +- resources/views/order-success.blade.php | 96 ++-- resources/views/product-detail.blade.php | 7 +- routes/web.php | 6 +- .../04ff3b0976d6c97ed24bb748c5e23122.php | 93 ++-- .../0ff4c44d6c7a7dc85eddb6c22b81e0f3.php | 424 ------------------ .../34ae340ff479643953f86c68f04ac61d.php | 191 -------- .../3763665363475be06cdc81b77877ae07.php | 23 +- .../37e763d5cd6e76eadead6082618a94db.php | 257 ----------- .../3a2cb9666b458ecc4f2fa2c2fec9d575.php | 292 ------------ .../4497534d143181b9fee095928655445e.php | 10 +- .../54c3d5356cdbbbf74cb08435146375fb.php | 7 - .../58cd42abd6d7deaa5d6a18b0afc483d5.php | 146 ++++++ .../6867b742e394e8b9b24132c9e986866f.php | 6 +- .../68d9018dcef4a20a369db8971b25d5cf.php | 2 +- .../690e9b8d1239f81f482e37c384703b0e.php | 7 +- .../753f54a550301d9371c07d127500ea99.php | 358 +++++++++++++++ .../8026b478662a1d4e9373ace7d60461ae.php | 14 +- .../8dd2c79bd081de46821e5a4c16e0218a.php | 17 +- .../963a42c38bd8e0fdfe0b4e765ea9f100.php | 8 +- .../adc4c4a369b2bee1705d8da3a6247c45.php | 23 +- .../c17b66f9c0263ecd84fe1ebbcc3be042.php | 13 +- 39 files changed, 1072 insertions(+), 1615 deletions(-) delete mode 100644 storage/framework/views/0ff4c44d6c7a7dc85eddb6c22b81e0f3.php delete mode 100644 storage/framework/views/34ae340ff479643953f86c68f04ac61d.php delete mode 100644 storage/framework/views/37e763d5cd6e76eadead6082618a94db.php delete mode 100644 storage/framework/views/3a2cb9666b458ecc4f2fa2c2fec9d575.php delete mode 100644 storage/framework/views/54c3d5356cdbbbf74cb08435146375fb.php create mode 100644 storage/framework/views/58cd42abd6d7deaa5d6a18b0afc483d5.php create mode 100644 storage/framework/views/753f54a550301d9371c07d127500ea99.php diff --git a/app/Http/Controllers/CustomOrderController.php b/app/Http/Controllers/CustomOrderController.php index 3c01ef8..5b052a0 100644 --- a/app/Http/Controllers/CustomOrderController.php +++ b/app/Http/Controllers/CustomOrderController.php @@ -164,36 +164,58 @@ class CustomOrderController extends Controller */ public function depositPayment(Request $request) { + Log::info('Deposit payment initiated', [ + 'request_data' => $request->all(), + 'user_id' => auth()->id(), + ]); $validated = $request->validate([ 'custom_order_id' => 'required|exists:custom_orders,id', ]); + Log::info('Deposit payment validation passed', $validated); $customOrder = CustomOrder::findOrFail($validated['custom_order_id']); // Check authorization if ($customOrder->user_id !== auth()->id()) { + Log::warning('Unauthorized deposit payment attempt', [ + 'custom_order_id' => $customOrder->id, + 'user_id' => auth()->id(), + ]); abort(403); } // Check if already paid if ($customOrder->deposit_status === 'paid') { + Log::info('Deposit already paid for custom order', [ + 'custom_order_id' => $customOrder->id, + ]); return redirect()->route('custom-orders.show', $customOrder) ->with('info', 'Deposit already paid for this order.'); } // Initiate Yoco payment for deposit + Log::info('Initiating Yoco payment for custom order deposit', [ + 'custom_order_id' => $customOrder->id, + 'deposit_amount' => $customOrder->deposit_amount, + ]); $yocoResponse = $this->initiateYocoPayment( amount: (int)($customOrder->deposit_amount * 100), // Convert to cents - orderId: $customOrder->uuid, + customOrder: $customOrder, orderType: 'custom_deposit', - description: "Deposit for Custom {$customOrder->type} Order #{$customOrder->order_number}" + description: "Deposit for Order #{$customOrder->order_number}" ); if (!$yocoResponse) { + Log::error('Failed to initiate Yoco payment for custom order deposit', [ + 'custom_order_id' => $customOrder->id, + ]); return redirect()->route('custom-orders.show', $customOrder) ->with('error', 'Failed to initiate payment. Please try again.'); } - + Log::info('Yoco payment initiated successfully for custom order deposit', [ + 'custom_order_id' => $customOrder->id, + 'checkout_url' => $yocoResponse['checkout_url'], + ]); return redirect($yocoResponse['checkout_url']); } @@ -207,11 +229,11 @@ class CustomOrderController extends Controller abort(403); } - // Update order status - $customOrder->update([ - 'deposit_status' => 'paid', - 'status' => 'submitted', - ]); + // // Update order status + // $customOrder->update([ + // 'deposit_status' => 'paid', + // 'status' => 'submitted', + // ]); return view('custom-orders.deposit-success', [ 'customOrder' => $customOrder, @@ -250,67 +272,143 @@ class CustomOrderController extends Controller /** * Initiate Yoco payment */ - private function initiateYocoPayment($amount, $orderId, $orderType, $description) + private function initiateYocoPayment($amount, $customOrder, $orderType, $description) { - $yocoSecret = config('services.yoco.secret_key'); + + Log::info('Initiating Yoco payment', [ + 'order_id' => $customOrder->uuid, + 'order_type' => $orderType, + 'amount' => $amount, + 'description' => $description, + ]); - if (!$yocoSecret) { + if (!$customOrder) { + Log::error('Custom order not found for Yoco payment', [ + 'order_id' => $customOrder->uuid ?? 'unknown', + ]); + return null; + } + Log::info('Custom order found for Yoco payment', [ + 'order_id' => $customOrder->uuid, + 'custom_order_data' => $customOrder->toArray(), + ]); + // Get configuration + $secretKey = config('services.yoco.secret_key'); + $mode = config('services.yoco.mode'); + + Log::info('Yoco configuration', [ + 'mode' => $mode, + 'secret_key_set' => !empty($secretKey) && $secretKey !== 'sk_test_your_key_here', + ]); + + // Check if API key is configured + if (empty($secretKey) || $secretKey === 'sk_test_your_key_here') { Log::error('Yoco secret key not configured'); return null; } - - $payload = [ + + $baseUrl = $mode === 'live' + ? 'https://payments.yoco.com/api/checkouts' + : 'https://payments.yoco.com/api/checkouts'; + + $checkoutData = [ 'amount' => $amount, 'currency' => 'ZAR', - 'successUrl' => route('yoco-custom-deposit-success', ['customOrder' => $orderId]), - 'failureUrl' => route('custom-orders.show', ['customOrder' => $orderId]), - 'cancelUrl' => route('custom-orders.show', ['customOrder' => $orderId]), + 'successUrl' => route('yoco-custom-deposit-success', ['customOrder' => $customOrder->uuid]), + 'cancelUrl' => route('custom-orders.show', ['customOrder' => $customOrder->uuid]), + 'failureUrl' => route('custom-orders.show', ['customOrder' => $customOrder->uuid]), 'metadata' => [ - 'order_uuid' => $orderId, + 'order_uuid' => $customOrder->uuid, 'order_type' => $orderType, - ], - 'description' => $description, + 'site' => 'additional_design', + 'description' => $description + ] ]; + Log::info('Yoco checkout data prepared', [ + 'order_id' => $customOrder->uuid, + 'checkout_data' => $checkoutData, + ]); + + // Make API request to Yoco + try { - Log::info('Initiating Yoco payment', [ - 'amount' => $amount, - 'orderId' => $orderId, - 'description' => $description - ]); - $response = Http::withHeaders([ - 'Authorization' => 'Bearer ' . $yocoSecret, + 'Authorization' => 'Bearer ' . $secretKey, 'Content-Type' => 'application/json', - ])->post('https://payments.yoco.com/api/checkouts', $payload); - - Log::info('Yoco API response', [ - 'status' => $response->status(), - 'body' => $response->body() - ]); - + ])->post($baseUrl, $checkoutData); + if ($response->successful()) { - $data = $response->json(); - Log::info('Yoco payment success', [ - 'checkout_url' => $data['redirectUrl'] ?? 'N/A', - 'checkout_id' => $data['id'] ?? 'N/A' + $checkout = $response->json(); + + $checkoutId = $checkout['id'] ?? null; + $redirectUrl = $checkout['redirectUrl'] ?? null; + + Log::info('Yoco checkout created for custom order', [ + 'order_uuid' => $customOrder->uuid, + 'checkout_id' => $checkoutId, + 'redirect_url' => $redirectUrl, ]); + + if (!$checkoutId || !$redirectUrl) { + Log::error('Invalid Yoco checkout response: missing id or redirectUrl', [ + 'order_uuid' => $customOrder->uuid, + 'response' => $checkout, + ]); + throw new \Exception('Invalid Yoco checkout response: missing id or redirectUrl'); + } + + // Persist checkout info to database + try { + $customOrder->update([ + 'yoco_checkout_id' => $checkoutId, + 'yoco_redirect_url' => $redirectUrl, + 'yoco_checkout_response' => json_encode($checkout), + ]); + + // Reload the model to verify update + $customOrder->refresh(); + + if ($customOrder->yoco_checkout_id) { + Log::info('Yoco checkout info saved successfully for custom order', [ + 'order_uuid' => $customOrder->uuid, + 'yoco_checkout_id' => $customOrder->yoco_checkout_id, + ]); + } else { + Log::warning('Yoco checkout ID not saved after update for custom order', [ + 'order_uuid' => $customOrder->uuid, + 'order_data' => $customOrder->toArray(), + ]); + } + } catch (\Exception $dbException) { + Log::error('Database error while saving Yoco checkout info for custom order', [ + 'order_uuid' => $customOrder->uuid, + 'error_message' => $dbException->getMessage(), + 'error_code' => $dbException->getCode(), + 'checkout_id' => $checkoutId, + 'redirect_url' => $redirectUrl, + ]); + throw $dbException; + } + return [ - 'checkout_url' => $data['redirectUrl'], - 'checkout_id' => $data['id'], + 'checkout_url' => $redirectUrl, + 'checkout_id' => $checkoutId, ]; } else { - Log::error('Yoco payment API error', [ + Log::error('Yoco API Error for custom order', [ + 'order_uuid' => $customOrder->uuid, 'status' => $response->status(), 'body' => $response->body() ]); + return null; } } catch (\Exception $e) { - Log::error('Yoco payment exception: ' . $e->getMessage(), [ - 'trace' => $e->getTraceAsString() + Log::error('Yoco Payment Exception for custom order', [ + 'order_uuid' => $customOrder->uuid, + 'message' => $e->getMessage() ]); + return null; } - - return null; } } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 2f8cd66..1a033e2 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Models\CustomOrder; use App\Models\Order; use App\Models\OrderItem; use App\Models\Product; @@ -267,6 +268,7 @@ class OrderController extends Controller 'metadata' => [ 'order_uuid' => $order->uuid, 'order_number' => $order->order_number, + 'order_type' => 'standard', 'site' => 'additional_design', ], ]; @@ -477,6 +479,7 @@ class OrderController extends Controller $metadata = $payload['metadata'] ?? []; $orderUuid = $metadata['order_uuid'] ?? null; + $orderType = $metadata['order_type'] ?? null; $site = $metadata['site'] ?? null; $paymentId = $payload['id'] ?? null; $status = $payload['status'] ?? null; @@ -484,6 +487,7 @@ class OrderController extends Controller \Log::info('Yoco Webhook: Payload extracted', [ 'type' => $type, 'site' => $site, + 'order_type' => $orderType, 'order_uuid' => $orderUuid, 'payment_id' => $paymentId, 'status' => $status, @@ -506,49 +510,107 @@ class OrderController extends Controller return response()->json(['error' => 'Invalid payload'], 400); } - // 7. Update Payment State - $order = Order::where('uuid', $orderUuid)->first(); + // 7. Update Payment State where orderType is 'standard' + if ($orderType === 'standard') { - if (!$order) { - \Log::warning('Yoco Webhook: Order not found', ['order_uuid' => $orderUuid]); - return response()->json(['error' => 'Order not found'], 404); - } - - if ($status === 'succeeded') { - \Log::info('Yoco Webhook: Processing successful payment', [ - 'order_uuid' => $orderUuid, - 'payment_id' => $paymentId, - ]); + $order = Order::where('uuid', $orderUuid)->first(); - if ($order->payment_status !== 'paid') { - $order->update([ - 'payment_status' => 'paid', - 'status' => 'processing', - 'yoco_checkout_response' => json_encode($payload), + if (!$order) { + \Log::warning('Yoco Webhook: Order not found', ['order_uuid' => $orderUuid]); + return response()->json(['error' => 'Order not found'], 404); + } + + if ($status === 'succeeded') { + \Log::info('Yoco Webhook: Processing successful payment', [ + 'order_uuid' => $orderUuid, + 'payment_id' => $paymentId, ]); - // Reduce stock - foreach ($order->items as $item) { - $product = $item->product; - $product->stock -= $item->quantity; - $product->save(); + if ($order->payment_status !== 'paid') { + $order->update([ + 'payment_status' => 'paid', + 'status' => 'processing', + 'yoco_checkout_response' => json_encode($payload), + ]); + + // Reduce stock + foreach ($order->items as $item) { + $product = $item->product; + $product->stock -= $item->quantity; + $product->save(); + } + + \Log::info('Yoco Webhook: Order updated for successful payment', [ + 'order_uuid' => $orderUuid, + 'order_id' => $order->id, + ]); } - - \Log::info('Yoco Webhook: Order updated for successful payment', [ + } elseif ($status === 'failed' || $status === 'cancelled') { + \Log::info('Yoco Webhook: Processing failed/cancelled payment', [ 'order_uuid' => $orderUuid, - 'order_id' => $order->id, + 'payment_id' => $paymentId, + 'status' => $status, + ]); + + $order->update([ + 'payment_status' => 'failed', ]); } - } elseif ($status === 'failed' || $status === 'cancelled') { - \Log::info('Yoco Webhook: Processing failed/cancelled payment', [ - 'order_uuid' => $orderUuid, - 'payment_id' => $paymentId, - 'status' => $status, - ]); + } elseif ($orderType === 'custom_deposit' || $orderType === 'custom_balance') { - $order->update([ - 'payment_status' => 'failed', - ]); + $order = CustomOrder::where('uuid', $orderUuid)->first(); + + if (!$order) { + \Log::warning('Yoco Webhook: Order not found', ['order_uuid' => $orderUuid]); + return response()->json(['error' => 'Order not found'], 404); + } + + if ($status === 'succeeded') { + \Log::info('Yoco Webhook: Processing successful payment', [ + 'order_uuid' => $orderUuid, + 'payment_id' => $paymentId, + 'order_type' => $orderType, + ]); + + if ($orderType === 'custom_deposit' && $order->deposit_status !== 'paid') { + $order->update([ + 'deposit_status' => 'paid', + 'status' => 'submitted', + 'yoco_checkout_response' => json_encode($payload), + ]); + + \Log::info('Yoco Webhook: Order updated for successful deposit payment', [ + 'order_uuid' => $orderUuid, + 'order_id' => $order->id, + 'order_type' => $orderType, + ]); + + } elseif ($orderType === 'custom_balance' && $order->balance_status !== 'paid') { + $order->update([ + 'balance_status' => 'paid', + 'status' => 'in production', + 'yoco_checkout_response' => json_encode($payload), + ]); + + \Log::info('Yoco Webhook: Order updated for successful balance payment', [ + 'order_uuid' => $orderUuid, + 'order_id' => $order->id, + 'order_type' => $orderType, + ]); + } + } elseif ($status === 'failed' || $status === 'cancelled') { + \Log::info('Yoco Webhook: Processing failed/cancelled payment', [ + 'order_uuid' => $orderUuid, + 'payment_id' => $paymentId, + 'status' => $status, + ]); + + if ($orderType === 'custom_deposit') { + $order->update(['deposit_status' => 'failed']); + } elseif ($orderType === 'custom_balance') { + $order->update(['balance_status' => 'failed']); + } + } } \Log::info('Yoco Webhook: Processed successfully', [ diff --git a/app/Models/CustomOrder.php b/app/Models/CustomOrder.php index c70372c..74b8138 100644 --- a/app/Models/CustomOrder.php +++ b/app/Models/CustomOrder.php @@ -23,6 +23,9 @@ class CustomOrder extends Model 'balance_amount', 'deposit_status', 'balance_status', + 'yoco_checkout_id', + 'yoco_redirect_url', + 'yoco_checkout_response', 'customer_brief', 'admin_notes', 'submitted_at', diff --git a/public/css/styles.css b/public/css/styles.css index 4b20791..49d8ae3 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -163,7 +163,8 @@ a:hover { header { background-color: var(--bg-primary); - padding: var(--spacing-md) 0; + /* backdrop-filter: blur(10px); */ + padding: var(--spacing-xs) 0; border-bottom: 1px solid var(--border-color); position: sticky; top: 0; @@ -306,6 +307,35 @@ nav a:hover { /* ===== CARDS ===== */ .card { + background-color: white; + padding: var(--spacing-lg); + border-radius: 20px; + border: 1px solid var(--border-color); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + margin-bottom: var(--spacing-lg); + transition: var(--transition); +} + +.card:hover { + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); +} + +.card--pink { + background-color: var(--accent-light); + padding: var(--spacing-lg); + border-radius: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); + margin-bottom: var(--spacing-lg); + /* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); */ + transition: var(--transition); +} + +.card--pink:hover { + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); +} + +/* Product cards (with image on top) */ +.product-card { background-color: white; overflow: hidden; transition: var(--transition); @@ -313,7 +343,7 @@ nav a:hover { border-radius: 20px; } -.card:hover { +.product-card:hover { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); } diff --git a/resources/views/account/orders.blade.php b/resources/views/account/orders.blade.php index ea856d9..d3c66b8 100644 --- a/resources/views/account/orders.blade.php +++ b/resources/views/account/orders.blade.php @@ -50,10 +50,8 @@ } .table-container { - background: white; - border-radius: 8px; + border-radius: 20px; overflow: hidden; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } table { @@ -114,10 +112,7 @@ } .empty-state { - background-color: var(--bg-secondary); - border-radius: 8px; - padding: var(--spacing-xl); - text-align: center; + border-radius: 20px; } .empty-state p { @@ -184,7 +179,7 @@
You haven't placed any standard orders yet.
Browse ProductsYou haven't created any custom orders yet.
Create Custom OrderContact us for assistance with your account or orders.
support@example.com diff --git a/resources/views/cart.blade.php b/resources/views/cart.blade.php index e75c215..b39d7eb 100644 --- a/resources/views/cart.blade.php +++ b/resources/views/cart.blade.php @@ -18,11 +18,7 @@ margin-bottom: 3rem; } - .cart-items { - background: white; - padding: 2rem; - border-radius: 8px; - } + .empty-cart { text-align: center; @@ -111,9 +107,6 @@ } .summary { - background: white; - padding: 2rem; - border-radius: 8px; height: fit-content; } @@ -221,7 +214,7 @@ @if(count($items) > 0)