fix(sase): search form not submitting — React form action → onSubmit

Both the VIN list and the user list used the React 19 server-action-
style <form action={fn}> pattern with a client function. In production
that didn't actually navigate — form submitted with no URL change, the
table stayed unfiltered.

Switch to plain onSubmit + controlled input (useState for the query
text). Clears now also resets the input value, not just the URL.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Semih
2026-05-19 08:14:37 +03:00
parent 39c26bd4d4
commit 931bcda35d
2 changed files with 35 additions and 21 deletions

View File

@@ -1,7 +1,7 @@
"use client";
import { useRouter, useSearchParams, usePathname } from "next/navigation";
import { useTransition } from "react";
import { useState, useTransition } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
@@ -29,6 +29,7 @@ export function UsersFilterBar({
const pathname = usePathname();
const sp = useSearchParams();
const [pending, startTransition] = useTransition();
const [query, setQuery] = useState(initial.q ?? "");
const current: UsersSearchParams = {
q: sp.get("q") ?? undefined,
@@ -47,6 +48,12 @@ export function UsersFilterBar({
startTransition(() => router.push(href));
}
function submitSearch(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const q = query.trim();
nav({ q: q || undefined });
}
function isPlanActive(id: string) {
const v = current.plan;
if (!v) return false;
@@ -65,16 +72,11 @@ export function UsersFilterBar({
return (
<div className="space-y-3 rounded-md border p-3">
<form
action={(fd) => {
const q = String(fd.get("q") ?? "").trim();
nav({ q: q || undefined });
}}
className="flex items-center gap-2"
>
<form onSubmit={submitSearch} className="flex items-center gap-2">
<Input
name="q"
defaultValue={initial.q ?? ""}
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Email, isim veya user ID ile ara…"
className="max-w-md"
/>
@@ -86,7 +88,10 @@ export function UsersFilterBar({
type="button"
variant="ghost"
size="sm"
onClick={() => router.push(pathname)}
onClick={() => {
setQuery("");
router.push(pathname);
}}
>
Temizle
</Button>

View File

@@ -1,7 +1,7 @@
"use client";
import { useRouter, useSearchParams, usePathname } from "next/navigation";
import { useTransition } from "react";
import { useState, useTransition } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
@@ -23,6 +23,7 @@ export function VinsFilterBar({ initial }: { initial: VinsSearchParams }) {
const pathname = usePathname();
const sp = useSearchParams();
const [pending, startTransition] = useTransition();
const [query, setQuery] = useState(initial.q ?? "");
const current: VinsSearchParams = {
q: sp.get("q") ?? undefined,
@@ -38,6 +39,12 @@ export function VinsFilterBar({ initial }: { initial: VinsSearchParams }) {
startTransition(() => router.push(href));
}
function submitSearch(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const q = query.trim();
nav({ q: q || undefined });
}
function isProviderActive(p: string) {
const v = current.provider;
if (!v) return false;
@@ -46,28 +53,30 @@ export function VinsFilterBar({ initial }: { initial: VinsSearchParams }) {
return (
<div className="space-y-3 rounded-md border p-3">
<form
action={(fd) => {
const q = String(fd.get("q") ?? "").trim();
nav({ q: q || undefined });
}}
className="flex items-center gap-2"
>
<form onSubmit={submitSearch} className="flex items-center gap-2">
<Input
name="q"
defaultValue={initial.q ?? ""}
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="VIN veya email ile ara…"
className="max-w-md"
/>
<Button type="submit" disabled={pending} size="sm">
Ara
</Button>
{Object.values(current).some((v) => v !== undefined && v !== "") && (
{(current.q ||
current.provider ||
current.success ||
current.from ||
current.to) && (
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => router.push(pathname)}
onClick={() => {
setQuery("");
router.push(pathname);
}}
>
Temizle
</Button>