Skip to content

Commit

Permalink
Merge pull request #872 from boxwise/feature/add_breadcrumb_to_transfers
Browse files Browse the repository at this point in the history
Add Breadcrumbs and menus transfer views
  • Loading branch information
HaGuesto authored Jul 31, 2023
2 parents ef1b1c4 + 68d530f commit b686058
Show file tree
Hide file tree
Showing 37 changed files with 312 additions and 243 deletions.
3 changes: 1 addition & 2 deletions react/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ coverage
node_modules
# temporarily disable eslint on the current code
src/types
src/components/BTBreadcrumbNavigation.tsx
src/components/HeaderMenu
!src/components/HeaderMenu/HeaderMenuDeskop.tsx
!src/components/HeaderMenu/HeaderMenuDesktop.tsx
!src/components/HeaderMenu/HeaderMenuMobile.tsx
!src/components/HeaderMenu/HeaderMenuContainer.tsx
!src/components/QrReader
Expand Down
3 changes: 1 addition & 2 deletions react/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ coverage
node_modules
# temporarily disable eslint on the current code
src/types
src/components/BTBreadcrumbNavigation.tsx
src/components/HeaderMenu
!src/components/HeaderMenu/HeaderMenuDeskop.tsx
!src/components/HeaderMenu/HeaderMenuDesktop.tsx
!src/components/HeaderMenu/HeaderMenuMobile.tsx
!src/components/HeaderMenu/HeaderMenuContainer.tsx
!src/components/QrReader
Expand Down
33 changes: 0 additions & 33 deletions react/src/components/BTBreadcrumbNavigation.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ it("4.7.1 - Query for shipment, box, available products, sizes and locations is
globalPreferences: {
dispatch: jest.fn(),
globalPreferences: {
selectedOrganisationId: organisation1.id,
organisation: { id: organisation1.id, name: organisation1.name },
availableBases: organisation1.bases,
selectedBaseId: organisation1.bases[0].id,
selectedBase: organisation1.bases[0],
},
},
});
Expand Down Expand Up @@ -131,9 +131,9 @@ it("4.7.2 - Query for shipment, box, available products, sizes and locations ret
globalPreferences: {
dispatch: jest.fn(),
globalPreferences: {
selectedOrganisationId: organisation1.id,
organisation: { id: organisation1.id, name: organisation1.name },
availableBases: organisation1.bases,
selectedBaseId: organisation1.bases[0].id,
selectedBase: organisation1.bases[0],
},
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function BoxReconciliationOverlay({
const { createToast } = useNotification();
const { triggerError } = useErrorHandling();
const { globalPreferences } = useContext(GlobalPreferencesContext);
const baseId = globalPreferences.selectedBaseId;
const baseId = globalPreferences.selectedBase?.id;
const boxReconciliationOverlayState = useReactiveVar(boxReconciliationOverlayVar);
const navigate = useNavigate();

Expand Down
60 changes: 60 additions & 0 deletions react/src/components/BreadcrumbNavigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useContext } from "react";
import { GlobalPreferencesContext } from "providers/GlobalPreferencesProvider";
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, Button } from "@chakra-ui/react";
import { ChevronLeftIcon, ChevronRightIcon } from "@chakra-ui/icons";
import { Link } from "react-router-dom";

interface IBreadcrumbItemData {
label: string;
// eslint-disable-next-line react/require-default-props
linkPath?: string;
}

interface IBreadcrumbNavigationProps {
items: IBreadcrumbItemData[];
}

export function MobileBreadcrumbButton({ label, linkPath }: IBreadcrumbItemData) {
return (
<Button
variant="outline"
color="black"
borderColor="black"
as={Link}
to={linkPath ?? "#"}
border="2px"
borderRadius={0}
mb={4}
leftIcon={<ChevronLeftIcon />}
>
{label}
</Button>
);
}

export function BreadcrumbNavigation({ items }: IBreadcrumbNavigationProps) {
const { globalPreferences } = useContext(GlobalPreferencesContext);
const orgName = globalPreferences.organisation?.name;
const baseName = globalPreferences.selectedBase?.name;
return (
<Breadcrumb separator={<ChevronRightIcon />} fontSize="md" mb={4}>
<BreadcrumbItem>
<BreadcrumbLink as={Link} to="#">
{orgName}
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbItem>
<BreadcrumbLink as={Link} to="#">
{baseName}
</BreadcrumbLink>
</BreadcrumbItem>
{items.map((item) => (
<BreadcrumbItem key={`breadcrumb${item.label}`}>
<BreadcrumbLink as={Link} to={item.linkPath ?? "#"}>
{item.label}
</BreadcrumbLink>
</BreadcrumbItem>
))}
</Breadcrumb>
);
}
4 changes: 2 additions & 2 deletions react/src/components/HeaderMenu/HeaderMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LayoutProps, useMediaQuery } from "@chakra-ui/react";
import HeaderMenuDeskop from "./HeaderMenuDeskop";
import HeaderMenuDesktop from "./HeaderMenuDesktop";
import HeaderMenuMobile from "./HeaderMenuMobile";

export interface MenuItemData {
Expand Down Expand Up @@ -51,7 +51,7 @@ const HeaderMenu = (props: HeaderMenuProps) => {
if (isSmallScreen) {
return <HeaderMenuMobile {...props} />;
} else {
return <HeaderMenuDeskop {...props} />;
return <HeaderMenuDesktop {...props} />;
}
};
export default HeaderMenu;
15 changes: 14 additions & 1 deletion react/src/components/HeaderMenu/HeaderMenuContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useReactiveVar } from "@apollo/client";
const HeaderMenuContainer = () => {
const auth0 = useAuth0();
const { globalPreferences } = useContext(GlobalPreferencesContext);
const baseId = globalPreferences.selectedBaseId!;
const baseId = globalPreferences.selectedBase?.id!;
const qrReaderOverlayState = useReactiveVar(qrReaderOverlayVar);

const menuItems: MenuItemsGroupData[] = useMemo(
Expand All @@ -27,6 +27,19 @@ const HeaderMenuContainer = () => {
},
],
},
{
text: "Transfers",
links: [
{
link: "/transfers/shipments",
name: "Manage Shipments",
},
{
link: "/transfers/agreements",
name: "Manage Agreements",
},
],
},
// {
// text: "Boxes",
// links: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const MenuItemsGroupDesktop = ({ ...props }: MenuItemsGroupProps) => {
const { globalPreferences } = useContext(GlobalPreferencesContext);

function renderMenuItem(link: MenuItemData, i: number) {
const baseId = globalPreferences.selectedBaseId;
const baseId = globalPreferences.selectedBase?.id;
let { qrCode, labelIdentifier } = useParams();

if (link.link.includes(`${process.env.REACT_APP_OLD_APP_BASE_URL}`)) {
Expand Down Expand Up @@ -183,7 +183,7 @@ const HeaderMenuDesktopContainer = ({ children, ...props }) => {
);
};

const HeaderMenuDeskop = (props: HeaderMenuProps) => {
const HeaderMenuDesktop = (props: HeaderMenuProps) => {
return (
<HeaderMenuDesktopContainer>
<Flex w="100%" justifyContent="space-between" alignItems="center">
Expand All @@ -205,4 +205,4 @@ const HeaderMenuDeskop = (props: HeaderMenuProps) => {
);
};

export default HeaderMenuDeskop;
export default HeaderMenuDesktop;
2 changes: 1 addition & 1 deletion react/src/components/HeaderMenu/HeaderMenuMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ const MenuItemsGroupMobile = ({
const { isOpen, onToggle } = useDisclosure();

function renderLinkBoxes(link: MenuItemData, i: number) {
const baseId = globalPreferences.selectedBaseId;
const baseId = globalPreferences.selectedBase?.id;
let { qrCode, labelIdentifier } = useParams();

if (link.link.includes(`${process.env.REACT_APP_OLD_APP_BASE_URL}`)) {
Expand Down
2 changes: 1 addition & 1 deletion react/src/components/QrReader/QrReaderContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ interface IQrReaderContainerProps {

function QrReaderContainer({ onSuccess }: IQrReaderContainerProps) {
const { globalPreferences } = useContext(GlobalPreferencesContext);
const baseId = globalPreferences.selectedBaseId;
const baseId = globalPreferences.selectedBase?.id;
const navigate = useNavigate();
const { triggerError } = useErrorHandling();
const { resolveQrCode } = useQrResolver();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ interface IQrReaderMultiBoxContainerProps {
function QrReaderMultiBoxContainer({ onSuccess }: IQrReaderMultiBoxContainerProps) {
const navigate = useNavigate();
const { globalPreferences } = useContext(GlobalPreferencesContext);
const currentBaseId = globalPreferences.selectedBaseId;
const currentBaseId = globalPreferences.selectedBase?.id;
// selected radio button
const [multiBoxAction, setMultiBoxAction] = useState<IMultiBoxAction>(IMultiBoxAction.moveBox);

Expand Down
4 changes: 2 additions & 2 deletions react/src/hooks/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface INotificationProps extends UseToastOptions {

export const useGetUrlForResourceHelpers = () => {
const { globalPreferences } = useContext(GlobalPreferencesContext);
const baseId = globalPreferences.selectedBaseId;
const baseId = globalPreferences.selectedBase?.id;
if (baseId == null) {
throw new Error("Could not extract baseId from URL");
}
Expand Down Expand Up @@ -47,7 +47,7 @@ export const useToggle = (initialValue = false) => {

export const useGlobalSiteState = () => {
const { globalPreferences } = useContext(GlobalPreferencesContext);
const currentBaseId = globalPreferences.selectedBaseId!;
const currentBaseId = globalPreferences.selectedBase?.id!;
const navigate = useNavigate();

return {
Expand Down
59 changes: 31 additions & 28 deletions react/src/hooks/useLoadAndSetGlobalPreferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { gql, useLazyQuery } from "@apollo/client";
import { useLocation, useNavigate } from "react-router-dom";
import { GlobalPreferencesContext } from "providers/GlobalPreferencesProvider";
import { ApolloAuth0WrapperContext } from "providers/ApolloAuth0Provider";
import { BasesQuery } from "types/generated/graphql";
import { OrganisationAndBasesQuery } from "types/generated/graphql";

export const useLoadAndSetGlobalPreferences = () => {
const { user } = useAuth0();
Expand All @@ -14,40 +14,42 @@ export const useLoadAndSetGlobalPreferences = () => {
const { isAccessTokenInHeader } = useContext(ApolloAuth0WrapperContext);
const [error, setError] = useState<string>();

// set organisation id
useEffect(() => {
if (user) {
const organisationId = user["https://www.boxtribute.com/organisation_id"];
dispatch({
type: "setOrganisationId",
payload: organisationId,
});
}
}, [dispatch, user]);

// load available bases
const BASES_QUERY = gql`
query Bases {
const ORGANISATION_AND_BASES_QUERY = gql`
query OrganisationAndBases($organisationId: ID!) {
bases {
id
name
}
organisation(id: $organisationId) {
id
name
}
}
`;
const [runBaseQuery, { loading: isBasesQueryLoading, data }] =
useLazyQuery<BasesQuery>(BASES_QUERY);
const [runOrganisationAndBasesQuery, { loading: isOrganisationAndBasesQueryLoading, data }] =
useLazyQuery<OrganisationAndBasesQuery>(ORGANISATION_AND_BASES_QUERY);

useEffect(() => {
// run query only if the access token is in the request header from the apollo client
if (isAccessTokenInHeader) {
runBaseQuery();
if (isAccessTokenInHeader && user) {
runOrganisationAndBasesQuery({
variables: { organisationId: user["https://www.boxtribute.com/organisation_id"] },
});
}
}, [runBaseQuery, globalPreferences.availableBases, isAccessTokenInHeader]);
}, [runOrganisationAndBasesQuery, globalPreferences.availableBases, isAccessTokenInHeader, user]);

// set available bases
useEffect(() => {
if (!isBasesQueryLoading && data != null) {
const { bases } = data;
if (!isOrganisationAndBasesQueryLoading && data != null) {
const { bases, organisation } = data;
if (organisation) {
dispatch({
type: "setOrganisation",
payload: organisation,
});
}

if (bases.length > 0) {
dispatch({
type: "setAvailableBases",
Expand All @@ -58,11 +60,12 @@ export const useLoadAndSetGlobalPreferences = () => {
const baseId = location.pathname.match(/\/bases\/(\d+)(\/)?/);
// validate if requested base is in the array of available bases
if (baseId != null) {
if (bases.some((base) => base.id === baseId[1])) {
const matchingBase = bases.find((base) => base.id === baseId[1]);
if (matchingBase) {
// set selected base
dispatch({
type: "setSelectedBaseId",
payload: baseId[1],
type: "setSelectedBase",
payload: matchingBase,
});
} else {
// this error is set if the requested base is not part of the available bases
Expand All @@ -71,7 +74,7 @@ export const useLoadAndSetGlobalPreferences = () => {
} else {
// handle the case if the url does not start with "/bases/<number>"
// prepend /bases/<newBaseId>
const newBaseId = globalPreferences?.selectedBaseId ?? bases[0].id;
const newBaseId = globalPreferences?.selectedBase?.id ?? bases[0].id;
navigate(`/bases/${newBaseId}${location.pathname}`);
}
} else {
Expand All @@ -81,14 +84,14 @@ export const useLoadAndSetGlobalPreferences = () => {
}
}, [
data,
isBasesQueryLoading,
isOrganisationAndBasesQueryLoading,
dispatch,
location.pathname,
globalPreferences?.selectedBaseId,
globalPreferences?.selectedBase?.id,
navigate,
]);

const isLoading = !globalPreferences.availableBases || !globalPreferences.selectedBaseId;
const isLoading = !globalPreferences.availableBases || !globalPreferences.selectedBase?.id;

return { isLoading, error };
};
Loading

0 comments on commit b686058

Please sign in to comment.