chore: update memory limits in Dockerfile and next.config.ts
All checks were successful
Deploy / deploy (push) Successful in 7m21s
All checks were successful
Deploy / deploy (push) Successful in 7m21s
- Reduced NODE_OPTIONS max-old-space-size from 1536 to 1024 MB in Dockerfile. - Adjusted turbopackMemoryLimit in next.config.ts from 1.5 GB to 1 GB to prevent OOM-kills during build on VPS with limited memory. - Added a search input for filtering Turkish provinces in the SihirbazAdimlar component, improving user experience with real-time search functionality. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
// üniversite tipi sayıları kategori+il'e göre /api/facetler'den tazelenir.
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { ArrowLeft, ArrowRight, X } from "lucide-react";
|
||||
import { ArrowLeft, ArrowRight, Search, X } from "lucide-react";
|
||||
import { useReducedMotion } from "motion/react";
|
||||
import useMeasure from "react-use-measure";
|
||||
import { toast } from "sonner";
|
||||
@@ -27,11 +27,14 @@ export function Cip({
|
||||
secili,
|
||||
onClick,
|
||||
children,
|
||||
kucuk = false,
|
||||
}: {
|
||||
secili: boolean;
|
||||
onClick: () => void;
|
||||
children: React.ReactNode;
|
||||
kucuk?: boolean;
|
||||
}) {
|
||||
const boyut = kucuk ? "px-2.5 py-1 text-xs" : "px-3.5 py-2 text-sm";
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
@@ -39,8 +42,8 @@ export function Cip({
|
||||
aria-pressed={secili}
|
||||
className={
|
||||
secili
|
||||
? "cursor-pointer rounded-full border border-primary bg-primary px-3.5 py-2 text-sm font-medium text-white transition-colors duration-200"
|
||||
: "cursor-pointer rounded-full border border-slate-200 bg-white px-3.5 py-2 text-sm text-slate-700 transition-colors duration-200 hover:border-slate-300 hover:bg-slate-50"
|
||||
? `cursor-pointer rounded-full border border-primary bg-primary font-medium text-white transition-colors duration-200 ${boyut}`
|
||||
: `cursor-pointer rounded-full border border-slate-200 bg-white text-slate-700 transition-colors duration-200 hover:border-slate-300 hover:bg-slate-50 ${boyut}`
|
||||
}
|
||||
>
|
||||
{children}
|
||||
@@ -103,6 +106,26 @@ export function SihirbazAdimlar({
|
||||
() => siraliIller.filter((i) => !HARITA_ILLERI.has(i.il)),
|
||||
[siraliIller],
|
||||
);
|
||||
// İl araması: Türkçe büyük/küçük harf ve şapkalı harf farklarına duyarsız
|
||||
// eşleşme için iki taraf da normalizeIlAdi'dan geçirilir.
|
||||
const [ilArama, setIlArama] = useState("");
|
||||
const ilAramaNorm = normalizeIlAdi(ilArama.trim());
|
||||
const gorunenTurkiyeIlleri = useMemo(
|
||||
() =>
|
||||
ilAramaNorm
|
||||
? turkiyeIlleri.filter((i) =>
|
||||
normalizeIlAdi(i.il).includes(ilAramaNorm),
|
||||
)
|
||||
: turkiyeIlleri,
|
||||
[turkiyeIlleri, ilAramaNorm],
|
||||
);
|
||||
const gorunenDisIller = useMemo(
|
||||
() =>
|
||||
ilAramaNorm
|
||||
? disIller.filter((i) => normalizeIlAdi(i.il).includes(ilAramaNorm))
|
||||
: disIller,
|
||||
[disIller, ilAramaNorm],
|
||||
);
|
||||
const haritaIlleri = useMemo(
|
||||
() => canliFacetler.iller.filter((i) => HARITA_ILLERI.has(i.il)),
|
||||
[canliFacetler.iller],
|
||||
@@ -266,45 +289,79 @@ export function SihirbazAdimlar({
|
||||
En fazla 5 il seçebilirsin. İstersen boş bırak, fark etmez.
|
||||
</p>
|
||||
|
||||
<div className="mt-4 flex items-center gap-2 rounded-full border border-slate-200 bg-white px-3.5 py-2 transition-colors focus-within:border-slate-300">
|
||||
<Search className="size-4 shrink-0 text-slate-400" aria-hidden />
|
||||
<input
|
||||
type="text"
|
||||
value={ilArama}
|
||||
onChange={(e) => setIlArama(e.target.value)}
|
||||
placeholder="İl ara..."
|
||||
aria-label="İl ara"
|
||||
autoComplete="off"
|
||||
className="min-w-0 flex-1 bg-transparent text-sm text-slate-950 outline-none placeholder:text-slate-400"
|
||||
/>
|
||||
{ilArama ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIlArama("")}
|
||||
aria-label="Aramayı temizle"
|
||||
className="flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-full text-slate-400 transition-colors hover:bg-slate-100 hover:text-slate-700"
|
||||
>
|
||||
<X className="size-3.5" aria-hidden />
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{/* Çipler birincil seçim yolu (haritadaki küçük iller mobilde
|
||||
güvenilir dokunma hedefi değil); iller seçili kategorilere göre
|
||||
süzülmüş, program sayısına göre sıralı listelenir. Penceresinde
|
||||
programı olan TÜM iller görünür (kırpma yok). */}
|
||||
programı olan TÜM iller görünür (kırpma yok); arama yalnızca
|
||||
görünümü daraltır, seçimleri etkilemez. */}
|
||||
<div
|
||||
className={`mt-4 flex max-h-56 flex-wrap gap-2 overflow-y-auto sm:max-h-none sm:overflow-visible ${
|
||||
className={`mt-3 flex max-h-56 flex-wrap gap-1.5 overflow-y-auto sm:max-h-none sm:overflow-visible ${
|
||||
facetYukleniyor ? "animate-pulse opacity-60" : ""
|
||||
}`}
|
||||
>
|
||||
{turkiyeIlleri.map((i) => (
|
||||
{gorunenTurkiyeIlleri.map((i) => (
|
||||
<Cip
|
||||
key={i.il}
|
||||
kucuk
|
||||
secili={iller.includes(i.il)}
|
||||
onClick={() => listeDegistir(iller, setIller, i.il, 5)}
|
||||
>
|
||||
{trBaslikDuzeni(i.il)}
|
||||
<span className="ml-1.5 text-xs opacity-70">{i.adet}</span>
|
||||
<span className="ml-1 text-[10px] opacity-70">{i.adet}</span>
|
||||
</Cip>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{disIller.length > 0 ? (
|
||||
{ilAramaNorm &&
|
||||
gorunenTurkiyeIlleri.length === 0 &&
|
||||
gorunenDisIller.length === 0 ? (
|
||||
<p className="mt-3 text-sm text-slate-500">
|
||||
“{ilArama.trim()}” ile eşleşen il yok.
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{gorunenDisIller.length > 0 ? (
|
||||
<div className="mt-4">
|
||||
<p className="mb-2 text-xs font-semibold tracking-wide text-slate-400 uppercase">
|
||||
KKTC & Yurt Dışı
|
||||
</p>
|
||||
<div
|
||||
className={`flex flex-wrap gap-2 ${
|
||||
className={`flex flex-wrap gap-1.5 ${
|
||||
facetYukleniyor ? "animate-pulse opacity-60" : ""
|
||||
}`}
|
||||
>
|
||||
{disIller.map((i) => (
|
||||
{gorunenDisIller.map((i) => (
|
||||
<Cip
|
||||
key={i.il}
|
||||
kucuk
|
||||
secili={iller.includes(i.il)}
|
||||
onClick={() => listeDegistir(iller, setIller, i.il, 5)}
|
||||
>
|
||||
{trBaslikDuzeni(i.il)}
|
||||
<span className="ml-1.5 text-xs opacity-70">{i.adet}</span>
|
||||
<span className="ml-1 text-[10px] opacity-70">{i.adet}</span>
|
||||
</Cip>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user