From ce46db7dbef02a1105d48c60b4c8b9497e36f18f Mon Sep 17 00:00:00 2001 From: Tudor Sitaru Date: Tue, 7 Apr 2026 16:17:56 +0100 Subject: [PATCH] shortening placeholder text --- .DS_Store | Bin 8196 -> 8196 bytes nextjs-app/components/FilterBar.tsx | 190 +++++++++++++------- nextjs-app/components/SchoolSearchModal.tsx | 41 +++-- 3 files changed, 148 insertions(+), 83 deletions(-) diff --git a/.DS_Store b/.DS_Store index 91c66eee8571f3ffc985062290c053162f72d23d..680fe1d4d09fea7092b9c069f7192835180598e0 100644 GIT binary patch delta 109 zcmV-z0FwWNK!iY$V*$9aah3;>fDN+;2pk9#xMFZ@X>)WiFxCMA0|W&I2M7q0HV|7Y z2?<{i7<+p$GcYV5F)}xOEFgP1H8Lz9HZd@LeF+E^BQHBrUu$e_Zf}Z{y$~M(i?iJj PDhIO$821FT{uBoTv}zw> delta 110 zcmV-!0FnQMK!iY$V*$Cbah3;>fDN+;2pk9#xngi^X>)WiFxCMA0|W&I2M7m~HV|7Z z2nk;h8GCy)H#saIGBh@QEFgO^GBPtPAT~BJeSHZC6(cV@QeSIqZEkOile`cg0gSWU Q5Gn_=2N?DQv-}hX1Jacrq5uE@ diff --git a/nextjs-app/components/FilterBar.tsx b/nextjs-app/components/FilterBar.tsx index 53e668a..e94c7f0 100644 --- a/nextjs-app/components/FilterBar.tsx +++ b/nextjs-app/components/FilterBar.tsx @@ -1,10 +1,10 @@ -'use client'; +"use client"; -import { useState, useCallback, useTransition, useRef, useEffect } from 'react'; -import { useRouter, useSearchParams, usePathname } from 'next/navigation'; -import { isValidPostcode } from '@/lib/utils'; -import type { Filters, ResultFilters } from '@/lib/types'; -import styles from './FilterBar.module.css'; +import { useState, useCallback, useTransition, useRef, useEffect } from "react"; +import { useRouter, useSearchParams, usePathname } from "next/navigation"; +import { isValidPostcode } from "@/lib/utils"; +import type { Filters, ResultFilters } from "@/lib/types"; +import styles from "./FilterBar.module.css"; interface FilterBarProps { filters: Filters; @@ -19,22 +19,28 @@ export function FilterBar({ filters, isHero, resultFilters }: FilterBarProps) { const [isPending, startTransition] = useTransition(); const inputRef = useRef(null); - const currentSearch = searchParams.get('search') || ''; - const currentPostcode = searchParams.get('postcode') || ''; - const currentRadius = searchParams.get('radius') || '1'; + const currentSearch = searchParams.get("search") || ""; + const currentPostcode = searchParams.get("postcode") || ""; + const currentRadius = searchParams.get("radius") || "1"; const initialOmniValue = currentPostcode || currentSearch; const [omniValue, setOmniValue] = useState(initialOmniValue); - const currentLA = searchParams.get('local_authority') || ''; - const currentType = searchParams.get('school_type') || ''; - const currentPhase = searchParams.get('phase') || ''; - const currentGender = searchParams.get('gender') || ''; - const currentAdmissionsPolicy = searchParams.get('admissions_policy') || ''; - const currentHasSixthForm = searchParams.get('has_sixth_form') || ''; + const currentLA = searchParams.get("local_authority") || ""; + const currentType = searchParams.get("school_type") || ""; + const currentPhase = searchParams.get("phase") || ""; + const currentGender = searchParams.get("gender") || ""; + const currentAdmissionsPolicy = searchParams.get("admissions_policy") || ""; + const currentHasSixthForm = searchParams.get("has_sixth_form") || ""; // Count active dropdown filters (not search/postcode, not phase since it's always visible) - const activeDropdownFilters = [currentLA, currentType, currentGender, currentAdmissionsPolicy, currentHasSixthForm].filter(Boolean); + const activeDropdownFilters = [ + currentLA, + currentType, + currentGender, + currentAdmissionsPolicy, + currentHasSixthForm, + ].filter(Boolean); const hasActiveDropdownFilters = activeDropdownFilters.length > 0; const [filtersOpen, setFiltersOpen] = useState(hasActiveDropdownFilters); @@ -45,47 +51,56 @@ export function FilterBar({ filters, isHero, resultFilters }: FilterBarProps) { useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { - if ((e.key === '/' || (e.key === 'k' && (e.ctrlKey || e.metaKey))) && - document.activeElement?.tagName !== 'INPUT' && - document.activeElement?.tagName !== 'TEXTAREA' && - document.activeElement?.tagName !== 'SELECT') { + if ( + (e.key === "/" || (e.key === "k" && (e.ctrlKey || e.metaKey))) && + document.activeElement?.tagName !== "INPUT" && + document.activeElement?.tagName !== "TEXTAREA" && + document.activeElement?.tagName !== "SELECT" + ) { e.preventDefault(); inputRef.current?.focus(); } }; - document.addEventListener('keydown', handleKeyDown); - return () => document.removeEventListener('keydown', handleKeyDown); + document.addEventListener("keydown", handleKeyDown); + return () => document.removeEventListener("keydown", handleKeyDown); }, []); - const updateURL = useCallback((updates: Record) => { - const params = new URLSearchParams(searchParams); + const updateURL = useCallback( + (updates: Record) => { + const params = new URLSearchParams(searchParams); - Object.entries(updates).forEach(([key, value]) => { - if (value && value !== '') { - params.set(key, value); - } else { - params.delete(key); - } - }); + Object.entries(updates).forEach(([key, value]) => { + if (value && value !== "") { + params.set(key, value); + } else { + params.delete(key); + } + }); - params.delete('page'); + params.delete("page"); - startTransition(() => { - router.push(`${pathname}?${params.toString()}`); - }); - }, [searchParams, pathname, router]); + startTransition(() => { + router.push(`${pathname}?${params.toString()}`); + }); + }, + [searchParams, pathname, router], + ); const handleSearchSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!omniValue.trim()) { - updateURL({ search: '', postcode: '', radius: '' }); + updateURL({ search: "", postcode: "", radius: "" }); return; } if (isValidPostcode(omniValue)) { - updateURL({ postcode: omniValue.trim().toUpperCase(), radius: currentRadius || '1', search: '' }); + updateURL({ + postcode: omniValue.trim().toUpperCase(), + radius: currentRadius || "1", + search: "", + }); } else { - updateURL({ search: omniValue.trim(), postcode: '', radius: '' }); + updateURL({ search: omniValue.trim(), postcode: "", radius: "" }); } }; @@ -94,25 +109,38 @@ export function FilterBar({ filters, isHero, resultFilters }: FilterBarProps) { }; const handleClearFilters = () => { - setOmniValue(''); + setOmniValue(""); startTransition(() => { router.push(pathname); }); }; - const hasActiveFilters = currentSearch || currentLA || currentType || currentPhase || currentPostcode || currentGender || currentAdmissionsPolicy || currentHasSixthForm; + const hasActiveFilters = + currentSearch || + currentLA || + currentType || + currentPhase || + currentPostcode || + currentGender || + currentAdmissionsPolicy || + currentHasSixthForm; // Use result-scoped filter values when available, fall back to global - const laOptions = resultFilters?.local_authorities ?? filters.local_authorities; + const laOptions = + resultFilters?.local_authorities ?? filters.local_authorities; const typeOptions = resultFilters?.school_types ?? filters.school_types; const phaseOptions = resultFilters?.phases ?? filters.phases ?? []; const genderOptions = resultFilters?.genders ?? filters.genders ?? []; - const admissionsPolicyOptions = resultFilters?.admissions_policies ?? filters.admissions_policies ?? []; + const admissionsPolicyOptions = + resultFilters?.admissions_policies ?? filters.admissions_policies ?? []; - const isSecondaryMode = currentPhase === 'secondary' || genderOptions.length > 0; + const isSecondaryMode = + currentPhase === "secondary" || genderOptions.length > 0; return ( -
+
setOmniValue(e.target.value)} - placeholder="Search by school name or postcode (e.g., SW1A 1AA)..." + placeholder="Search by school or postcode ..." className={styles.omniInput} /> -
@@ -137,7 +169,7 @@ export function FilterBar({ filters, isHero, resultFilters }: FilterBarProps) { handleFilterChange('phase', e.target.value)} + onChange={(e) => handleFilterChange("phase", e.target.value)} className={styles.controlSelect} disabled={isPending} > {phaseOptions.map((p) => ( - + ))} )} @@ -166,14 +200,24 @@ export function FilterBar({ filters, isHero, resultFilters }: FilterBarProps) { {hasActiveFilters && ( - )} @@ -183,25 +227,33 @@ export function FilterBar({ filters, isHero, resultFilters }: FilterBarProps) {
@@ -210,20 +262,26 @@ export function FilterBar({ filters, isHero, resultFilters }: FilterBarProps) { {genderOptions.length > 0 && ( )} handleFilterChange('admissions_policy', e.target.value)} + onChange={(e) => + handleFilterChange("admissions_policy", e.target.value) + } className={styles.filterSelect} disabled={isPending} > {admissionsPolicyOptions.map((p) => ( - + ))} )} diff --git a/nextjs-app/components/SchoolSearchModal.tsx b/nextjs-app/components/SchoolSearchModal.tsx index d5d2185..37a03e4 100644 --- a/nextjs-app/components/SchoolSearchModal.tsx +++ b/nextjs-app/components/SchoolSearchModal.tsx @@ -3,15 +3,15 @@ * Modal for searching and adding schools to comparison */ -'use client'; +"use client"; -import { useState, useMemo } from 'react'; -import { Modal } from './Modal'; -import { useComparison } from '@/hooks/useComparison'; -import { debounce } from '@/lib/utils'; -import { fetchSchools } from '@/lib/api'; -import type { School } from '@/lib/types'; -import styles from './SchoolSearchModal.module.css'; +import { useState, useMemo } from "react"; +import { Modal } from "./Modal"; +import { useComparison } from "@/hooks/useComparison"; +import { debounce } from "@/lib/utils"; +import { fetchSchools } from "@/lib/api"; +import type { School } from "@/lib/types"; +import styles from "./SchoolSearchModal.module.css"; interface SchoolSearchModalProps { isOpen: boolean; @@ -20,7 +20,7 @@ interface SchoolSearchModalProps { export function SchoolSearchModal({ isOpen, onClose }: SchoolSearchModalProps) { const { addSchool, selectedSchools, canAddMore } = useComparison(); - const [searchTerm, setSearchTerm] = useState(''); + const [searchTerm, setSearchTerm] = useState(""); const [results, setResults] = useState([]); const [isSearching, setIsSearching] = useState(false); const [hasSearched, setHasSearched] = useState(false); @@ -37,17 +37,20 @@ export function SchoolSearchModal({ isOpen, onClose }: SchoolSearchModalProps) { setIsSearching(true); try { - const data = await fetchSchools({ search: term, page_size: 10 }, { cache: 'no-store' }); + const data = await fetchSchools( + { search: term, page_size: 10 }, + { cache: "no-store" }, + ); setResults(data.schools || []); setHasSearched(true); } catch (error) { - console.error('Search failed:', error); + console.error("Search failed:", error); setResults([]); } finally { setIsSearching(false); } }, 300), - [] + [], ); const handleSearchChange = (value: string) => { @@ -65,7 +68,7 @@ export function SchoolSearchModal({ isOpen, onClose }: SchoolSearchModalProps) { }; const handleClose = () => { - setSearchTerm(''); + setSearchTerm(""); setResults([]); setHasSearched(false); onClose(); @@ -88,7 +91,7 @@ export function SchoolSearchModal({ isOpen, onClose }: SchoolSearchModalProps) { type="text" value={searchTerm} onChange={(e) => handleSearchChange(e.target.value)} - placeholder="Search by school name or location..." + placeholder="Search by school or postcode ..." className={styles.searchInput} autoFocus /> @@ -114,17 +117,17 @@ export function SchoolSearchModal({ isOpen, onClose }: SchoolSearchModalProps) { {school.local_authority && ( {school.local_authority} )} - {school.school_type && ( - {school.school_type} - )} + {school.school_type && {school.school_type}}
);