Working on the homepage

This commit is contained in:
Shaun Collins
2026-04-29 15:55:21 +01:00
parent 53aa345082
commit 89cc867c7d
29 changed files with 360 additions and 58 deletions
+1
View File
@@ -11,6 +11,7 @@
/.phpunit.cache /.phpunit.cache
/.vscode /.vscode
/.zed /.zed
/.junie
/auth.json /auth.json
/node_modules /node_modules
/public/build /public/build
+18
View File
@@ -3,9 +3,27 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
class ImagesController extends Controller class ImagesController extends Controller
{ {
public function jobs()
{
$path = resource_path('images/Jobs');
if (!File::exists($path)) {
return response()->json([]);
}
$files = File::files($path);
$filenames = array_map(function ($file) {
return $file->getFilename();
}, $files);
return response()->json($filenames);
}
public function show(Request $request, string $file) public function show(Request $request, string $file)
{ {
try { try {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

+1 -1
View File
@@ -13,7 +13,7 @@
'Segoe UI Symbol', 'Noto Color Emoji'; 'Segoe UI Symbol', 'Noto Color Emoji';
--primary: #F7D720; --primary: #F7D720;
/*--secondary: #0091FE;*/ /*--secondary: #0091FE;*/
--secondary: #000000; --secondary: #02284E;
--tertiary:#000000; --tertiary:#000000;
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 708 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

+3
View File
@@ -2,3 +2,6 @@ import axios from 'axios';
window.axios = axios; window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
import * as bootstrap from 'bootstrap';
window.bootstrap = bootstrap;
@@ -0,0 +1,62 @@
<div class="container py-5">
<div class="row align-items-center">
<div class="col-lg-7">
<h1 class="fw-bold mb-4 text-primary">About Us</h1>
<p class="lead mb-4">
Based in Shrewsbury and serving Shropshire and nationwide, <strong>Stu Moves You</strong> is your trusted partner for professional removals and efficient waste management.
</p>
<p class="mb-4">
We specialize in both domestic and commercial removals, bringing years of experience and a dedication to care for every job. Whether you're moving your family home or relocating your entire business, our team ensures a seamless, stress-free experience from start to finish.
</p>
<p class="mb-4">
As fully licensed and insured waste management specialists, we also provide a convenient and cost-effective alternative to skip hire. We take pride in our competitive pricing and our commitment to responsible disposal, guaranteeing to beat any price on waste removal.
</p>
<div class="row g-4 mt-2">
<div class="col-md-6">
<div class="d-flex align-items-start">
<i class="fas fa-check-circle text-primary mt-1 me-3"></i>
<div>
<h2 class="h5 fw-bold mb-1">Licensed & Insured</h2>
<p class="text-muted small mb-0">Complete peace of mind for every move.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="d-flex align-items-start">
<i class="fas fa-truck text-primary mt-1 me-3"></i>
<div>
<h2 class="h5 fw-bold mb-1">Nationwide Coverage</h2>
<p class="text-muted small mb-0">From Shrewsbury to anywhere in the UK.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="d-flex align-items-start">
<i class="fas fa-trash-alt text-primary mt-1 me-3"></i>
<div>
<h2 class="h5 fw-bold mb-1">Waste Management</h2>
<p class="text-muted small mb-0">Cheaper than a skip, guaranteed!</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="d-flex align-items-start">
<i class="fas fa-users text-primary mt-1 me-3"></i>
<div>
<h2 class="h5 fw-bold mb-1">Domestic & Commercial</h2>
<p class="text-muted small mb-0">Tailored solutions for homes and offices.</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-5 mt-5 mt-lg-0">
<div class="position-relative">
<img src="/images/banner.jpg" alt="About Stu Moves You" class="img-fluid rounded-3 shadow-lg">
<div class="position-absolute bottom-0 end-0 bg-primary text-secondary p-4 rounded-start-3 shadow-lg d-none d-md-block" style="max-width: 250px;">
<p class="mb-0 fw-bold h5">Professional, affordable and effective!</p>
</div>
</div>
</div>
</div>
</div>
+26 -20
View File
@@ -1,50 +1,56 @@
<div class="container"> <div class="container">
<div class="text-center mb-4"> <div class="text-center mb-4">
<h1>Stress-Free Removals, Nationwide</h1> <h1 class="fw-bold text-primary">Stress-Free Removals, Nationwide</h1>
<p> <p class="lead">
Whether you're moving across town or to the other end of the country, From local relocations to nationwide moves, our dedicated team delivers a seamless, high-quality service tailored to your specific requirements. We manage every detail of your transition with professional care and efficiency, including:
our experienced team provides a seamless and efficient removal service tailored to your needs.
We handle every aspect of your move, including:
</p> </p>
</div> </div>
<div class="row g-4"> <div class="row g-4">
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<div class="text-secondary bg-primary p-4 rounded-3 h-100"> <div class="text-secondary bg-primary p-4 rounded-3 h-100">
<h2>Full Removal Services</h2> <h2 class="h4 fw-bold">Comprehensive Relocation</h2>
<p> <p class="mb-0">
From carefully packing your belongings to safely transporting them to your new destination. Our end-to-end removal service handles everything from initial planning to safe delivery, ensuring a seamless transition to your new home.
</p> </p>
</div> </div>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<div class="text-secondary bg-primary p-4 rounded-3 h-100"> <div class="text-secondary bg-primary p-4 rounded-3 h-100">
<h2>Professional Packing Services</h2> <h2 class="h4 fw-bold">Expert Packing Solutions</h2>
<p> <p class="mb-0">
Let our skilled packers take the stress out of packing. We ensure your items are secure and protected for transit. Relieve the pressure of moving with our professional packing team, using industry-standard techniques to keep your items secure and protected.
</p> </p>
</div> </div>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<div class="text-secondary bg-primary p-4 rounded-3 h-100"> <div class="text-secondary bg-primary p-4 rounded-3 h-100">
<h2>Packing Materials</h2> <h2 class="h4 fw-bold">Premium Packing Supplies</h2>
<p> <p class="mb-0">
We can source and supply all the high-quality packing materials you need, saving you time and effort. We supply high-grade, durable materials—including reinforced boxes and protective wrap—designed to safeguard your valuables throughout the journey.
</p> </p>
</div> </div>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<div class="text-secondary bg-primary p-4 rounded-3 h-100"> <div class="text-secondary bg-primary p-4 rounded-3 h-100">
<h2>Transportation to New Address or Storage</h2> <h2 class="h4 fw-bold">Secure Nationwide Transport</h2>
<p> <p class="mb-0">
We'll move your items safely and efficiently to your new home or business premises, or to a secure storage facility. Our modern fleet and experienced drivers ensure the timely and safe transportation of your possessions to any destination across the UK.
</p> </p>
</div> </div>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<div class="text-secondary bg-primary p-4 rounded-3 h-100"> <div class="text-secondary bg-primary p-4 rounded-3 h-100">
<h2>Storage Solutions</h2> <h2 class="h4 fw-bold">Flexible Storage Options</h2>
<p> <p class="mb-0">
Need storage? We can help you find a suitable and secure storage facility to meet your specific requirements. Should you require extra space, we provide access to secure, monitored storage facilities for both short and long-term requirements.
</p>
</div>
</div>
<div class="col-12 col-md-4">
<div class="text-secondary bg-primary p-4 rounded-3 h-100">
<h2 class="h4 fw-bold">Professional Waste Clearance</h2>
<p class="mb-0">
As licensed waste carriers, we offer a cost-effective alternative to skip hire, with a commitment to responsible disposal and competitive pricing.
</p> </p>
</div> </div>
</div> </div>
@@ -0,0 +1,124 @@
<div class="container py-5">
<div class="text-center mb-5">
<h2 class="fw-bold text-primary">Our Recent Jobs</h2>
<p class="lead">Take a look at some of our recent jobs.</p>
</div>
<div id="jobsCarousel" class="carousel slide shadow-lg rounded-3 overflow-hidden">
<div class="carousel-inner bg-light" id="carousel-items" style="min-height: 400px;">
<div class="carousel-item active">
<div class="d-flex justify-content-center align-items-center" style="height: 500px;">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#jobsCarousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon bg-dark rounded-circle p-2" aria-hidden="true" style="background-size: 50%;"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#jobsCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon bg-dark rounded-circle p-2" aria-hidden="true" style="background-size: 50%;"></span>
<span class="visually-hidden">Next</span>
</button>
<div class="carousel-indicators" id="carousel-indicators">
<!-- Indicators will be injected here -->
</div>
</div>
</div>
<style>
#jobsCarousel .carousel-item img {
height: 500px;
object-fit: contain;
background-color: #f8f9fa;
}
@media (max-width: 768px) {
#jobsCarousel .carousel-item img {
height: 350px;
}
#jobsCarousel .carousel-inner,
#jobsCarousel .carousel-item > div {
min-height: 350px !important;
height: 350px !important;
}
}
#jobsCarousel .carousel-indicators [data-bs-target] {
background-color: var(--bs-primary);
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
const carouselInner = document.getElementById('carousel-items');
const indicatorsContainer = document.getElementById('carousel-indicators');
fetch('{{ route('Images.jobs') }}')
.then(response => response.json())
.then(images => {
if (!images || images.length === 0) {
carouselInner.innerHTML = `
<div class="carousel-item active">
<div class="d-flex justify-content-center align-items-center" style="height: 500px;">
<p class="text-muted">No recent job images available.</p>
</div>
</div>`;
return;
}
carouselInner.innerHTML = '';
indicatorsContainer.innerHTML = '';
images.forEach((image, index) => {
// Create Item
const item = document.createElement('div');
item.className = `carousel-item ${index === 0 ? 'active' : ''}`;
const img = document.createElement('img');
img.src = `/images/Jobs/${image}`;
img.className = 'd-block w-100';
img.alt = `Job image ${index + 1}`;
item.appendChild(img);
carouselInner.appendChild(item);
// Create Indicator
const indicator = document.createElement('button');
indicator.type = 'button';
indicator.dataset.bsTarget = '#jobsCarousel';
indicator.dataset.bsSlideTo = index;
indicator.className = index === 0 ? 'active' : '';
indicator.setAttribute('aria-label', `Slide ${index + 1}`);
if (index === 0) indicator.setAttribute('aria-current', 'true');
indicatorsContainer.appendChild(indicator);
});
if (images.length <= 1) {
document.querySelectorAll('#jobsCarousel [data-bs-slide]').forEach(el => el.style.display = 'none');
indicatorsContainer.style.display = 'none';
}
// Initialize carousel after items are added
if (window.bootstrap && window.bootstrap.Carousel) {
new window.bootstrap.Carousel(document.getElementById('jobsCarousel'), {
ride: 'carousel',
interval: 5000
});
}
})
.catch(error => {
console.error('Error loading job images:', error);
carouselInner.innerHTML = `
<div class="carousel-item active">
<div class="d-flex justify-content-center align-items-center" style="height: 500px;">
<p class="text-danger">Failed to load images. Please try again later.</p>
</div>
</div>`;
});
});
</script>
+110 -26
View File
@@ -1,42 +1,126 @@
@extends('layouts.main') @extends('layouts.main')
@section('content') @section('content')
<div class="row g-5">
<!-- Contact Information -->
<div class="col-lg-5">
<h1 class="fw-bold text-primary mb-4">Get in Touch</h1>
<p class="lead text-muted mb-5">
Whether you're planning a house move, office relocation, or need professional waste management, our team is ready to help. Reach out today for a free, no-obligation quote.
</p>
<div class="contact-details">
<a href="tel:{{ config('app.phone') }}" class="contact-card d-flex align-items-center mb-3 p-3 rounded-3 border bg-white shadow-sm text-decoration-none transition-all">
<div class="flex-shrink-0 bg-primary text-secondary rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-phone-alt"></i>
</div>
<div class="ms-4">
<h5 class="mb-0 fw-bold text-dark">Phone</h5>
<p class="mb-0 text-muted">{{ config('app.phone') }}</p>
</div>
<div class="ms-auto text-primary">
<i class="fas fa-chevron-right"></i>
</div>
</a>
<a href="mailto:{{ config('app.email') ?: 'info@stumovesyou.co.uk' }}" class="contact-card d-flex align-items-center mb-3 p-3 rounded-3 border bg-white shadow-sm text-decoration-none transition-all">
<div class="flex-shrink-0 bg-primary text-secondary rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fas fa-envelope"></i>
</div>
<div class="ms-4">
<h5 class="mb-0 fw-bold text-dark">Email</h5>
<p class="mb-0 text-muted">{{ config('app.email') ?: 'info@stumovesyou.co.uk' }}</p>
</div>
<div class="ms-auto text-primary">
<i class="fas fa-chevron-right"></i>
</div>
</a>
<a href="{{ config('social.links.facebook.url') }}" target="_blank" class="contact-card d-flex align-items-center mb-3 p-3 rounded-3 border bg-white shadow-sm text-decoration-none transition-all">
<div class="flex-shrink-0 bg-primary text-secondary rounded-circle d-flex align-items-center justify-content-center" style="width: 50px; height: 50px;">
<i class="fab fa-facebook-f"></i>
</div>
<div class="ms-4">
<h5 class="mb-0 fw-bold text-dark">Facebook</h5>
<p class="mb-0 text-muted">Stu Moves You</p>
</div>
<div class="ms-auto text-primary">
<i class="fas fa-chevron-right"></i>
</div>
</a>
</div>
</div>
<!-- Contact Form -->
<div class="col-lg-7">
<div class="card border-0 shadow-sm rounded-3 bg-light">
<div class="card-body p-4 p-md-5">
@if(session('success')) @if(session('success'))
<div class="alert alert-success"> <div class="alert alert-success border-0 shadow-sm mb-4">
{{ session('success') }} <i class="fas fa-check-circle me-2"></i> {{ session('success') }}
</div> </div>
@endif @endif
<div class="container mt-5">
<h1 class="mt-4 mb-4">Contact Us</h1>
<div class="row">
<div class="col-md-8 offset-md-2">
<form action="{{ route('contact.submit') }}" method="POST"> <form action="{{ route('contact.submit') }}" method="POST">
@csrf @csrf
<div class="mb-3"> <div class="row g-3">
<label for="name" class="form-label">Your Name</label> <div class="col-md-6">
<input type="text" class="form-control" id="name" name="name" placeholder="Enter your name" required> <div class="form-floating">
<input type="text" class="form-control border-0" id="name" name="name" placeholder="Your Name" required>
<label for="name">Your Name</label>
</div> </div>
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<input type="email" class="form-control" id="email" name="email" placeholder="Enter your email" required>
</div> </div>
<div class="mb-3"> <div class="col-md-6">
<label for="message" class="form-label">Message</label> <div class="form-floating">
<textarea class="form-control" id="message" name="message" rows="5" placeholder="Enter your message" required></textarea> <input type="email" class="form-control border-0" id="email" name="email" placeholder="name@example.com" required>
<label for="email">Email Address</label>
</div>
</div>
<div class="col-12">
<div class="form-floating">
<textarea class="form-control border-0" placeholder="Leave a message here" id="message" name="message" style="height: 150px" required></textarea>
<label for="message">Your Message</label>
</div>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary btn-lg px-5 py-3 w-100 fw-bold shadow-sm">
Send Message <i class="fas fa-paper-plane ms-2"></i>
</button>
</div>
</div> </div>
<button type="submit" class="btn btn-primary">Send</button>
</form> </form>
</div> </div>
</div> </div>
<div class="row mt-5 text-center justify-content-center">
@foreach(config('social.links') as $link)
<div class="col-6 col-md-8 mb-4">
<a href="{{ $link['url'] }}" class="social-link text-decoration-none d-flex align-items-center justify-content-center gap-2 p-3 border rounded social-link"
target="_blank">
<i class="{{ $link['icon'] }} fs-3 text-primary"></i>
<span style="font-size: 1rem; font-weight: bold;">{{ $link['name'] }}</span>
</a>
</div> </div>
@endforeach
</div>
</div> </div>
@if(config('site.show_location') && config('site.map_key'))
<div class="row mt-5">
<div class="col-12">
<div class="rounded-3 overflow-hidden shadow-sm">
<iframe
width="100%" height="400"
frameborder="0" style="border:0"
referrerpolicy="no-referrer-when-downgrade"
src="https://www.google.com/maps/embed/v1/place?key={{ config('site.map_key') }}&q={{ config('site.address') }}"
allowfullscreen>
</iframe>
</div>
</div>
</div>
@endif
<style>
.contact-card {
transition: all 0.3s ease;
}
.contact-card:hover {
transform: translateY(-5px);
border-color: var(--bs-primary) !important;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
background-color: #f8f9fa !important;
}
.contact-card:hover .flex-shrink-0 {
transform: scale(1.1);
transition: transform 0.3s ease;
}
</style>
@endsection @endsection
+7 -4
View File
@@ -9,18 +9,19 @@
@endif @endif
<div <div
class="p-5 min-h-screen bg-cover bg-center d-flex align-items-center justify-content-center text-center position-relative" class="p-5 min-h-screen bg-cover bg-center d-flex align-items-center justify-content-center text-center position-relative"
style="background-image: url('/images/home.jpeg'); background-size: cover; min-height: 100%; max-width: 100%; width: 100vw;"> style="background-image: url('/images/home.jpg'); background-size: cover; min-height: 100%; max-width: 100%; width: 100vw;">
<div class="position-absolute top-0 start-0 w-100 h-100" style="background-color: rgba(0, 0, 0, 0.5);"></div> <div class="position-absolute top-0 start-0 w-100 h-100" style="background-color: rgba(0, 0, 0, 0.5);"></div>
<div class="position-relative text-white px-3"> <div class="position-relative text-white px-3">
<div class="display-1 fw-bold mb-4"> <div class="display-1 fw-bold mb-4">
Domestic and commercial Removals Professional House Movers
<br>
Commercial & Domestic
<br> <br>
<span class="text-primary">&#x2022;</span> <span class="text-primary">&#x2022;</span>
<span class="text-secondary">&#x2022;</span>
<br> <br>
Waste management Effective Waste Management
</div> </div>
<div class="display-4 mb-3"> <div class="display-4 mb-3">
in Shrewsbury | Shropshire | Nationwide in Shrewsbury | Shropshire | Nationwide
@@ -32,6 +33,8 @@
@endif @endif
</div> </div>
</div> </div>
@include('components.about')
@include('components.jobs-carousel')
<div class="container py-5"> <div class="container py-5">
<div class="col-md-12"> <div class="col-md-12">
<div class="row justify-content-center"> <div class="row justify-content-center">
+1
View File
@@ -39,6 +39,7 @@ Route::get('/classes', function () {
})->name('Classes'); })->name('Classes');
Route::controller(ImagesController::class)->group(function () { Route::controller(ImagesController::class)->group(function () {
Route::get('images/Jobs', 'jobs')->name('Images.jobs');
Route::get('images/{file}', 'show')->name('Images.show'); Route::get('images/{file}', 'show')->name('Images.show');
Route::get('images/{directory}/{file}', 'subDirectory')->name('Images.subDirectory'); Route::get('images/{directory}/{file}', 'subDirectory')->name('Images.subDirectory');
}); });