Skip to content

Instantly share code, notes, and snippets.

@NandoKstroNet
Last active June 27, 2025 16:05
Show Gist options
  • Save NandoKstroNet/3e51c7e51aa54744fd5bba69e69b0055 to your computer and use it in GitHub Desktop.
Save NandoKstroNet/3e51c7e51aa54744fd5bba69e69b0055 to your computer and use it in GitHub Desktop.
GIST conteudos home projeto
Route::prefix('cart')->name('site.cart.')->group(function(){
Route::get('/', [\App\Http\Controllers\Site\CartController::class, 'index'])->name('index');
Route::post('/add', [\App\Http\Controllers\Site\CartController::class, 'add'])->name('add');
Route::delete('/remove/{item}', [\App\Http\Controllers\Site\CartController::class, 'remove'])->name('remove');
Route::get('/cancel', [\App\Http\Controllers\Site\CartController::class, 'cancel'])->name('cancel');
});
<x-layouts.site>
<div class="w-full">
<div class="border-b border-gray-300 pb-4 flex justify-between items-center">
<h1 class="text-4xl font-thin text-white">
<a href="{{ route('site.home') }}"
class="text-xl hover:underline hover:text-black transition duration-300 ease-in-out">Home</a> <span
class="text-xl">&raquo;</span> Carrinho
</h1>
</div>
<div class="w-full">
@cartcount($cartItems)
@php $totalCart = 0; @endphp
@foreach ($cartItems as $item)
<div class="w-full py-8 border-b border-gray-300 flex justify-around items-center gap-x-5">
<div class="w-[10%]">
<img src="{{ $item['photo'] ? asset('storage/' . $item['photo']) : asset('storage/no-photo.jpg') }}"
alt="Foto Produto: {{ $item['name'] }}" class="w-full rounded-t">
</div>
<div class="w-2/3 flex flex-col">
<div class="text-left">
<h4 class="font-bold capitalize text-white">{{ $item['name'] }} - R$
{{ number_format($item['price'], 2, ',', '.') }} ({{ $item['quantity'] }}x)</h4>
@php $subtotal = $item['price'] * $item['quantity']; @endphp
<h2 class="text-xl font-thin text-white">Subtotal: R$
{{ number_format($subtotal, 2, ',', '.') }}</h2>
</div>
</div>
<div>
<form action="{{ route('site.cart.remove', ['item' => $item['slug']]) }}" method="POST">
@csrf
@method('DELETE')
<button class="text-white cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" class="w-6 h-6 hover:text-red-800">
<path stroke-linecap="round" stroke-linejoin="round"
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
</svg>
</button>
</form>
</div>
</div>
@php $totalCart += $subtotal; @endphp
@endforeach
<div class="w-full py-8 border-b border-gray-300 flex justify-start text-white">
<h2 class="w-[20%] text-2xl font-extrabold">Total:</h2>
<strong class="w-2/3 text-left text-2xl font-extrabold">R$
{{ number_format($totalCart, 2, ',', '.') }}</strong>
</div>
<div class="w-full py-8 mt-10 flex justify-around gap-5 text-white">
<a href="{{ route('site.cart.cancel') }}"
class="px-5 py-2 rounded text-white text-2xl font-bold bg-red-600">Cancelar</a>
<a href="" class="px-5 py-2 rounded text-white text-2xl font-bold bg-green-600">Continuar</a>
</div>
@else
<h3 class="w-full text-center text-white text-4xl font-thin py-4">Nenhum item no seu carrinho de compras!
</h3>
@endcartcount
</div>
</div>
</x-layouts.site>
<?php
namespace App\Services;
use Illuminate\Session\SessionManager;
class CartService
{
public const SESSION_KEY = 'cart';
public function __construct(private SessionManager $session)
{
if(!$this->session->has(self::SESSION_KEY)) $this->session->put(self::SESSION_KEY, []);
}
public function all()
{
return $this->session->get(self::SESSION_KEY);
}
public function count()
{
return count($this->all());
}
public function has(string $item, string $column = 'id')
{
$itemsList = array_column($this->all(), $column);
return in_array($item, $itemsList);
}
public function add(array $item)
{
if($this->session->has(self::SESSION_KEY)) {
if($this->has($item['slug'], 'slug')) {
$items = $this->increaseExistentProduct($this->all(), $item);
$this->session->put(self::SESSION_KEY, $items);
return;
}
$this->session->push(self::SESSION_KEY, $item);
} else {
$this->session->put(self::SESSION_KEY, [$item]);
}
}
public function remove(string $item)
{
$cart = $this->all();
$this->session->put(self::SESSION_KEY, array_filter($cart, function($line) use($item) {
return $line['slug'] !== $item;
}));
}
public function clear()
{
$this->session->put(self::SESSION_KEY, []);
}
private function increaseExistentProduct($items, $item)
{
return array_map(function($itemLine) use($item){
if($item['slug'] == $itemLine['slug']) {
$itemLine['quantity'] += $item['quantity'];
}
return $itemLine;
}, $items);
}
}
<x-layouts.site>
<div class="w-full mt-20">
<div class="border-b border-purple-500 mb-10 pb-4 flex justify-between items-center">
<h1 class="text-4xl font-bold text-white">Produtos</h1>
</div>
<div class="max-w-7xl grid grid-cols-3 gap-14">
@foreach ($products as $product)
<div
class="w-96 min-h-[460px] relative bg-white border border-purple-500 rounded mb-10 shadow shadow-purple-500">
<img src="{{ $product->thumb ? asset('storage/' . $product->thumb) : asset('storage/no-photo.jpg') }}"
alt="Foto Produto: {{ $product->name }}" class="w-full h-52 rounded-t">
<div class="p-4">
<h4 class="text-xl font-bold capitalize">{{ $product->name }}</h4>
<p class="text-xl font-thin py-2">{{ $product->description }}</p>
<h2 class="text-3xl mt-4 mb-10 font-bold text-red-800">R$
{{ number_format($product->price, 2, ',', '.') }}</h2>
<a href="{{ route('site.single', ['product' => $product->slug]) }}"
class="absolute bottom-2 px-8 py-4 mt-5 bg-gradient-to-b from-purple-500 to-purple-800
font-bold text-white transition-all duration-300 ease-in-out rounded
hover:to-purple-800 hover:from-purple-900">
Ver produto
</a>
</div>
</div>
@endforeach
</div>
</div>
</x-layouts.site>
<x-layouts.site>
<div class="w-full mt-20">
@php $photos = $product->photos; @endphp
<div class="max-w-7xl @if ($photos->count()) flex gap-x-4 @endif">
@if ($photos->count())
<div class="w-[40%] p-2">
<img src="{{ asset('storage/' . $photos->first()->photo) }}" alt="Foto Produto: {{ $product->name }}"
class="w-full p-1 rounded bg-purple-500 shadow shadow-black rounded-t" id="mainPhoto">
<div class="w-full mt-4 flex gap-x-2">
@foreach ($photos as $photo)
<img src="{{ asset('storage/' . $photo->photo) }}" alt="Foto Produto: {{ $product->name }}"
class="w-[25%] p-1 rounded bg-purple-500 shadow shadow-black rounded-t photoList">
@endforeach
</div>
</div>
@endif
<div class="@if ($photos->count()) w-[60%] @else w-full @endif pl-12">
<h1 class="text-4xl font-bold text-white mb-4">Produto: {{ $product->name }}</h1>
<p class="text-white">{{ $product->description }}</p>
<h2 class="text-3xl mt-4 mb-10 font-bold text-white">R$
{{ number_format($product->price, 2, ',', '.') }}</h2>
<form action="" method="post">
@csrf
<div class="flex items-center gap-x-2">
<label class="text-white">Quantidade</label>
<input type="hidden" name="cart[product]" value="{{ $product->slug }}">
<input type="number" min="1" name="cart[quantity]" required
class="w-[80px] p-4 rounded border-purple-900 text-white bg-black text-2xl" value="1">
@error('cart.product')
<span class="text-xl font-bold text-white bg-red-800 rounded p-1">{{ $message }}</span>
@enderror
@error('cart.quantity')
<span class="text-xl font-bold text-white bg-red-800 rounded p-1">{{ $message }}</span>
@enderror
</div>
<button
class="px-8 py-4 mt-5 bg-gradient-to-b from-purple-500 to-purple-800
font-bold text-white transition-all duration-300 ease-in-out rounded
hover:to-purple-800 hover:from-purple-900">
COMPRAR
</button>
</form>
</div>
</div>
<div class="w-full mt-10 py-10 border-t border-purple-500">
<p class="text-white text-xl">{{ $product->body }}</p>
</div>
</div>
@push('scripts')
<script>
const mainPhoto = document.querySelector('img#mainPhoto')
const listPhotos = document.querySelectorAll('img.photoList')
listPhotos.forEach(photoEl => {
photoEl.addEventListener('mouseover', e => {
mainPhoto.src = e.target.src;
})
})
</script>
@endpush
</x-layouts.site>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Experts Store</title>
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="bg-fixed bg-gradient-to-b from-10% to-80% from-purple-800 to-black">
<header class="w-full mb-10">
<div class="max-w-7xl mx-auto flex justify-between items-center py-4">
<a href="{{ route('site.home') }}" class="font-extrabold text-white text-xl">Experts Store</a>
<nav class="mr-4">
<ul class="flex items-center gap-x-4">
<li><a href="{{ route('site.home') }}"
class="text-white hover:underline hover:font-bold transition duration-300 ease-in-out @if (request()->routeIs('site.home')) font-bold @else font-thin @endif">Home</a>
</li>
<li class="relative">
<a href=""
class="flex gap-x-2 items-center text-white hover:underline hover:font-bold transition duration-300 ease-in-out @if (request()->routeIs('site.home')) font-bold @else font-thin @endif">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round"
d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 0 0-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 0 0-16.536-1.84M7.5 14.25 5.106 5.272M6 20.25a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Zm12.75 0a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0Z" />
</svg>
@if (session()->has('cart') && count(session('cart')))
<span class="rounded-xl p-1 text-white bg-red-700">
{{ count(session('cart')) }}
</span>
@endif
</a>
</li>
</ul>
</nav>
</div>
</header>
<div class="max-w-7xl mx-auto">
{{ $slot }}
</div>
<footer class="w-full mt-10">
<div class="max-w-7xl mx-auto py-4 text-center border-t border-purple-500">
<small class="text-white ">Experts Store &copy; Todos os Direitos Reservados</small>
</div>
</footer>
@stack('scripts')
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment