Add search
This commit is contained in:
parent
3faa1cb12f
commit
047e580502
browser-domain/src
flights-domain/flights-information/src/api
gateway/src/api/routes
|
@ -73,8 +73,8 @@ interface FlightData {
|
|||
count: number
|
||||
}
|
||||
|
||||
export const fetchFlights = (origin: string | null, page: number | null): Promise<FlightData> => {
|
||||
return instance.get("flights" + (origin ? "?origin=" + origin : "") + (page ? "?page=" + page : ""))
|
||||
export const fetchFlights = (page: number | null, search: string | null): Promise<FlightData> => {
|
||||
return instance.get("flights" + (page ? "?page=" + page : "") + (search ? (page ? "&" : "?") + "search=" + search : ""))
|
||||
};
|
||||
|
||||
export const createFlight = (
|
||||
|
|
|
@ -5,6 +5,8 @@ import { Flight } from "../../Types";
|
|||
import { useNavigate } from "react-router";
|
||||
import useAuth from "../../useAuth";
|
||||
import { useFetchSubscriptions } from "../../hooks/useFetchSubscriptions";
|
||||
import { Button, Input, Space } from "antd";
|
||||
import { SearchOutlined, CloseCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
interface Props {
|
||||
flights?: Flight[];
|
||||
|
@ -12,9 +14,10 @@ interface Props {
|
|||
|
||||
export const Home: React.FC<Props> = (props) => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const origin = urlParams.get('origin');
|
||||
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 [currentPage, setCurrentPage] = useState(initialPage);
|
||||
|
@ -25,6 +28,9 @@ export const Home: React.FC<Props> = (props) => {
|
|||
useEffect(() => {
|
||||
const newParams = new URLSearchParams(window.location.search);
|
||||
newParams.set('page', currentPage.toString());
|
||||
if (searchQuery && searchQuery.length != 0) {
|
||||
newParams.set("search", searchQuery);
|
||||
}
|
||||
navigate(`?${newParams.toString()}`);
|
||||
}, [currentPage, navigate]);
|
||||
|
||||
|
@ -52,6 +58,26 @@ export const Home: React.FC<Props> = (props) => {
|
|||
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) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
@ -62,8 +88,33 @@ export const Home: React.FC<Props> = (props) => {
|
|||
<div className="Box">
|
||||
{isAirline ? <button name="CreateFlight" onClick={() => { navigate("/create-flight") }}>Create flight</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))` }}>
|
||||
{flights.length == 0 && <p>No flights found!</p>}
|
||||
{(props.flights ? props.flights : flights).map((f) => {
|
||||
return <Card key={f.id} flight={f} user={user}
|
||||
subscribed={subscriptions.some((i => i.flight_id === f.id))}
|
||||
|
@ -73,7 +124,7 @@ export const Home: React.FC<Props> = (props) => {
|
|||
</div>
|
||||
<div>
|
||||
{checkMinPage() && <button onClick={goToPrevPage}>Prev</button>}
|
||||
<span> Page {currentPage} </span>
|
||||
{flights.length != 0 && <span> Page {currentPage} </span>}
|
||||
{checkMaxPage() && <button onClick={goToNextPage}>Next</button>}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { useCallback, useEffect } from "react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { useState } from "react";
|
||||
import { User, Flight } from "../Types";
|
||||
import { Flight } from "../Types";
|
||||
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 [error, setError] = useState<string | null>(null);
|
||||
const [flights, setFlights] = useState<Flight[]>([]);
|
||||
|
@ -13,7 +13,7 @@ export const useFetchFlights = (origin: string | null, page: number | null) =>
|
|||
setError(null);
|
||||
setIsLoading(true)
|
||||
|
||||
fetchFlights(origin, page)
|
||||
fetchFlights(page, search)
|
||||
.then((data) => {
|
||||
setCount(data.count)
|
||||
setFlights(data.flights);
|
||||
|
@ -25,7 +25,7 @@ export const useFetchFlights = (origin: string | null, page: number | null) =>
|
|||
}
|
||||
})
|
||||
.finally(() => setIsLoading(false))
|
||||
}, [origin, page]);
|
||||
}, [page, search]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData()
|
||||
|
|
|
@ -60,13 +60,16 @@ def get_flight_by_id(db: Session, flight_id: int):
|
|||
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:
|
||||
page = 1
|
||||
skip = (page - 1) * limit
|
||||
condition = Flight.status != "Deleted" if not deleted else True
|
||||
count = db.query(Flight).filter(condition).count()
|
||||
return db.query(Flight).filter(condition).offset(skip).limit(limit).all(), count
|
||||
conditions = [
|
||||
Flight.status != "Deleted" if not deleted else True,
|
||||
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):
|
||||
|
|
|
@ -87,6 +87,7 @@ def get_flights(
|
|||
future: Optional[str] = None,
|
||||
deleted: Optional[str] = None,
|
||||
page: Optional[int] = 1,
|
||||
search: Optional[str] = None,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
if origin and lastUpdated:
|
||||
|
@ -102,7 +103,9 @@ def get_flights(
|
|||
db=db, destination=destination, future=future
|
||||
)
|
||||
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)
|
||||
|
||||
if not flights:
|
||||
|
|
|
@ -71,6 +71,7 @@ async def get_flights(
|
|||
lastUpdated: Optional[str] = None,
|
||||
deleted: Optional[str] = None,
|
||||
page: Optional[int] = 1,
|
||||
search: Optional[str] = None,
|
||||
future: Optional[str] = None,
|
||||
):
|
||||
query = {}
|
||||
|
@ -84,6 +85,8 @@ async def get_flights(
|
|||
query["future"] = future
|
||||
if deleted:
|
||||
query["deleted"] = deleted
|
||||
if search:
|
||||
query["search"] = search
|
||||
if page:
|
||||
query["page"] = page
|
||||
request_id = req.state.request_id
|
||||
|
|
Loading…
Reference in New Issue