Add search

This commit is contained in:
Santiago Lo Coco 2023-12-07 14:40:11 -03:00
parent 3faa1cb12f
commit 047e580502
6 changed files with 76 additions and 16 deletions

View File

@ -73,8 +73,8 @@ interface FlightData {
count: number count: number
} }
export const fetchFlights = (origin: string | null, page: number | null): Promise<FlightData> => { export const fetchFlights = (page: number | null, search: string | null): Promise<FlightData> => {
return instance.get("flights" + (origin ? "?origin=" + origin : "") + (page ? "?page=" + page : "")) return instance.get("flights" + (page ? "?page=" + page : "") + (search ? (page ? "&" : "?") + "search=" + search : ""))
}; };
export const createFlight = ( export const createFlight = (

View File

@ -5,6 +5,8 @@ import { Flight } from "../../Types";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import useAuth from "../../useAuth"; import useAuth from "../../useAuth";
import { useFetchSubscriptions } from "../../hooks/useFetchSubscriptions"; import { useFetchSubscriptions } from "../../hooks/useFetchSubscriptions";
import { Button, Input, Space } from "antd";
import { SearchOutlined, CloseCircleOutlined } from '@ant-design/icons';
interface Props { interface Props {
flights?: Flight[]; flights?: Flight[];
@ -12,9 +14,10 @@ interface Props {
export const Home: React.FC<Props> = (props) => { export const Home: React.FC<Props> = (props) => {
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const origin = urlParams.get('origin');
const initialPage = parseInt(urlParams.get('page') || '1', 10); const initialPage = parseInt(urlParams.get('page') || '1', 10);
const { flights, count, error, isLoading, fetchData: refreshFlights } = useFetchFlights(origin, initialPage); const query = urlParams.get('search');
const [searchQuery, setSearchQuery] = useState(query);
const { flights, count, error, isLoading, fetchData: refreshFlights } = useFetchFlights(initialPage, searchQuery);
const navigate = useNavigate() const navigate = useNavigate()
const [currentPage, setCurrentPage] = useState(initialPage); const [currentPage, setCurrentPage] = useState(initialPage);
@ -25,6 +28,9 @@ export const Home: React.FC<Props> = (props) => {
useEffect(() => { useEffect(() => {
const newParams = new URLSearchParams(window.location.search); const newParams = new URLSearchParams(window.location.search);
newParams.set('page', currentPage.toString()); newParams.set('page', currentPage.toString());
if (searchQuery && searchQuery.length != 0) {
newParams.set("search", searchQuery);
}
navigate(`?${newParams.toString()}`); navigate(`?${newParams.toString()}`);
}, [currentPage, navigate]); }, [currentPage, navigate]);
@ -52,6 +58,26 @@ export const Home: React.FC<Props> = (props) => {
return currentPage > 1 ? true : false return currentPage > 1 ? true : false
} }
const handleSearchSubmit = (e: React.FormEvent | undefined) => {
let searchQueryValue = null
if (!!e) {
e.preventDefault();
const formData = new FormData(e.currentTarget as HTMLFormElement);
searchQueryValue = formData.get("searchInput") as string;
}
setSearchQuery(searchQueryValue)
const newParams = new URLSearchParams(window.location.search);
newParams.set('page', "1");
if (searchQueryValue && searchQueryValue.length != 0) {
newParams.set("search", searchQueryValue);
} else {
newParams.delete("search")
}
navigate(`?${newParams.toString()}`);
};
if (loading || isLoading) { if (loading || isLoading) {
return <div>Loading...</div>; return <div>Loading...</div>;
} }
@ -62,8 +88,33 @@ export const Home: React.FC<Props> = (props) => {
<div className="Box"> <div className="Box">
{isAirline ? <button name="CreateFlight" onClick={() => { navigate("/create-flight") }}>Create flight</button> : <></>} {isAirline ? <button name="CreateFlight" onClick={() => { navigate("/create-flight") }}>Create flight</button> : <></>}
{isAdmin ? <button onClick={() => { navigate("/create-airline") }}>Create airline user</button> : <></>} {isAdmin ? <button onClick={() => { navigate("/create-airline") }}>Create airline user</button> : <></>}
<h2>Flights</h2> <form onSubmit={handleSearchSubmit}>
<Space size={8} direction="horizontal">
{/* <h2>Flights</h2> */}
<div style={{ display: 'flex' }}>
<Input
type="text"
placeholder="Enter flight code"
name="searchInput"
defaultValue={searchQuery || ""}
style={{ borderRadius: 0 }}
/>
{searchQuery && (<Button
type="text"
onClick={() => handleSearchSubmit(undefined)}
style={{ border: 'none', backgroundColor: 'transparent', marginRight: '5px' }}
>
<CloseCircleOutlined style={{ color: 'gray' }} />
</Button>
)}
<Button type="primary" style={{ border: 'none', borderRadius: 0 }} htmlType="submit">
<SearchOutlined/>
</Button>
</div>
</Space>
</form>
<div className="Items" style={{ gridTemplateColumns: `repeat(${columns}, minmax(80px, 250px))` }}> <div className="Items" style={{ gridTemplateColumns: `repeat(${columns}, minmax(80px, 250px))` }}>
{flights.length == 0 && <p>No flights found!</p>}
{(props.flights ? props.flights : flights).map((f) => { {(props.flights ? props.flights : flights).map((f) => {
return <Card key={f.id} flight={f} user={user} return <Card key={f.id} flight={f} user={user}
subscribed={subscriptions.some((i => i.flight_id === f.id))} subscribed={subscriptions.some((i => i.flight_id === f.id))}
@ -73,7 +124,7 @@ export const Home: React.FC<Props> = (props) => {
</div> </div>
<div> <div>
{checkMinPage() && <button onClick={goToPrevPage}>Prev</button>} {checkMinPage() && <button onClick={goToPrevPage}>Prev</button>}
<span> Page {currentPage} </span> {flights.length != 0 && <span> Page {currentPage} </span>}
{checkMaxPage() && <button onClick={goToNextPage}>Next</button>} {checkMaxPage() && <button onClick={goToNextPage}>Next</button>}
</div> </div>
</div> </div>

View File

@ -1,9 +1,9 @@
import React, { useCallback, useEffect } from "react"; import { useCallback, useEffect } from "react";
import { useState } from "react"; import { useState } from "react";
import { User, Flight } from "../Types"; import { Flight } from "../Types";
import { fetchFlights } from "../Api"; import { fetchFlights } from "../Api";
export const useFetchFlights = (origin: string | null, page: number | null) => { export const useFetchFlights = (page: number | null, search: string | null) => {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [flights, setFlights] = useState<Flight[]>([]); const [flights, setFlights] = useState<Flight[]>([]);
@ -13,7 +13,7 @@ export const useFetchFlights = (origin: string | null, page: number | null) =>
setError(null); setError(null);
setIsLoading(true) setIsLoading(true)
fetchFlights(origin, page) fetchFlights(page, search)
.then((data) => { .then((data) => {
setCount(data.count) setCount(data.count)
setFlights(data.flights); setFlights(data.flights);
@ -25,7 +25,7 @@ export const useFetchFlights = (origin: string | null, page: number | null) =>
} }
}) })
.finally(() => setIsLoading(false)) .finally(() => setIsLoading(false))
}, [origin, page]); }, [page, search]);
useEffect(() => { useEffect(() => {
fetchData() fetchData()

View File

@ -60,13 +60,16 @@ def get_flight_by_id(db: Session, flight_id: int):
return db.query(Flight).filter(Flight.id == flight_id).first() return db.query(Flight).filter(Flight.id == flight_id).first()
def get_flights(db: Session, deleted, page: int = 1, limit: int = 8): def get_flights(db: Session, deleted, search, page: int = 1, limit: int = 8):
if page <= 0: if page <= 0:
page = 1 page = 1
skip = (page - 1) * limit skip = (page - 1) * limit
condition = Flight.status != "Deleted" if not deleted else True conditions = [
count = db.query(Flight).filter(condition).count() Flight.status != "Deleted" if not deleted else True,
return db.query(Flight).filter(condition).offset(skip).limit(limit).all(), count func.lower(Flight.flight_code).contains(search.lower()) if search else True,
]
count = db.query(Flight).filter(*conditions).count()
return db.query(Flight).filter(*conditions).offset(skip).limit(limit).all(), count
def create_flight(db: Session, flight: FlightPydantic): def create_flight(db: Session, flight: FlightPydantic):

View File

@ -87,6 +87,7 @@ def get_flights(
future: Optional[str] = None, future: Optional[str] = None,
deleted: Optional[str] = None, deleted: Optional[str] = None,
page: Optional[int] = 1, page: Optional[int] = 1,
search: Optional[str] = None,
db: Session = Depends(get_db), db: Session = Depends(get_db),
): ):
if origin and lastUpdated: if origin and lastUpdated:
@ -102,7 +103,9 @@ def get_flights(
db=db, destination=destination, future=future db=db, destination=destination, future=future
) )
else: else:
flights, count = flight_crud.get_flights(db=db, page=page, deleted=deleted) flights, count = flight_crud.get_flights(
db=db, page=page, deleted=deleted, search=search
)
response.headers["X-Count"] = str(count) response.headers["X-Count"] = str(count)
if not flights: if not flights:

View File

@ -71,6 +71,7 @@ async def get_flights(
lastUpdated: Optional[str] = None, lastUpdated: Optional[str] = None,
deleted: Optional[str] = None, deleted: Optional[str] = None,
page: Optional[int] = 1, page: Optional[int] = 1,
search: Optional[str] = None,
future: Optional[str] = None, future: Optional[str] = None,
): ):
query = {} query = {}
@ -84,6 +85,8 @@ async def get_flights(
query["future"] = future query["future"] = future
if deleted: if deleted:
query["deleted"] = deleted query["deleted"] = deleted
if search:
query["search"] = search
if page: if page:
query["page"] = page query["page"] = page
request_id = req.state.request_id request_id = req.state.request_id