Skip to content
Open
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
81 changes: 81 additions & 0 deletions resources/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,89 @@
'Noto Color Emoji';
}

@custom-variant dark (&:where(.dark, .dark *));

@layer base {
body {
font-stretch: 96%;
@apply transition-colors duration-300;
}
}

.dark .bg-red-50 {
background-color: rgb(239 68 68 / 0.1);
}
.dark .bg-red-100 {
background-color: rgb(239 68 68 / 0.15);
}
.dark .text-red-600 {
color: rgb(248 113 113);
}
.dark .text-red-700 {
color: rgb(252 165 165);
}

.dark .bg-blue-50 {
background-color: rgb(59 130 246 / 0.1);
}
.dark .bg-blue-100 {
background-color: rgb(59 130 246 / 0.15);
}
.dark .text-blue-600 {
color: rgb(96 165 250);
}
.dark .text-blue-700 {
color: rgb(147 197 253);
}

.dark .bg-purple-50 {
background-color: rgb(168 85 247 / 0.1);
}
.dark .bg-purple-100 {
background-color: rgb(168 85 247 / 0.15);
}
.dark .text-purple-600 {
color: rgb(192 132 252);
}
.dark .text-purple-700 {
color: rgb(216 180 254);
}

.dark .bg-emerald-50 {
background-color: rgb(16 185 129 / 0.1);
}
.dark .bg-emerald-100 {
background-color: rgb(16 185 129 / 0.15);
}
.dark .text-emerald-600 {
color: rgb(52 211 153);
}
.dark .text-emerald-700 {
color: rgb(110 231 183);
}

.dark .bg-amber-50 {
background-color: rgb(245 158 11 / 0.1);
}
.dark .bg-amber-100 {
background-color: rgb(245 158 11 / 0.15);
}
.dark .text-amber-600 {
color: rgb(251 191 36);
}
.dark .text-amber-700 {
color: rgb(252 211 77);
}

.dark .bg-green-50 {
background-color: rgb(34 197 94 / 0.1);
}
.dark .bg-green-100 {
background-color: rgb(34 197 94 / 0.15);
}
.dark .text-green-600 {
color: rgb(74 222 128);
}
.dark .text-green-700 {
color: rgb(134 239 172);
}
11 changes: 11 additions & 0 deletions resources/js/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ import AppLayout from './layouts/AppLayout.vue';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

// Apply dark mode before paint to prevent flash
const stored = localStorage.getItem('theme');

if (
stored === 'dark' ||
(stored !== 'light' &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.classList.add('dark');
}

registerSW({ immediate: true });

createInertiaApp({
Expand Down
10 changes: 5 additions & 5 deletions resources/js/components/AIBanner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { Sparkles, ArrowRight } from 'lucide-vue-next';
<template>
<Link
href="/ai"
class="group relative mb-6 flex items-center justify-between gap-3 overflow-hidden rounded-2xl border border-indigo-100/80 bg-gradient-to-r from-indigo-50/90 via-violet-50/40 to-fuchsia-50/30 p-3.5 shadow-xs transition-all duration-300 hover:border-indigo-300 hover:shadow-md sm:p-4"
class="group relative mb-6 flex items-center justify-between gap-3 overflow-hidden rounded-2xl border border-indigo-100/80 bg-gradient-to-r from-indigo-50/90 via-violet-50/40 to-fuchsia-50/30 p-3.5 shadow-xs transition-all duration-300 hover:border-indigo-300 hover:shadow-md sm:p-4 dark:border-indigo-500/20 dark:from-indigo-500/5 dark:via-violet-500/5 dark:to-fuchsia-500/5 dark:hover:border-indigo-500/40"
>
<!-- Background Ambient Glow -->
<div
class="pointer-events-none absolute -top-8 -right-8 h-28 w-28 rounded-full bg-indigo-500/10 blur-xl transition-all duration-300 group-hover:scale-125 sm:-top-10 sm:-right-10 sm:h-32 sm:w-32 sm:blur-2xl"
class="pointer-events-none absolute -top-8 -right-8 h-28 w-28 rounded-full bg-indigo-500/10 blur-xl transition-all duration-300 group-hover:scale-125 sm:-top-10 sm:-right-10 sm:h-32 sm:w-32 sm:blur-2xl dark:bg-indigo-500/5"
></div>

<!-- Left Content Section -->
Expand All @@ -26,12 +26,12 @@ import { Sparkles, ArrowRight } from 'lucide-vue-next';
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-1.5 sm:gap-2">
<span
class="text-sm leading-tight font-extrabold text-slate-900"
class="text-sm leading-tight font-extrabold text-slate-900 dark:text-gray-100"
>HSCStack AI</span
>
</div>
<p
class="mt-0.5 truncate text-[11px] font-medium text-slate-600 sm:text-xs sm:whitespace-normal"
class="mt-0.5 truncate text-[11px] font-medium text-slate-600 sm:text-xs sm:whitespace-normal dark:text-gray-400"
>
বিষয় ও অধ্যায় সিলেক্ট করে সরাসরি প্রশ্ন ও গাণিতিক সমস্যা
সলভ করুন।
Expand All @@ -41,7 +41,7 @@ import { Sparkles, ArrowRight } from 'lucide-vue-next';

<!-- Right Action Arrow (Visible on Mobile & Desktop) -->
<div
class="relative z-10 flex shrink-0 items-center gap-1 text-xs font-bold text-indigo-600"
class="relative z-10 flex shrink-0 items-center gap-1 text-xs font-bold text-indigo-600 dark:text-indigo-400"
>
<span class="hidden sm:inline">এক্সপ্লোর করুন</span>
<ArrowRight
Expand Down
17 changes: 12 additions & 5 deletions resources/js/components/AppLogo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,32 @@ const isSsc = computed(() => page.url.startsWith('/ssc'));
<template>
<Link href="/" class="flex items-center gap-2.5">
<div
class="flex h-8 w-8 items-center justify-center overflow-hidden rounded-lg bg-slate-900 shadow-sm"
class="flex h-8 w-8 items-center justify-center overflow-hidden rounded-lg bg-slate-900 shadow-sm dark:bg-gray-100"
>
<img
src="/favicon.svg"
alt="HSCStack"
class="h-6 w-6 scale-110 object-cover"
class="h-6 w-6 scale-120 object-cover"
/>
</div>

<div class="flex items-center gap-1.5">
<span class="text-lg font-extrabold tracking-tight text-slate-900">
HSC<span :class="isSsc ? 'text-emerald-600' : 'text-indigo-600'"
<span
class="text-lg font-extrabold tracking-tight text-slate-900 dark:text-gray-100"
>
HSC<span
:class="
isSsc
? 'text-emerald-600 dark:text-emerald-400'
: 'text-indigo-600 dark:text-indigo-400'
"
>Stack</span
>
</span>

<span
v-if="isSsc"
class="rounded border border-emerald-200 bg-emerald-100 px-1.5 py-0.5 text-[10px] font-black tracking-wider text-emerald-700 uppercase"
class="rounded border border-emerald-200 bg-emerald-100 px-1.5 py-0.5 text-[10px] font-black tracking-wider text-emerald-700 uppercase dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-400"
>
SSC
</span>
Expand Down
28 changes: 17 additions & 11 deletions resources/js/components/BlogCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ const formattedDate = computed(() => {

<template>
<div
class="group flex flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-xs transition-all duration-300 hover:-translate-y-0.5 hover:shadow-md"
class="group flex flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-xs transition-all duration-300 hover:-translate-y-0.5 hover:shadow-md dark:border-gray-700 dark:bg-gray-900 dark:hover:shadow-gray-900/50"
>
<!-- Featured Image Container -->
<Link
:href="'/blogs/' + blog.slug"
class="relative block aspect-[16/9] overflow-hidden bg-slate-100"
class="relative block aspect-[16/9] overflow-hidden bg-slate-100 dark:bg-gray-800"
>
<img
:src="blog.featured_image || 'https://placehold.co/600x400'"
Expand All @@ -53,22 +53,26 @@ const formattedDate = computed(() => {
<div class="flex flex-1 flex-col p-4">
<!-- News Meta (Author & Date) -->
<div
class="mb-1.5 flex items-center gap-1.5 text-xs text-slate-500"
class="mb-1.5 flex items-center gap-1.5 text-xs text-slate-500 dark:text-gray-400"
>
<span class="text-slate-400">Author</span>
<span class="text-slate-400 dark:text-gray-500">Author</span>
<Link
:href="`/about-us#${blog.user?.id}`"
class="font-medium text-indigo-600 underline transition-colors hover:underline"
class="font-medium text-indigo-600 underline transition-colors hover:underline dark:text-indigo-400"
>
{{ blog.user?.name }}
</Link>

<span v-if="formattedDate" class="text-slate-300">•</span>
<span
v-if="formattedDate"
class="text-slate-300 dark:text-gray-600"
>•</span
>

<time
v-if="formattedDate"
:datetime="blog.created_at"
class="text-slate-400"
class="text-slate-400 dark:text-gray-500"
>
{{ formattedDate }}
</time>
Expand All @@ -77,24 +81,26 @@ const formattedDate = computed(() => {
<!-- Title -->
<Link :href="'/blogs/' + blog.slug" class="group/title block">
<h3
class="line-clamp-2 text-base leading-snug font-bold text-slate-900 transition duration-150 group-hover/title:text-indigo-600"
class="line-clamp-2 text-base leading-snug font-bold text-slate-900 transition duration-150 group-hover/title:text-indigo-600 dark:text-gray-100 dark:group-hover/title:text-indigo-400"
>
{{ blog.title }}
</h3>
</Link>

<!-- Excerpt -->
<p
class="mt-1.5 mb-3 line-clamp-2 text-xs leading-relaxed text-slate-600"
class="mt-1.5 mb-3 line-clamp-2 text-xs leading-relaxed text-slate-600 dark:text-gray-400"
>
{{ blog.excerpt }}
</p>

<!-- Footer Action -->
<div class="mt-auto border-t border-slate-100 pt-3">
<div
class="mt-auto border-t border-slate-100 pt-3 dark:border-gray-800"
>
<Link
:href="'/blogs/' + blog.slug"
class="inline-flex items-center gap-1 text-xs font-semibold text-indigo-600 transition hover:text-indigo-700"
class="inline-flex items-center gap-1 text-xs font-semibold text-indigo-600 transition hover:text-indigo-700 dark:text-indigo-400 dark:hover:text-indigo-300"
>
<span>বিস্তারিত পড়ুন</span>
<ArrowRight
Expand Down
22 changes: 12 additions & 10 deletions resources/js/components/BlogRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ const deleteBlog = () => {

<template>
<div
class="group relative flex items-center justify-between gap-3 rounded-xl border border-gray-100 bg-white p-3.5 transition-colors duration-150 hover:border-blue-200"
class="group relative flex items-center justify-between gap-3 rounded-xl border border-gray-100 bg-white p-3.5 transition-colors duration-150 hover:border-blue-200 dark:border-gray-700 dark:bg-gray-900 dark:hover:border-blue-500/30"
>
<Link
:href="`/admin/blogs/edit/${blog.slug}`"
class="flex min-w-0 flex-1 items-center gap-3 active:scale-[0.99]"
>
<div
class="h-12 w-12 shrink-0 overflow-hidden rounded-lg border border-gray-100 bg-gray-50"
class="h-12 w-12 shrink-0 overflow-hidden rounded-lg border border-gray-100 bg-gray-50 dark:border-gray-700 dark:bg-gray-800"
>
<img
v-if="blog.featured_image"
Expand All @@ -33,34 +33,36 @@ const deleteBlog = () => {
/>
<div
v-else
class="flex h-full w-full items-center justify-center text-xs font-bold text-gray-400 uppercase"
class="flex h-full w-full items-center justify-center text-xs font-bold text-gray-400 uppercase dark:text-gray-500"
>
TXT
</div>
</div>

<div class="min-w-0 flex-1">
<h4 class="truncate text-sm font-semibold text-gray-900">
<h4
class="truncate text-sm font-semibold text-gray-900 dark:text-gray-100"
>
{{ blog.title }}
</h4>

<div
class="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-gray-500"
class="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-gray-500 dark:text-gray-400"
>
<span>{{ blog.views }} views</span>
<span>•</span>
<span
:class="
blog.is_published
? 'text-green-600'
: 'text-gray-400'
? 'text-green-600 dark:text-green-400'
: 'text-gray-400 dark:text-gray-500'
"
>
{{ blog.is_published ? 'Published' : 'Draft' }}
</span>
<span
v-if="blog.is_featured"
class="rounded bg-amber-50 px-1.5 py-0.5 text-[10px] font-bold tracking-wider text-amber-700 uppercase"
class="rounded bg-amber-50 px-1.5 py-0.5 text-[10px] font-bold tracking-wider text-amber-700 uppercase dark:bg-amber-500/10 dark:text-amber-400"
>
Featured
</span>
Expand All @@ -72,7 +74,7 @@ const deleteBlog = () => {
<button
@click.stop.prevent="deleteBlog"
type="button"
class="rounded-lg p-1.5 text-gray-400 transition-colors hover:bg-red-50 hover:text-red-600"
class="rounded-lg p-1.5 text-gray-400 transition-colors hover:bg-red-50 hover:text-red-600 dark:text-gray-500 dark:hover:bg-red-500/10 dark:hover:text-red-400"
title="Delete blog"
>
<svg
Expand All @@ -91,7 +93,7 @@ const deleteBlog = () => {
</svg>
</button>

<span class="text-lg text-gray-300">→</span>
<span class="text-lg text-gray-300 dark:text-gray-600">→</span>
</div>
</div>
</template>
12 changes: 6 additions & 6 deletions resources/js/components/BreadcrumbNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ const breadcrumbs = computed(() => {

<template>
<nav
class="no-scrollbar mb-6 flex items-center space-x-2 overflow-x-auto text-xs font-semibold tracking-wider whitespace-nowrap text-slate-400 uppercase"
class="no-scrollbar mb-6 flex items-center space-x-2 overflow-x-auto text-xs font-semibold tracking-wider whitespace-nowrap text-slate-400 uppercase dark:text-gray-500"
>
<Link
href="/"
class="mr-0.5 flex items-center rounded-lg p-1 transition-colors hover:bg-slate-100/80 hover:text-indigo-600"
class="mr-0.5 flex items-center rounded-lg p-1 transition-colors hover:bg-slate-100/80 hover:text-indigo-600 dark:hover:bg-gray-800 dark:hover:text-indigo-400"
>
<Home class="h-4 w-4 stroke-[2.2]" />
</Link>

<ChevronRight
class="h-3.5 w-3.5 shrink-0 stroke-[2.5] text-slate-300"
class="h-3.5 w-3.5 shrink-0 stroke-[2.5] text-slate-300 dark:text-gray-600"
/>

<Link
:href="`/${props.subject?.slug || ''}`"
class="px-1 whitespace-nowrap transition-colors hover:text-indigo-600"
class="px-1 whitespace-nowrap transition-colors hover:text-indigo-600 dark:hover:text-indigo-400"
>
{{ props.subject?.name }}
</Link>
Expand All @@ -50,12 +50,12 @@ const breadcrumbs = computed(() => {
:key="`${crumb.name}-${index}`"
>
<ChevronRight
class="h-3.5 w-3.5 shrink-0 stroke-[2.5] text-slate-300"
class="h-3.5 w-3.5 shrink-0 stroke-[2.5] text-slate-300 dark:text-gray-600"
/>

<Link
:href="crumb.link"
class="px-1 whitespace-nowrap transition-colors hover:text-indigo-600"
class="px-1 whitespace-nowrap transition-colors hover:text-indigo-600 dark:hover:text-indigo-400"
>
{{ crumb.name }}
</Link>
Expand Down
Loading