diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index ebddaca..8eec78a 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -11,6 +11,42 @@ use Illuminate\Support\Facades\Storage; class ProductController extends Controller { + /** + * Display the homepage with featured products. + */ + public function homepage() + { + // Get trending products (most upvoted in the last 7 days) + $trendingProducts = Product::query() + ->with(['user', 'category']) + ->approved() + ->where('created_at', '>=', now()->subDays(7)) + ->withCount('upvotes') + ->orderBy('upvotes_count', 'desc') + ->limit(6) + ->get(); + + // Get recently added products + $recentProducts = Product::query() + ->with(['user', 'category']) + ->approved() + ->latest() + ->limit(12) + ->get(); + + // Get popular categories with product counts + $categories = Category::query() + ->withCount(['products' => function($query) { + $query->approved(); + }]) + ->having('products_count', '>', 0) + ->orderBy('products_count', 'desc') + ->limit(8) + ->get(); + + return view('welcome', compact('trendingProducts', 'recentProducts', 'categories')); + } + /** * Display a listing of the products. */ diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index e2cbc60..67d1fa0 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -15,7 +15,22 @@ class ProfileController extends Controller */ public function show(User $user) { - return view('profile.show', compact('user')); + // Get user's products + $products = $user->products() + ->with(['category', 'user']) + ->approved() + ->withCount('upvotes') + ->latest() + ->paginate(12); + + // Get user's stats + $stats = [ + 'products_count' => $user->products()->approved()->count(), + 'total_upvotes' => $user->products()->approved()->withCount('upvotes')->get()->sum('upvotes_count'), + 'comments_count' => $user->comments()->count(), + ]; + + return view('profile.show', compact('user', 'products', 'stats')); } /** diff --git a/package-lock.json b/package-lock.json index db9d7c6..726bd64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,14 +9,14 @@ }, "devDependencies": { "@popperjs/core": "^2.11.6", - "@tailwindcss/vite": "^4.0.0", + "@tailwindcss/vite": "^4.1.18", "alpinejs": "^3.14.1", "axios": "^1.11.0", "bootstrap": "^5.2.3", "concurrently": "^9.0.1", "laravel-vite-plugin": "^2.0.0", "sass": "^1.56.1", - "tailwindcss": "^4.0.0", + "tailwindcss": "^4.1.18", "vite": "^7.0.7" } }, diff --git a/package.json b/package.json index 2bd249d..328c0a6 100644 --- a/package.json +++ b/package.json @@ -8,14 +8,14 @@ }, "devDependencies": { "@popperjs/core": "^2.11.6", - "@tailwindcss/vite": "^4.0.0", + "@tailwindcss/vite": "^4.1.18", "alpinejs": "^3.14.1", "axios": "^1.11.0", "bootstrap": "^5.2.3", "concurrently": "^9.0.1", "laravel-vite-plugin": "^2.0.0", "sass": "^1.56.1", - "tailwindcss": "^4.0.0", + "tailwindcss": "^4.1.18", "vite": "^7.0.7" }, "dependencies": { diff --git a/resources/css/app.css b/resources/css/app.css index 1031702..e37b815 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1,68 +1,47 @@ -@import 'tailwindcss'; - -@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php'; -@source '../../storage/framework/views/*.php'; -@source '../**/*.blade.php'; -@source '../**/*.js'; +@import "tailwindcss"; +/* Custom Styles */ @theme { - --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', - 'Segoe UI Symbol', 'Noto Color Emoji'; + --color-primary-50: #f0f9ff; + --color-primary-100: #e0f2fe; + --color-primary-200: #bae6fd; + --color-primary-300: #7dd3fc; + --color-primary-400: #38bdf8; + --color-primary-500: #0ea5e9; + --color-primary-600: #0284c7; + --color-primary-700: #0369a1; + --color-primary-800: #075985; + --color-primary-900: #0c4a6e; + --color-primary-950: #082f49; - /* Custom color palette for ProductHunt-like theme */ - --color-primary-50: #fef2f2; - --color-primary-100: #fee2e2; - --color-primary-200: #fecaca; - --color-primary-300: #fca5a5; - --color-primary-400: #f87171; - --color-primary-500: #ef4444; - --color-primary-600: #dc2626; - --color-primary-700: #b91c1c; - --color-primary-800: #991b1b; - --color-primary-900: #7f1d1d; - - --color-accent-50: #fff7ed; - --color-accent-100: #ffedd5; - --color-accent-200: #fed7aa; - --color-accent-300: #fdba74; - --color-accent-400: #fb923c; - --color-accent-500: #f97316; - --color-accent-600: #ea580c; - --color-accent-700: #c2410c; - --color-accent-800: #9a3412; - --color-accent-900: #7c2d12; + --color-accent-50: #fdf4ff; + --color-accent-100: #fae8ff; + --color-accent-200: #f5d0fe; + --color-accent-300: #f0abfc; + --color-accent-400: #e879f9; + --color-accent-500: #d946ef; + --color-accent-600: #c026d3; + --color-accent-700: #a21caf; + --color-accent-800: #86198f; + --color-accent-900: #701a75; + --color-accent-950: #4a044e; } -/* Custom utility classes */ -@layer utilities { - .text-balance { - text-wrap: balance; - } +/* Utility Classes */ +.line-clamp-1 { + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + overflow: hidden; } -/* Custom component styles */ -@layer components { - .btn-primary { - @apply px-4 py-2 bg-primary-600 text-white rounded-lg font-medium hover:bg-primary-700 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2; - } - - .btn-secondary { - @apply px-4 py-2 bg-gray-100 text-gray-900 rounded-lg font-medium hover:bg-gray-200 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2; - } - - .btn-outline { - @apply px-4 py-2 border-2 border-gray-300 text-gray-700 rounded-lg font-medium hover:border-gray-400 hover:bg-gray-50 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2; - } - - .card { - @apply bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden transition-shadow duration-200 hover:shadow-md; - } - - .input { - @apply block w-full rounded-lg border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 transition-colors duration-200; - } - - .badge { - @apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium; - } +.line-clamp-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.btn-primary { + @apply inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500; } diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index ea9ac94..0c77ad5 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -1,72 +1,77 @@ @extends('layouts.app') @section('content') -
-
-
-
-
{{ __('Login') }}
+
+
+
+

+ {{ __('Login') }} +

+
+
+
+ @csrf -
- - @csrf - -
- - -
- - - @error('email') - - {{ $message }} - - @enderror -
-
- -
- - -
- - - @error('password') - - {{ $message }} - - @enderror -
-
- -
-
-
- - - -
-
-
- -
-
- - - @if (Route::has('password.request')) - - {{ __('Forgot Your Password?') }} - - @endif -
-
- +
+ +
+ + @error('email') +

{{ $message }}

+ @enderror +
-
+ +
+ +
+ + @error('password') +

{{ $message }}

+ @enderror +
+
+ +
+
+ + +
+ + @if (Route::has('password.request')) + + @endif +
+ +
+ +
+ + @if (Route::has('register')) +
+ {{ __("Don't have an account?") }} + + {{ __('Register') }} + +
+ @endif +
diff --git a/resources/views/auth/passwords/confirm.blade.php b/resources/views/auth/passwords/confirm.blade.php index f8c8e61..6e5f020 100644 --- a/resources/views/auth/passwords/confirm.blade.php +++ b/resources/views/auth/passwords/confirm.blade.php @@ -1,48 +1,48 @@ @extends('layouts.app') @section('content') -
-
-
-
-
{{ __('Confirm Password') }}
+
+
+
+

+ {{ __('Confirm Password') }} +

+

+ {{ __('Please confirm your password before continuing.') }} +

+
+
+
+ @csrf -
- {{ __('Please confirm your password before continuing.') }} - - - @csrf - -
- - -
- - - @error('password') - - {{ $message }} - - @enderror -
-
- -
-
- - - @if (Route::has('password.request')) - - {{ __('Forgot Your Password?') }} - - @endif -
-
- +
+ +
+ + @error('password') +

{{ $message }}

+ @enderror +
-
+ +
+ +
+ + @if (Route::has('password.request')) + + @endif +
diff --git a/resources/views/auth/passwords/email.blade.php b/resources/views/auth/passwords/email.blade.php index d1ac783..61b1990 100644 --- a/resources/views/auth/passwords/email.blade.php +++ b/resources/views/auth/passwords/email.blade.php @@ -1,46 +1,65 @@ @extends('layouts.app') @section('content') -
-
-
-
-
{{ __('Reset Password') }}
- -
- @if (session('status')) -