Add search
This commit is contained in:
parent
3faa1cb12f
commit
047e580502
|
@ -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 = (
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue