Faisal Nazik
Faisal Nazik

Reputation: 2863

How to hide header and footer for a specific Route

I have a OrderPrintReceiptScreen, on loading this screen I want the header and footer to not show on the screen. And after that I want to use window.print(); And this way a clean PDF Receipt can be achieved. But due to header and Footer they make it very dense and I'm not sure how to remove that on loading this OrderPrintReceiptScreen.

This is the layout of App

function App() {
  return (
    <Router>
      <Header />
      <main className="py-1">
        <Container>
          //.....
          <Route path="/order-receipt/:id" component={OrderPrintReceiptScreen} />
          //.....
        </Container>
      </main>
      <Footer />
    </Router>
  );
}

export default App;

OrderPrintReceiptScreen.js

import React, { useEffect } from "react";
import { Button, Row, Col, ListGroup } from "react-bootstrap";
import { Page, Text, View, Document, StyleSheet } from "@react-pdf/renderer";
import { LinkContainer } from "react-router-bootstrap";

import { useDispatch, useSelector } from "react-redux";

import Message from "../components/Message";
import Loader from "../components/Loader";
import {
  getOrderDetails,
  // payOrder,
} from "../actions/orderActions";

import {
  ORDER_PAY_RESET,
  ORDER_DELIVER_RESET,
} from "../constants/orderConstants";

// Create styles
const styles = StyleSheet.create({
  page: {
    flexDirection: "row",
    backgroundColor: "#E4E4E4",
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1,
  },
});
function OrderPrintReceiptScreen({ match, history }) {
  const orderId = match.params.id;
  const dispatch = useDispatch();

  const orderDetails = useSelector((state) => state.orderDetails);
  const { order, error, loading } = orderDetails;

  const orderPay = useSelector((state) => state.orderPay);
  const { loading: loadingPay, success: successPay } = orderPay;

  const orderDeliver = useSelector((state) => state.orderDeliver);
  const { loading: loadingDeliver, success: successDeliver } = orderDeliver;

  const userLogin = useSelector((state) => state.userLogin);
  const { userInfo } = userLogin;

  if (!loading && !error) {
    order.itemsPrice = order.orderItems
      .reduce((acc, item) => acc + item.price * item.qty, 0)
      .toFixed(2);
  }

  useEffect(() => {
    if (!userInfo) {
      history.push("/login");
    }

    if (
      !order ||
      successPay ||
      order._id !== Number(orderId) ||
      successDeliver
    ) {
      dispatch({ type: ORDER_PAY_RESET });
      dispatch({ type: ORDER_DELIVER_RESET });

      dispatch(getOrderDetails(orderId));
    }
  }, [dispatch, order, orderId, successPay, successDeliver]);

  const printReceipt = (e) => {
    e.preventDefault();
    window.print();
  };

  return loading ? (
    <Loader />
  ) : error ? (
    <Message variant="danger">{error}</Message>
  ) : (
    <Page size="A4" style={styles.page}>
      <View style={styles.section}>
        <Text>Section #1</Text>
      </View>
      <View style={styles.section}>
        <Text>Section #2</Text>
      </View>
      <Row>
        <Col md={10}>
          <ListGroup variant="flush">
            <ListGroup.Item>
              <LinkContainer to={`/order-receipt/${order._id}`}>
                <Button
                  variant="outline-success"
                  className="mx-4 my-4 btn-lg"
                  fluid
                  onClick={printReceipt}
                >
                  Download Receipt
                </Button>
              </LinkContainer>
            </ListGroup.Item>

            <ListGroup.Item>Order ID : {order._id}</ListGroup.Item>
            <ListGroup.Item>
              Created On : {order.createdAt.substring(0, 10)},{" "}
              {order.createdAt.substring(11, 19)}
            </ListGroup.Item>
            <ListGroup.Item>
              Order Items:
              {order.orderItems.length === 0 ? (
                <Message variant="info">Order is empty</Message>
              ) : (
                <ListGroup flush>
                  {order.orderItems.map((item, index) => (
                    <ListGroup.Item key={index}>
                      <Row>
                        <Col>{item.name}</Col>
                      </Row>
                    </ListGroup.Item>
                  ))}
                </ListGroup>
              )}
            </ListGroup.Item>

            <ListGroup variant="flush">
              <ListGroup.Item>Name : {order.user.name}</ListGroup.Item>
              <ListGroup.Item>
                Phone Number : {order.shippingAddress.phoneNumber}
              </ListGroup.Item>
              <ListGroup.Item>
                Shipping Address : {order.shippingAddress.address},{" "}
                {order.shippingAddress.city}
                {"  "}
                {order.shippingAddress.postalCode},{"  "}
                {order.shippingAddress.country}
              </ListGroup.Item>

              {order.isPaid ? (
                <Message variant="light">
                  Payment Status : Paid On {order.paidAt.substring(0, 10)},{" "}
                  {order.paidAt.substring(11, 19)}
                </Message>
              ) : (
                <Message variant="warning">Not Paid</Message>
              )}
              <ListGroup variant="flush">
                <ListGroup.Item>Payment Summary : </ListGroup.Item>

                <ListGroup.Item>
                  <Row>
                    <Col>Items Price :</Col>
                    <Col>PKR {order.itemsPrice}</Col>
                  </Row>
                </ListGroup.Item>

                <ListGroup.Item>
                  <Row>
                    <Col>Shipping Price :</Col>
                    <Col>PKR {order.shippingPrice}</Col>
                  </Row>
                </ListGroup.Item>

                <ListGroup.Item>
                  <Row>
                    <Col>Tax Amount :</Col>
                    <Col>PKR {order.taxPrice}</Col>
                  </Row>
                </ListGroup.Item>

                <ListGroup.Item>
                  <Row>
                    <Col>Total Payable :</Col>
                    <Col> PKR {order.totalPrice}</Col>
                  </Row>
                </ListGroup.Item>
                <ListGroup.Item>
                  <Row>
                    <Col>Total Paid :</Col>
                    <Col> PKR {order.totalPricePaid}</Col>
                  </Row>
                </ListGroup.Item>
                <ListGroup.Item>
                  <Row>
                    <Col>Remaining Amount:</Col>
                    <Col>
                      {" "}
                      PKR {Number(order.totalPrice) - order.totalPricePaid}
                    </Col>
                  </Row>
                </ListGroup.Item>
              </ListGroup>

              {order.isDelivered ? (
                <Message variant="light">
                  Delivery Status : Delivered on{" "}
                  {order.deliveredAt.substring(0, 10)},{" "}
                  {order.deliveredAt.substring(11, 19)}
                </Message>
              ) : (
                <Message variant="warning">Not Delivered</Message>
              )}
            </ListGroup>
          </ListGroup>
        </Col>

        {/* <Col md={4}>
          
        </Col> */}
      </Row>
    </Page>
  );
}

export default OrderPrintReceiptScreen;

Upvotes: 1

Views: 2702

Answers (4)

abhishek_maran
abhishek_maran

Reputation: 19

You can use useLocation from react-router-dom in the header and footer components of the web app.

Take a look at the code below:

import { useLocation } from 'react-router-dom';

function Header() {
    const location = useLocation();
    const hideHeaderForPaths = ['/pathname1','/pathname2'];

    if(hideHeaderForPaths.includes(location.pathname)) {
       return <></>;
    }

    return (
      // Header JSX code...
    )
}

You can use a similar approach for the footer component as well.

Upvotes: 0

Abd Abughazaleh
Abd Abughazaleh

Reputation: 5495

You can use the window.location.pathname to get the current route after that do the validation on the route if the same hide the header else show the header.

{
       window.location.pathname!=="/login"? <Header/> : null
    }

Upvotes: 2

Sanat Gupta
Sanat Gupta

Reputation: 1154

You need to create a component Like a layout inside layout you can manage conditional header and footer Like this example.

Remove the Header footer from the App file.

Have a look I hope it's helpful

const OrderPrintReceiptScreen= (props) => {
  return (
    <Layouts
      showFooter={false}
      showHeader={false}
    >
      <Childeren {...props} />
    </Layouts>
  );
};

const Layouts= ({showFooter,showHeader,children}) =>{
   return (
           {showHeader && <Header/>}
           {children}
           {showFooter && <Footer/>}
    )
}

........

Upvotes: 1

Ryan Le
Ryan Le

Reputation: 8412

There are 2 ways to do this:


The first method is to check your matching URL before rendering:
render() {
  const {match: {url}} = this.props;

  if(url.startWith('/ignore-header-path') {
    return null;
  } else {
    // your render jsx
  }
}

The second method is to use @media print:

@media print { 
 /* Your print styles */
 .header, .footer { display: none !important; } 
}

Upvotes: 1

Related Questions