Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions app/Http/Controllers/PreferencesController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace App\Http\Controllers;

use App\Http\Requests\UpdatePreferencesRequest;
use App\Services\Preferences\PreferencesService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;

class PreferencesController extends Controller
{
protected $preferencesService;

public function __construct(PreferencesService $preferencesService)
{
$this->preferencesService = $preferencesService;
}

/**
* Get user preferences.
*/
public function show(Request $request)
{
$preferences = $this->preferencesService->getPreferences($request->user());

return response()->json($preferences);
}

/**
* Update user preferences.
*/
public function update(UpdatePreferencesRequest $request)
{
$this->preferencesService->updatePreferences($request->user(), $request->validated());

return Redirect::back()->with('status', 'preferences-updated');
}
}
39 changes: 39 additions & 0 deletions app/Http/Requests/UpdatePreferencesRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class UpdatePreferencesRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}

/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'theme' => ['required', 'string', 'in:system,light,dark'],
];
}

/**
* Get custom messages for validator errors.
*/
public function messages(): array
{
return [
'theme.required' => 'Theme is required.',
'theme.in' => 'The selected theme is invalid.',
];
}
}
4 changes: 4 additions & 0 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
use App\Repositories\Address\Interfaces\AddressRepositoryInterface;
use App\Repositories\Address\AddressRepository;

use App\Repositories\Preferences\Interfaces\PreferencesRepositoryInterface;
use App\Repositories\Preferences\PreferencesRepository;

use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Vite;
use Illuminate\Support\ServiceProvider;
Expand All @@ -41,6 +44,7 @@ public function register(): void
$this->app->bind(ProductRepositoryInterface::class, ProductRepository::class);
$this->app->bind(BannerRepositoryInterface::class, BannerRepository::class);
$this->app->bind(AddressRepositoryInterface::class, AddressRepository::class);
$this->app->bind(PreferencesRepositoryInterface::class, PreferencesRepository::class);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace App\Repositories\Preferences\Interfaces;

use App\Models\User;

interface PreferencesRepositoryInterface
{
/**
* Get user preferences by user ID.
*
* @param int $userId
* @return array
*/
public function getByUserId(int $userId): array;

/**
* Update user preferences.
*
* @param int $userId
* @param array $data
* @return array
*/
public function updateByUserId(int $userId, array $data): array;
}
47 changes: 47 additions & 0 deletions app/Repositories/Preferences/PreferencesRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace App\Repositories\Preferences;

use App\Models\Profile;
use App\Repositories\Preferences\Interfaces\PreferencesRepositoryInterface;

class PreferencesRepository implements PreferencesRepositoryInterface
{
/**
* Get user preferences by user ID.
*
* @param int $userId
* @return array
*/
public function getByUserId(int $userId): array
{
$profile = Profile::where('user_id', $userId)->first();

return [
'theme' => $profile?->theme ?? 'system',
];
}

/**
* Update user preferences.
*
* @param int $userId
* @param array $data
* @return array
*/
public function updateByUserId(int $userId, array $data): array
{
$profile = Profile::firstOrCreate(
['user_id' => $userId],
['theme' => 'system'],
);

if (isset($data['theme'])) {
$profile->update(['theme' => $data['theme']]);
}

return [
'theme' => $profile->theme,
];
}
}
39 changes: 39 additions & 0 deletions app/Services/Preferences/PreferencesService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Services\Preferences;

use App\Models\User;
use App\Repositories\Preferences\Interfaces\PreferencesRepositoryInterface;

class PreferencesService
{
protected $preferencesRepository;

public function __construct(PreferencesRepositoryInterface $preferencesRepository)
{
$this->preferencesRepository = $preferencesRepository;
}

/**
* Get preferences for a user.
*
* @param User $user
* @return array
*/
public function getPreferences(User $user): array
{
return $this->preferencesRepository->getByUserId($user->id);
}

/**
* Update preferences for a user.
*
* @param User $user
* @param array $data
* @return array
*/
public function updatePreferences(User $user, array $data): array
{
return $this->preferencesRepository->updateByUserId($user->id, $data);
}
}
83 changes: 46 additions & 37 deletions resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@
--leading-loose: 2;

/* Primary Light (New Green Palette) */
--primary-50: 120.0 66.7% 98.8%; /* #FAFEFA */
--primary-100: 128.0 49.5% 82.2%; /* #bbe8c1 */
--primary-50: 120 66.7% 98.8%; /* #FAFEFA */
--primary-100: 128 49.5% 82.2%; /* #bbe8c1 */
--primary-200: 127.3 49.3% 73.7%; /* #9bdda3 */
--primary-300: 126.8 49.7% 61.8%; /* #6dce78 */
--primary-400: 126.7 50.0% 54.5%; /* #51c55e */
--primary-500: 127.0 66.2% 42.9%; /* #25b636 */
--primary-600: 126.8 66.0% 39.2%; /* #22a631 */
--primary-700: 127.0 66.5% 30.4%; /* #1a8126 */
--primary-400: 126.7 50% 54.5%; /* #51c55e */
--primary-500: 127 66.2% 42.9%; /* #25b636 */
--primary-600: 126.8 66% 39.2%; /* #22a631 */
--primary-700: 127 66.5% 30.4%; /* #1a8126 */
--primary-800: 127.5 66.7% 23.5%; /* #14641e */
--primary-900: 127.0 65.2% 18.0%; /* #104c17 */
--primary-1000: 127.0 65.2% 18.0%; /* #104c17 */
--primary-1100: 127.0 65.2% 18.0%; /* #104c17 */
--primary-900: 127 65.2% 18%; /* #104c17 */
--primary-1000: 127 65.2% 18%; /* #104c17 */
--primary-1100: 127 65.2% 18%; /* #104c17 */

/* Ground Light */
--ground-50: 240 20% 99%; /* #fcfcfd */
Expand All @@ -60,7 +60,7 @@

/* Base Mapping */
--primary: var(--primary-500);
--ground: var(--ground-50);
--ground: var(--ground-1100);

--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
Expand Down Expand Up @@ -89,11 +89,22 @@
--radius: 0.5rem;
}
.dark {
/* Primary Light */
/* Primary Dark */
--primary-50: 120 23% 6%; /* #0c130c */
--primary-100: 113 20% 9%; /* #131b12 */
--primary-200: 120 28% 13%; /* #182b18 */
--primary-300: 122 45% 16%; /* #173c18 */
--primary-400: 123 44% 20%; /* #1d4a1f */
--primary-500: 122 44% 25%; /* #235a25 */
--primary-600: 123 46% 29%; /* #286b2b */
--primary-700: 124 48% 33%; /* #2c7d31 */
--primary-800: 127 66% 43%; /* #25b636 */
--primary-900: 132 93% 35%; /* #06aa27 */
--primary-1000: 123 62% 59%; /* #55d75c */
--primary-1100: 119 76% 83%; /* #b5f5b4 */


/* Ground Light */
--ground-50: 240 6% 7%; /* #111113 */
/* Ground Dark - Using your dark green palette */
--ground-50: 240 6% 7%; /* #111113 - darkest green */
--ground-100: 240 4% 10%; /* #19191b */
--ground-200: 220 4% 14%; /* #222325 */
--ground-300: 228 6% 17%; /* #292a2e */
Expand All @@ -108,32 +119,30 @@

/* Base Mapping */
--primary: var(--primary-500);
--ground: var(--ground-200);
--ground: var(--ground-1100);

--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--card: 0 0% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 0 0% 3.9%;
--popover-foreground: 0 0% 98%;
/* --primary: 0 0% 98%;
--primary-foreground: 0 0% 9%; */
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--background: 113 20% 9%; /* #131b12 - dark green background */
--foreground: 120 66.7% 98.8%; /* #FAFEFA - light text */
--card: 0 0% 100%; /* #14641e - slightly lighter for cards */
--card-foreground: 120 66.7% 98.8%; /* #FAFEFA */
--popover: 127.5 66.7% 23.5%; /* #14641e */
--popover-foreground: 120 66.7% 98.8%; /* #FAFEFA */
--secondary: 127 66.5% 30.4%; /* #1a8126 */
--secondary-foreground: 120 66.7% 98.8%; /* #FAFEFA */
--muted: 0 0% 96.1%; /* #1a8126 */
--muted-foreground: var(--ground-800); /* #9bdda3 - muted light green */
--accent: 127 66.2% 42.9%; /* #25b636 */
--accent-foreground: 120 66.7% 98.8%; /* #FAFEFA */
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
--border: 113 20% 9%; /* #1a8126 - border in dark mode */
--input: 127.5 66.7% 23.5%; /* #14641e - input background */
--ring: 126.7 50% 54.5%; /* #51c55e - accent green for rings */
--chart-1: 127 66.2% 42.9%;
--chart-2: 127 66.5% 30.4%;
--chart-3: 127.5 66.7% 23.5%;
--chart-4: 126.8 49.7% 61.8%;
--chart-5: 126.7 50% 54.5%;
}
}

Expand Down
12 changes: 6 additions & 6 deletions resources/js/Components/AddressForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
reset();
}
}
}, [show]);

Check warning on line 85 in resources/js/Components/AddressForm.tsx

View workflow job for this annotation

GitHub Actions / Build and Test

React Hook useEffect has missing dependencies: 'initialData', 'isEditing', 'reset', and 'setData'. Either include them or remove the dependency array

const fetchProvinces = async () => {
try {
Expand Down Expand Up @@ -169,9 +169,9 @@

return (
<Modal show={show} onClose={handleClose} maxWidth="lg">
<div className="max-h-[90vh] overflow-y-auto p-6 sm:p-8">
<div className="max-h-[90vh] overflow-y-auto bg-background p-6 sm:p-8">
<div className="mb-5">
<h2 className="mb-2 text-2xl font-bold text-[#1A1A1A]">
<h2 className="mb-2 text-2xl font-bold text-foreground">
{isEditing ? 'Edit Address' : 'Add New Address'}
</h2>

Expand Down Expand Up @@ -269,7 +269,7 @@
id="province_id"
value={data.province_id ?? ''}
onChange={handleProvinceChange} // Gunakan fungsi yang dibuat di atas
className="h-12 w-full rounded-[16px] border border-gray-200 px-6 text-base"
className="h-12 w-full rounded-[16px] border border-gray-200 px-6 text-base dark:border-primary dark:bg-background dark:text-foreground"
>
<option value="">Select Province</option>
{provinces.map((province) => (
Expand Down Expand Up @@ -304,7 +304,7 @@
: null,
)
}
className="h-12 w-full rounded-[16px] border border-gray-200 px-6 text-base"
className="h-12 w-full rounded-[16px] border border-gray-200 px-6 text-base dark:border-primary dark:bg-background dark:text-foreground"
disabled={
processing || loadingGeo || !data.province_id
}
Expand Down Expand Up @@ -337,7 +337,7 @@
onChange={(e) => setData('address', e.target.value)}
placeholder="Enter your full address"
rows={4}
className="w-full rounded-[16px] border border-gray-200 px-6 py-3 text-base"
className="w-full rounded-[16px] border border-gray-200 px-6 py-3 text-base dark:border-primary dark:bg-background dark:text-foreground"
disabled={processing}
/>
<InputError message={errors.address} className="mt-2" />
Expand All @@ -359,7 +359,7 @@
}
placeholder="e.g., Ring the doorbell twice"
rows={3}
className="w-full rounded-[16px] border border-gray-200 px-6 py-3 text-base"
className="w-full rounded-[16px] border border-gray-200 px-6 py-3 text-base dark:border-primary dark:bg-background dark:text-foreground"
disabled={processing}
/>
<InputError
Expand Down
Loading