diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index d79d157..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/app/Http/Controllers/FrontMediaController.php b/app/Http/Controllers/FrontMediaController.php index 8e9312c..031b6bd 100644 --- a/app/Http/Controllers/FrontMediaController.php +++ b/app/Http/Controllers/FrontMediaController.php @@ -71,14 +71,14 @@ public function searchMemes(Request $request) ->where(function ($q) use ($query) { // Search in name and description using ILIKE for partial matches $q->where('name', 'ILIKE', "%{$query}%") - ->orWhere('description', 'ILIKE', "%{$query}%") + ->orWhere('description', 'ILIKE', "%{$query}%") // Search in JSON arrays using PostgreSQL JSON operators - ->orWhereRaw("keywords::text ILIKE ?", ["%{$query}%"]) - ->orWhereRaw("action_keywords::text ILIKE ?", ["%{$query}%"]) - ->orWhereRaw("emotion_keywords::text ILIKE ?", ["%{$query}%"]) - ->orWhereRaw("misc_keywords::text ILIKE ?", ["%{$query}%"]); + ->orWhereRaw('keywords::text ILIKE ?', ["%{$query}%"]) + ->orWhereRaw('action_keywords::text ILIKE ?', ["%{$query}%"]) + ->orWhereRaw('emotion_keywords::text ILIKE ?', ["%{$query}%"]) + ->orWhereRaw('misc_keywords::text ILIKE ?', ["%{$query}%"]); }) - ->orderByRaw(" + ->orderByRaw(' CASE WHEN name ILIKE ? THEN 1 WHEN description ILIKE ? THEN 2 @@ -88,7 +88,7 @@ public function searchMemes(Request $request) WHEN misc_keywords::text ILIKE ? THEN 6 ELSE 7 END, name ASC - ", ["%{$query}%", "%{$query}%", "%{$query}%", "%{$query}%", "%{$query}%", "%{$query}%"]) + ', ["%{$query}%", "%{$query}%", "%{$query}%", "%{$query}%", "%{$query}%", "%{$query}%"]) ->take($limit) ->get(); } @@ -115,12 +115,12 @@ public function searchBackgrounds(Request $request) // Search in prompt field using ILIKE for partial matches $backgrounds = BackgroundMedia::where('status', 'completed') ->where('prompt', 'ILIKE', "%{$query}%") - ->orderByRaw(" + ->orderByRaw(' CASE WHEN prompt ILIKE ? THEN 1 ELSE 2 END, prompt ASC - ", ["%{$query}%"]) + ', ["%{$query}%"]) ->take($limit) ->get(); } diff --git a/resources/js/app.tsx b/resources/js/app.tsx index cde4088..6b92f94 100644 --- a/resources/js/app.tsx +++ b/resources/js/app.tsx @@ -8,7 +8,7 @@ import { ErrorBoundary } from 'react-error-boundary'; import { GA4Provider } from '@/plugins/GA4Context.jsx'; // Updated import import DetailedErrorFallback from './components/custom/detailed-error-fallback'; // Import your component import { Toaster } from './components/ui/sonner'; -import { initializeTheme } from './hooks/use-appearance'; +import { useTheme } from './hooks/useTheme'; import AuthDialog from './modules/auth/AuthDialog'; import { AxiosProvider } from './plugins/AxiosContext'; import { MittProvider } from './plugins/MittContext'; @@ -56,4 +56,4 @@ createInertiaApp({ }, }); -initializeTheme(); +// Theme is now handled by useTheme hook in components diff --git a/resources/js/hooks/useTheme.js b/resources/js/hooks/useTheme.js new file mode 100644 index 0000000..446e03f --- /dev/null +++ b/resources/js/hooks/useTheme.js @@ -0,0 +1,61 @@ +import { useEffect, useState } from 'react'; + +export function useTheme() { + const [theme, setTheme] = useState('system'); + const [isDark, setIsDark] = useState(false); + + useEffect(() => { + // Get theme from session storage or default to system + const savedTheme = sessionStorage.getItem('theme') || 'system'; + setTheme(savedTheme); + + const updateTheme = (themeValue) => { + const root = document.documentElement; + + if (themeValue === 'system') { + const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + setIsDark(systemPrefersDark); + root.classList.toggle('dark', systemPrefersDark); + } else { + const shouldBeDark = themeValue === 'dark'; + setIsDark(shouldBeDark); + root.classList.toggle('dark', shouldBeDark); + } + }; + + // Apply initial theme + updateTheme(savedTheme); + + // Listen for system theme changes when using system theme + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + const handleSystemThemeChange = () => { + if (theme === 'system') { + updateTheme('system'); + } + }; + + mediaQuery.addEventListener('change', handleSystemThemeChange); + + return () => { + mediaQuery.removeEventListener('change', handleSystemThemeChange); + }; + }, [theme]); + + const toggleTheme = () => { + const newTheme = isDark ? 'light' : 'dark'; + setTheme(newTheme); + sessionStorage.setItem('theme', newTheme); + }; + + const resetToSystem = () => { + setTheme('system'); + sessionStorage.removeItem('theme'); + }; + + return { + theme, + isDark, + toggleTheme, + resetToSystem, + }; +} \ No newline at end of file diff --git a/resources/js/pages/home/partials/FAQDiscord.jsx b/resources/js/pages/home/partials/FAQDiscord.jsx index af5fe4c..0d5b1e4 100644 --- a/resources/js/pages/home/partials/FAQDiscord.jsx +++ b/resources/js/pages/home/partials/FAQDiscord.jsx @@ -77,15 +77,17 @@ const FAQDiscord = () => { - - Join Discord - - + {import.meta.env.VITE_DISCORD_LINK && ( + + Join Discord + + + )} diff --git a/resources/js/pages/home/partials/Footer.jsx b/resources/js/pages/home/partials/Footer.jsx index babe455..9ea6535 100644 --- a/resources/js/pages/home/partials/Footer.jsx +++ b/resources/js/pages/home/partials/Footer.jsx @@ -1,5 +1,10 @@ +import { Switch } from '@/components/ui/switch'; +import { useTheme } from '@/hooks/useTheme'; +import { Sun, Moon } from 'lucide-react'; + const Footer = () => { const currentYear = new Date().getFullYear(); + const { isDark, toggleTheme } = useTheme(); return (
@@ -7,7 +12,16 @@ const Footer = () => {
© {currentYear} MEMEFAST. All rights reserved.
-
+
+ {/* Theme Toggle */} +
+ + + +
+ + {/* Navigation Links */} +
Home @@ -17,14 +31,17 @@ const Footer = () => { Privacy - - Discord - + {import.meta.env.VITE_DISCORD_LINK && ( + + Discord + + )} +
diff --git a/resources/js/ziggy.js b/resources/js/ziggy.js index d873d82..b20c2ef 100644 --- a/resources/js/ziggy.js +++ b/resources/js/ziggy.js @@ -1,4 +1,4 @@ -const Ziggy = {"url":"https:\/\/memefast.test","port":null,"defaults":{},"routes":{"cashier.payment":{"uri":"stripe\/payment\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"cashier.webhook":{"uri":"stripe\/webhook","methods":["POST"]},"horizon.stats.index":{"uri":"horizon\/api\/stats","methods":["GET","HEAD"]},"horizon.workload.index":{"uri":"horizon\/api\/workload","methods":["GET","HEAD"]},"horizon.masters.index":{"uri":"horizon\/api\/masters","methods":["GET","HEAD"]},"horizon.monitoring.index":{"uri":"horizon\/api\/monitoring","methods":["GET","HEAD"]},"horizon.monitoring.store":{"uri":"horizon\/api\/monitoring","methods":["POST"]},"horizon.monitoring-tag.paginate":{"uri":"horizon\/api\/monitoring\/{tag}","methods":["GET","HEAD"],"parameters":["tag"]},"horizon.monitoring-tag.destroy":{"uri":"horizon\/api\/monitoring\/{tag}","methods":["DELETE"],"wheres":{"tag":".*"},"parameters":["tag"]},"horizon.jobs-metrics.index":{"uri":"horizon\/api\/metrics\/jobs","methods":["GET","HEAD"]},"horizon.jobs-metrics.show":{"uri":"horizon\/api\/metrics\/jobs\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.queues-metrics.index":{"uri":"horizon\/api\/metrics\/queues","methods":["GET","HEAD"]},"horizon.queues-metrics.show":{"uri":"horizon\/api\/metrics\/queues\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.jobs-batches.index":{"uri":"horizon\/api\/batches","methods":["GET","HEAD"]},"horizon.jobs-batches.show":{"uri":"horizon\/api\/batches\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.jobs-batches.retry":{"uri":"horizon\/api\/batches\/retry\/{id}","methods":["POST"],"parameters":["id"]},"horizon.pending-jobs.index":{"uri":"horizon\/api\/jobs\/pending","methods":["GET","HEAD"]},"horizon.completed-jobs.index":{"uri":"horizon\/api\/jobs\/completed","methods":["GET","HEAD"]},"horizon.silenced-jobs.index":{"uri":"horizon\/api\/jobs\/silenced","methods":["GET","HEAD"]},"horizon.failed-jobs.index":{"uri":"horizon\/api\/jobs\/failed","methods":["GET","HEAD"]},"horizon.failed-jobs.show":{"uri":"horizon\/api\/jobs\/failed\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.retry-jobs.show":{"uri":"horizon\/api\/jobs\/retry\/{id}","methods":["POST"],"parameters":["id"]},"horizon.jobs.show":{"uri":"horizon\/api\/jobs\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.index":{"uri":"horizon\/{view?}","methods":["GET","HEAD"],"wheres":{"view":"(.*)"},"parameters":["view"]},"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"api.pricing_page":{"uri":"api\/pricing","methods":["POST"]},"api.ai_hints":{"uri":"api\/ai-hints","methods":["POST"]},"api.user":{"uri":"api\/user","methods":["POST"]},"api.user.subscribe":{"uri":"api\/user\/subscribe","methods":["POST"]},"api.user.purchase":{"uri":"api\/user\/purchase","methods":["POST"]},"api.user.billing_portal":{"uri":"api\/user\/billing-portal","methods":["POST"]},"api.user.premium_export.request":{"uri":"api\/user\/premium-export\/request","methods":["POST"]},"api.user.premium_export.complete":{"uri":"api\/user\/premium-export\/complete","methods":["POST"]},"api.user.generate_meme":{"uri":"api\/user\/generate_meme","methods":["POST"]},"api.user.check_meme_job_status":{"uri":"api\/user\/generate_meme\/status","methods":["POST"]},"api.user.get_active_job":{"uri":"api\/user\/generate_meme\/active","methods":["POST"]},"api.user.get_meme_history":{"uri":"api\/user\/generate_meme\/history","methods":["POST"]},"api.app.init":{"uri":"api\/app\/init","methods":["POST"]},"api.app.memes":{"uri":"api\/app\/memes","methods":["POST"]},"api.app.background":{"uri":"api\/app\/background","methods":["POST"]},"auth.google.redirect":{"uri":"auth\/google\/redirect","methods":["GET","HEAD"]},"auth.google.callback":{"uri":"auth\/google\/callback","methods":["GET","HEAD"]},"dashboard":{"uri":"dashboard","methods":["GET","HEAD"]},"subscribe.success":{"uri":"subscribe\/success","methods":["GET","HEAD"]},"subscribe.cancelled":{"uri":"subscribe\/cancelled","methods":["GET","HEAD"]},"purchase.success":{"uri":"purchase\/success","methods":["GET","HEAD"]},"purchase.cancelled":{"uri":"purchase\/cancelled","methods":["GET","HEAD"]},"admin.dashboard":{"uri":"admin","methods":["GET","HEAD"]},"admin.background-generation":{"uri":"admin\/background-generation","methods":["GET","HEAD"]},"admin.background-generation.generate":{"uri":"admin\/background-generation\/generate","methods":["POST"]},"admin.background-generation.save":{"uri":"admin\/background-generation\/save","methods":["POST"]},"admin.background-generation.delete":{"uri":"admin\/background-generation\/delete\/{id}","methods":["POST"],"parameters":["id"]},"profile.edit":{"uri":"settings\/profile","methods":["GET","HEAD"]},"profile.update":{"uri":"settings\/profile","methods":["PATCH"]},"profile.destroy":{"uri":"settings\/profile","methods":["DELETE"]},"password.edit":{"uri":"settings\/password","methods":["GET","HEAD"]},"password.update":{"uri":"settings\/password","methods":["PUT"]},"appearance":{"uri":"settings\/appearance","methods":["GET","HEAD"]},"register":{"uri":"register","methods":["GET","HEAD"]},"login":{"uri":"login","methods":["GET","HEAD"]},"password.request":{"uri":"forgot-password","methods":["GET","HEAD"]},"password.email":{"uri":"forgot-password","methods":["POST"]},"password.reset":{"uri":"reset-password\/{token}","methods":["GET","HEAD"],"parameters":["token"]},"password.store":{"uri":"reset-password","methods":["POST"]},"verification.notice":{"uri":"verify-email","methods":["GET","HEAD"]},"verification.verify":{"uri":"verify-email\/{id}\/{hash}","methods":["GET","HEAD"],"parameters":["id","hash"]},"verification.send":{"uri":"email\/verification-notification","methods":["POST"]},"password.confirm":{"uri":"confirm-password","methods":["GET","HEAD"]},"logout":{"uri":"logout","methods":["POST"]},"home":{"uri":"\/","methods":["GET","HEAD"]},"privacy":{"uri":"privacy","methods":["GET","HEAD"]},"terms":{"uri":"terms","methods":["GET","HEAD"]},"storage.local":{"uri":"storage\/{path}","methods":["GET","HEAD"],"wheres":{"path":".*"},"parameters":["path"]}}}; +const Ziggy = {"url":"https:\/\/memefast.test","port":null,"defaults":{},"routes":{"cashier.payment":{"uri":"stripe\/payment\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"cashier.webhook":{"uri":"stripe\/webhook","methods":["POST"]},"horizon.stats.index":{"uri":"horizon\/api\/stats","methods":["GET","HEAD"]},"horizon.workload.index":{"uri":"horizon\/api\/workload","methods":["GET","HEAD"]},"horizon.masters.index":{"uri":"horizon\/api\/masters","methods":["GET","HEAD"]},"horizon.monitoring.index":{"uri":"horizon\/api\/monitoring","methods":["GET","HEAD"]},"horizon.monitoring.store":{"uri":"horizon\/api\/monitoring","methods":["POST"]},"horizon.monitoring-tag.paginate":{"uri":"horizon\/api\/monitoring\/{tag}","methods":["GET","HEAD"],"parameters":["tag"]},"horizon.monitoring-tag.destroy":{"uri":"horizon\/api\/monitoring\/{tag}","methods":["DELETE"],"wheres":{"tag":".*"},"parameters":["tag"]},"horizon.jobs-metrics.index":{"uri":"horizon\/api\/metrics\/jobs","methods":["GET","HEAD"]},"horizon.jobs-metrics.show":{"uri":"horizon\/api\/metrics\/jobs\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.queues-metrics.index":{"uri":"horizon\/api\/metrics\/queues","methods":["GET","HEAD"]},"horizon.queues-metrics.show":{"uri":"horizon\/api\/metrics\/queues\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.jobs-batches.index":{"uri":"horizon\/api\/batches","methods":["GET","HEAD"]},"horizon.jobs-batches.show":{"uri":"horizon\/api\/batches\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.jobs-batches.retry":{"uri":"horizon\/api\/batches\/retry\/{id}","methods":["POST"],"parameters":["id"]},"horizon.pending-jobs.index":{"uri":"horizon\/api\/jobs\/pending","methods":["GET","HEAD"]},"horizon.completed-jobs.index":{"uri":"horizon\/api\/jobs\/completed","methods":["GET","HEAD"]},"horizon.silenced-jobs.index":{"uri":"horizon\/api\/jobs\/silenced","methods":["GET","HEAD"]},"horizon.failed-jobs.index":{"uri":"horizon\/api\/jobs\/failed","methods":["GET","HEAD"]},"horizon.failed-jobs.show":{"uri":"horizon\/api\/jobs\/failed\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.retry-jobs.show":{"uri":"horizon\/api\/jobs\/retry\/{id}","methods":["POST"],"parameters":["id"]},"horizon.jobs.show":{"uri":"horizon\/api\/jobs\/{id}","methods":["GET","HEAD"],"parameters":["id"]},"horizon.index":{"uri":"horizon\/{view?}","methods":["GET","HEAD"],"wheres":{"view":"(.*)"},"parameters":["view"]},"sanctum.csrf-cookie":{"uri":"sanctum\/csrf-cookie","methods":["GET","HEAD"]},"api.pricing_page":{"uri":"api\/pricing","methods":["POST"]},"api.ai_hints":{"uri":"api\/ai-hints","methods":["POST"]},"api.user":{"uri":"api\/user","methods":["POST"]},"api.user.subscribe":{"uri":"api\/user\/subscribe","methods":["POST"]},"api.user.purchase":{"uri":"api\/user\/purchase","methods":["POST"]},"api.user.billing_portal":{"uri":"api\/user\/billing-portal","methods":["POST"]},"api.user.premium_export.request":{"uri":"api\/user\/premium-export\/request","methods":["POST"]},"api.user.premium_export.complete":{"uri":"api\/user\/premium-export\/complete","methods":["POST"]},"api.user.generate_meme":{"uri":"api\/user\/generate_meme","methods":["POST"]},"api.user.check_meme_job_status":{"uri":"api\/user\/generate_meme\/status","methods":["POST"]},"api.user.get_active_job":{"uri":"api\/user\/generate_meme\/active","methods":["POST"]},"api.user.get_meme_history":{"uri":"api\/user\/generate_meme\/history","methods":["POST"]},"api.app.init":{"uri":"api\/app\/init","methods":["POST"]},"api.app.memes":{"uri":"api\/app\/memes","methods":["POST"]},"api.app.search.memes":{"uri":"api\/app\/search\/memes","methods":["POST"]},"api.app.background":{"uri":"api\/app\/background","methods":["POST"]},"api.app.search.background":{"uri":"api\/app\/search\/background","methods":["POST"]},"auth.google.redirect":{"uri":"auth\/google\/redirect","methods":["GET","HEAD"]},"auth.google.callback":{"uri":"auth\/google\/callback","methods":["GET","HEAD"]},"dashboard":{"uri":"dashboard","methods":["GET","HEAD"]},"subscribe.success":{"uri":"subscribe\/success","methods":["GET","HEAD"]},"subscribe.cancelled":{"uri":"subscribe\/cancelled","methods":["GET","HEAD"]},"purchase.success":{"uri":"purchase\/success","methods":["GET","HEAD"]},"purchase.cancelled":{"uri":"purchase\/cancelled","methods":["GET","HEAD"]},"admin.dashboard":{"uri":"admin","methods":["GET","HEAD"]},"admin.background-generation":{"uri":"admin\/background-generation","methods":["GET","HEAD"]},"admin.background-generation.generate":{"uri":"admin\/background-generation\/generate","methods":["POST"]},"admin.background-generation.save":{"uri":"admin\/background-generation\/save","methods":["POST"]},"admin.background-generation.delete":{"uri":"admin\/background-generation\/delete\/{id}","methods":["POST"],"parameters":["id"]},"profile.edit":{"uri":"settings\/profile","methods":["GET","HEAD"]},"profile.update":{"uri":"settings\/profile","methods":["PATCH"]},"profile.destroy":{"uri":"settings\/profile","methods":["DELETE"]},"password.edit":{"uri":"settings\/password","methods":["GET","HEAD"]},"password.update":{"uri":"settings\/password","methods":["PUT"]},"appearance":{"uri":"settings\/appearance","methods":["GET","HEAD"]},"register":{"uri":"register","methods":["GET","HEAD"]},"login":{"uri":"login","methods":["GET","HEAD"]},"password.request":{"uri":"forgot-password","methods":["GET","HEAD"]},"password.email":{"uri":"forgot-password","methods":["POST"]},"password.reset":{"uri":"reset-password\/{token}","methods":["GET","HEAD"],"parameters":["token"]},"password.store":{"uri":"reset-password","methods":["POST"]},"verification.notice":{"uri":"verify-email","methods":["GET","HEAD"]},"verification.verify":{"uri":"verify-email\/{id}\/{hash}","methods":["GET","HEAD"],"parameters":["id","hash"]},"verification.send":{"uri":"email\/verification-notification","methods":["POST"]},"password.confirm":{"uri":"confirm-password","methods":["GET","HEAD"]},"logout":{"uri":"logout","methods":["POST"]},"home":{"uri":"\/","methods":["GET","HEAD"]},"privacy":{"uri":"privacy","methods":["GET","HEAD"]},"terms":{"uri":"terms","methods":["GET","HEAD"]},"storage.local":{"uri":"storage\/{path}","methods":["GET","HEAD"],"wheres":{"path":".*"},"parameters":["path"]}}}; if (typeof window !== 'undefined' && typeof window.Ziggy !== 'undefined') { Object.assign(Ziggy.routes, window.Ziggy.routes); } diff --git a/resources/views/app.blade.php b/resources/views/app.blade.php index 7de8a25..4105488 100644 --- a/resources/views/app.blade.php +++ b/resources/views/app.blade.php @@ -1,21 +1,22 @@ - ($appearance ?? 'system') == 'dark'])> + - {{-- Inline script to detect system dark mode preference and apply it immediately --}} + {{-- Inline script to detect theme preference and apply it immediately to prevent flash --}}