Added schedule load to daily veiw with additional CSS fixes. BOD-319

This commit is contained in:
Patrick Fic
2020-08-27 14:30:07 -07:00
parent 3150fdaade
commit 661241091a
8 changed files with 291 additions and 319 deletions

View File

@@ -13,7 +13,7 @@ import Icon, {
UnorderedListOutlined, UnorderedListOutlined,
UserOutlined, UserOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { Avatar, Layout, Menu } from "antd"; import { Avatar, Menu } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { BsKanban } from "react-icons/bs"; import { BsKanban } from "react-icons/bs";
@@ -29,16 +29,12 @@ import { createStructuredSelector } from "reselect";
import { selectRecentItems } from "../../redux/application/application.selectors"; import { selectRecentItems } from "../../redux/application/application.selectors";
import { setModalContext } from "../../redux/modals/modals.actions"; import { setModalContext } from "../../redux/modals/modals.actions";
import { signOutStart } from "../../redux/user/user.actions"; import { signOutStart } from "../../redux/user/user.actions";
import { import { selectCurrentUser } from "../../redux/user/user.selectors";
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import GlobalSearch from "../global-search/global-search.component"; import GlobalSearch from "../global-search/global-search.component";
import "./header.styles.scss"; import "./header.styles.scss";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser, currentUser: selectCurrentUser,
bodyshop: selectBodyshop,
recentItems: selectRecentItems, recentItems: selectRecentItems,
}); });
@@ -53,7 +49,6 @@ const mapDispatchToProps = (dispatch) => ({
}); });
function Header({ function Header({
bodyshop,
handleMenuClick, handleMenuClick,
currentUser, currentUser,
signOutStart, signOutStart,
@@ -63,281 +58,276 @@ function Header({
recentItems, recentItems,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { Header } = Layout;
return ( return (
<Header> <Menu
<Menu mode="horizontal"
mode="horizontal" theme="dark"
theme="dark" className="header-main-menu"
className="header-main-menu" selectedKeys={["home"]}
selectedKeys={["home"]} onClick={handleMenuClick}
onClick={handleMenuClick} >
<Menu.Item key="home">
<Link to="/manage">
<HomeFilled />
{t("menus.header.home")}
</Link>
</Menu.Item>
<Menu.Item key="schedule">
<Link to="/manage/schedule">
<Icon component={FaCalendarAlt} />
{t("menus.header.schedule")}
</Link>
</Menu.Item>
<Menu.SubMenu
title={
<span>
<Icon component={FaCarCrash} />
<span>{t("menus.header.jobs")}</span>
</span>
}
> >
<Menu.Item key="home"> <Menu.Item key="activejobs">
<Link to="/manage"> <FileFilled />
<HomeFilled /> <Link to="/manage/jobs">{t("menus.header.activejobs")}</Link>
{t("menus.header.home")} </Menu.Item>
<Menu.Item key="availablejobs">
<Link to="/manage/available">
<ImportOutlined /> {t("menus.header.availablejobs")}
</Link> </Link>
</Menu.Item> </Menu.Item>
<Menu.Item key="schedule"> <Menu.Divider />
<Link to="/manage/schedule"> <Menu.Item key="alljobs">
<Icon component={FaCalendarAlt} /> <UnorderedListOutlined />
{t("menus.header.schedule")} <Link to="/manage/jobs/all">{t("menus.header.alljobs")}</Link>
</Menu.Item>
<Menu.Divider />
<Menu.Item key="productionlist">
<Link to="/manage/production/list">
<ScheduleOutlined />
{t("menus.header.productionlist")}
</Link> </Link>
</Menu.Item> </Menu.Item>
<Menu.SubMenu <Menu.Item key="productionboard">
title={ <Link to="/manage/production/board">
<span> <Icon component={BsKanban} />
<Icon component={FaCarCrash} /> {t("menus.header.productionboard")}
<span>{t("menus.header.jobs")}</span> </Link>
</span> </Menu.Item>
} <Menu.Divider />
>
<Menu.Item key="activejobs"> <Menu.Item key="scoreboard">
<LineChartOutlined />
<Link to="/manage/scoreboard">{t("menus.header.scoreboard")}</Link>
</Menu.Item>
</Menu.SubMenu>
<Menu.SubMenu
title={
<span>
<UserOutlined />
<span>{t("menus.header.customers")}</span>
</span>
}
>
<Menu.Item key="owners">
<Link to="/manage/owners">
<TeamOutlined />
{t("menus.header.owners")}
</Link>
</Menu.Item>
<Menu.Item key="vehicles">
<Link to="/manage/vehicles">
<CarFilled />
{t("menus.header.vehicles")}
</Link>
</Menu.Item>
</Menu.SubMenu>
<Menu.SubMenu
title={
<span>
<CarFilled />
<span>{t("menus.header.courtesycars")}</span>
</span>
}
>
<Menu.Item key="courtesycarsall">
<Link to="/manage/courtesycars">
<CarFilled />
{t("menus.header.courtesycars-all")}
</Link>
</Menu.Item>
<Menu.Item key="contracts">
<Link to="/manage/courtesycars/contracts">
<FileFilled /> <FileFilled />
<Link to="/manage/jobs">{t("menus.header.activejobs")}</Link> {t("menus.header.courtesycars-contracts")}
</Menu.Item> </Link>
<Menu.Item key="availablejobs">
<Link to="/manage/available">
<ImportOutlined /> {t("menus.header.availablejobs")}
</Link>
</Menu.Item>
<Menu.Divider />
<Menu.Item key="alljobs">
<UnorderedListOutlined />
<Link to="/manage/jobs/all">{t("menus.header.alljobs")}</Link>
</Menu.Item>
<Menu.Divider />
<Menu.Item key="productionlist">
<Link to="/manage/production/list">
<ScheduleOutlined />
{t("menus.header.productionlist")}
</Link>
</Menu.Item>
<Menu.Item key="productionboard">
<Link to="/manage/production/board">
<Icon component={BsKanban} />
{t("menus.header.productionboard")}
</Link>
</Menu.Item>
<Menu.Divider />
<Menu.Item key="scoreboard">
<LineChartOutlined />
<Link to="/manage/scoreboard">{t("menus.header.scoreboard")}</Link>
</Menu.Item>
</Menu.SubMenu>
<Menu.SubMenu
title={
<span>
<UserOutlined />
<span>{t("menus.header.customers")}</span>
</span>
}
>
<Menu.Item key="owners">
<Link to="/manage/owners">
<TeamOutlined />
{t("menus.header.owners")}
</Link>
</Menu.Item>
<Menu.Item key="vehicles">
<Link to="/manage/vehicles">
<CarFilled />
{t("menus.header.vehicles")}
</Link>
</Menu.Item>
</Menu.SubMenu>
<Menu.SubMenu
title={
<span>
<CarFilled />
<span>{t("menus.header.courtesycars")}</span>
</span>
}
>
<Menu.Item key="courtesycarsall">
<Link to="/manage/courtesycars">
<CarFilled />
{t("menus.header.courtesycars-all")}
</Link>
</Menu.Item>
<Menu.Item key="contracts">
<Link to="/manage/courtesycars/contracts">
<FileFilled />
{t("menus.header.courtesycars-contracts")}
</Link>
</Menu.Item>
<Menu.Item key="newcontract">
<Link to="/manage/courtesycars/contracts/new">
<FileAddFilled />
{t("menus.header.courtesycars-newcontract")}
</Link>
</Menu.Item>
</Menu.SubMenu>
<Menu.SubMenu
title={
<span>
<DollarCircleFilled />
<span>{t("menus.header.accounting")}</span>
</span>
}
>
<Menu.Item key="invoices">
<Link to="/manage/invoices">{t("menus.header.invoices")}</Link>
</Menu.Item>
<Menu.Item
key="enterinvoices"
onClick={() => {
setInvoiceEnterContext({
actions: {},
context: {},
});
}}
>
<Icon component={FaFileInvoiceDollar} />
{t("menus.header.enterinvoices")}
</Menu.Item>
<Menu.Divider />
<Menu.Item key="allpayments">
<Link to="/manage/payments">{t("menus.header.allpayments")}</Link>
</Menu.Item>
<Menu.Item
key="enterpayments"
onClick={() => {
setPaymentContext({
actions: {},
context: {},
});
}}
>
<Icon component={FaCreditCard} />
{t("menus.header.enterpayment")}
</Menu.Item>
<Menu.Divider />
<Menu.Item key="timetickets">
<Link to="/manage/timetickets">
{t("menus.header.timetickets")}
</Link>
</Menu.Item>
<Menu.Item
key="entertimetickets"
onClick={() => {
setTimeTicketContext({
actions: {},
context: {},
});
}}
>
{t("menus.header.entertimeticket")}
</Menu.Item>
<Menu.Divider />
<Menu.SubMenu title={t("menus.header.export")}>
<Menu.Item key="receivables">
<Link to="/manage/accounting/receivables">
{t("menus.header.accounting-receivables")}
</Link>
</Menu.Item>
<Menu.Item key="payables">
<Link to="/manage/accounting/payables">
{t("menus.header.accounting-payables")}
</Link>
</Menu.Item>
<Menu.Item key="payments">
<Link to="/manage/accounting/payments">
{t("menus.header.accounting-payments")}
</Link>
</Menu.Item>
</Menu.SubMenu>
</Menu.SubMenu>
<Menu.SubMenu title={t("menus.header.shop")}>
<Menu.Item key="shop">
<Link to="/manage/shop">{t("menus.header.shop_config")}</Link>
</Menu.Item>
<Menu.Item key="shop-templates">
<Link to="/manage/shop/templates">
{t("menus.header.shop_templates")}
</Link>
</Menu.Item>
<Menu.Item key="shop-vendors">
<Link to="/manage/shop/vendors">
{t("menus.header.shop_vendors")}
</Link>
</Menu.Item>
<Menu.Item key="shop-csi">
<Link to="/manage/shop/csi">{t("menus.header.shop_csi")}</Link>
</Menu.Item>
</Menu.SubMenu>
<Menu.Item>
<GlobalSearch />
</Menu.Item> </Menu.Item>
<Menu.SubMenu title={<ClockCircleFilled />}> <Menu.Item key="newcontract">
{recentItems.map((i, idx) => ( <Link to="/manage/courtesycars/contracts/new">
<Menu.Item key={idx}> <FileAddFilled />
<Link to={i.url}>{i.label}</Link> {t("menus.header.courtesycars-newcontract")}
</Menu.Item> </Link>
))} </Menu.Item>
</Menu.SubMenu>
<Menu.SubMenu
title={
<span>
<DollarCircleFilled />
<span>{t("menus.header.accounting")}</span>
</span>
}
>
<Menu.Item key="invoices">
<Link to="/manage/invoices">{t("menus.header.invoices")}</Link>
</Menu.Item>
<Menu.Item
key="enterinvoices"
onClick={() => {
setInvoiceEnterContext({
actions: {},
context: {},
});
}}
>
<Icon component={FaFileInvoiceDollar} />
{t("menus.header.enterinvoices")}
</Menu.Item>
<Menu.Divider />
<Menu.Item key="allpayments">
<Link to="/manage/payments">{t("menus.header.allpayments")}</Link>
</Menu.Item>
<Menu.Item
key="enterpayments"
onClick={() => {
setPaymentContext({
actions: {},
context: {},
});
}}
>
<Icon component={FaCreditCard} />
{t("menus.header.enterpayment")}
</Menu.Item>
<Menu.Divider />
<Menu.Item key="timetickets">
<Link to="/manage/timetickets">{t("menus.header.timetickets")}</Link>
</Menu.Item>
<Menu.Item
key="entertimetickets"
onClick={() => {
setTimeTicketContext({
actions: {},
context: {},
});
}}
>
{t("menus.header.entertimeticket")}
</Menu.Item>
<Menu.Divider />
<Menu.SubMenu title={t("menus.header.export")}>
<Menu.Item key="receivables">
<Link to="/manage/accounting/receivables">
{t("menus.header.accounting-receivables")}
</Link>
</Menu.Item>
<Menu.Item key="payables">
<Link to="/manage/accounting/payables">
{t("menus.header.accounting-payables")}
</Link>
</Menu.Item>
<Menu.Item key="payments">
<Link to="/manage/accounting/payments">
{t("menus.header.accounting-payments")}
</Link>
</Menu.Item>
</Menu.SubMenu> </Menu.SubMenu>
</Menu.SubMenu>
<Menu.SubMenu title={t("menus.header.shop")}>
<Menu.Item key="shop">
<Link to="/manage/shop">{t("menus.header.shop_config")}</Link>
</Menu.Item>
<Menu.Item key="shop-templates">
<Link to="/manage/shop/templates">
{t("menus.header.shop_templates")}
</Link>
</Menu.Item>
<Menu.Item key="shop-vendors">
<Link to="/manage/shop/vendors">
{t("menus.header.shop_vendors")}
</Link>
</Menu.Item>
<Menu.Item key="shop-csi">
<Link to="/manage/shop/csi">{t("menus.header.shop_csi")}</Link>
</Menu.Item>
</Menu.SubMenu>
<Menu.Item>
<GlobalSearch />
</Menu.Item>
<Menu.SubMenu title={<ClockCircleFilled />}>
{recentItems.map((i, idx) => (
<Menu.Item key={idx}>
<Link to={i.url}>{i.label}</Link>
</Menu.Item>
))}
</Menu.SubMenu>
<Menu.SubMenu
title={
<div>
{currentUser.photoURL ? (
<Avatar
src={currentUser.photoURL}
style={{
margin: "10px",
}}
/>
) : (
<Avatar
style={{
backgroundColor: "#87d068",
margin: "10px",
}}
icon={<UserOutlined />}
/>
)}
{currentUser.displayName || t("general.labels.unknown")}
</div>
}
>
<Menu.Item danger onClick={() => signOutStart()}>
{t("user.actions.signout")}
</Menu.Item>
<Menu.Item key="shiftclock">
<Link to="/manage/shiftclock">{t("menus.header.shiftclock")}</Link>
</Menu.Item>
<Menu.Item>
<Link to="/manage/profile">{t("menus.currentuser.profile")}</Link>
</Menu.Item>
<Menu.SubMenu <Menu.SubMenu
title={ title={
<div> <span>
{currentUser.photoURL ? ( <GlobalOutlined />
<Avatar <span>{t("menus.currentuser.languageselector")}</span>
src={currentUser.photoURL} </span>
style={{
margin: "10px",
}}
/>
) : (
<Avatar
style={{
backgroundColor: "#87d068",
margin: "10px",
}}
icon={<UserOutlined />}
/>
)}
{currentUser.displayName || t("general.labels.unknown")}
</div>
} }
> >
<Menu.Item danger onClick={() => signOutStart()}> <Menu.Item actiontype="lang-select" key="en-US">
{t("user.actions.signout")} {t("general.languages.english")}
</Menu.Item> </Menu.Item>
<Menu.Item key="shiftclock"> <Menu.Item actiontype="lang-select" key="fr-CA">
<Link to="/manage/shiftclock">{t("menus.header.shiftclock")}</Link> {t("general.languages.french")}
</Menu.Item> </Menu.Item>
<Menu.Item> <Menu.Item actiontype="lang-select" key="es-MX">
<Link to="/manage/profile">{t("menus.currentuser.profile")}</Link> {t("general.languages.spanish")}
</Menu.Item> </Menu.Item>
<Menu.SubMenu
title={
<span>
<GlobalOutlined />
<span>{t("menus.currentuser.languageselector")}</span>
</span>
}
>
<Menu.Item actiontype="lang-select" key="en-US">
{t("general.languages.english")}
</Menu.Item>
<Menu.Item actiontype="lang-select" key="fr-CA">
{t("general.languages.french")}
</Menu.Item>
<Menu.Item actiontype="lang-select" key="es-MX">
{t("general.languages.spanish")}
</Menu.Item>
</Menu.SubMenu>
</Menu.SubMenu> </Menu.SubMenu>
</Menu> </Menu.SubMenu>
</Header> </Menu>
); );
} }

View File

@@ -100,14 +100,17 @@ export function ScheduleCalendarHeaderComponent({
</div> </div>
</Popover> </Popover>
) : null; ) : null;
console.log("loadData", loadData);
return ( return (
<ScheduleBlockDay date={date} refetch={refetch}> <div className="imex-calendar-load">
<div> <ScheduleBlockDay date={date} refetch={refetch}>
{label} <div>
{calculating ? <LoadingSkeleton /> : LoadComponent} {label}
</div> {calculating ? <LoadingSkeleton /> : LoadComponent}
</ScheduleBlockDay> </div>
</ScheduleBlockDay>
</div>
); );
} }
export default connect( export default connect(

View File

@@ -1,8 +1,10 @@
@import "react-big-calendar/lib/sass/styles"; @import "react-big-calendar/lib/sass/styles";
.rbc-time-view .rbc-row { .rbc-time-header-cell-single-day {
box-sizing: unset !important; display: unset;
min-height: unset !important; }
.rbc-time-view .rbc-allday-cell {
height: unset;
} }
.imex-event-arrived { .imex-event-arrived {
@@ -20,3 +22,9 @@
.rbc-event.rbc-selected { .rbc-event.rbc-selected {
background-color: slategrey; background-color: slategrey;
} }
.imex-calendar-load {
max-width: 12rem;
position: relative;
left: 50%;
transform: translateX(-50%);
}

View File

@@ -1,25 +1,11 @@
import { SyncOutlined } from "@ant-design/icons"; import { SyncOutlined } from "@ant-design/icons";
import { Button } from "antd"; import { Button } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { setModalContext } from "../../redux/modals/modals.actions";
import ScheduleCalendarWrapperComponent from "../schedule-calendar-wrapper/scheduler-calendar-wrapper.component"; import ScheduleCalendarWrapperComponent from "../schedule-calendar-wrapper/scheduler-calendar-wrapper.component";
import ScheduleModal from "../schedule-job-modal/schedule-job-modal.container"; import ScheduleModal from "../schedule-job-modal/schedule-job-modal.container";
import ScheduleProductionList from "../schedule-production-list/schedule-production-list.component"; import ScheduleProductionList from "../schedule-production-list/schedule-production-list.component";
const mapDispatchToProps = (dispatch) => ({ export default function ScheduleCalendarComponent({ data, refetch }) {
setScheduleContext: (context) =>
dispatch(setModalContext({ context: context, modal: "schedule" })),
});
export function ScheduleCalendarComponent({
data,
refetch,
setScheduleContext,
}) {
const { t } = useTranslation();
return ( return (
<div> <div>
<div className="imex-flex-row"> <div className="imex-flex-row">
@@ -32,19 +18,6 @@ export function ScheduleCalendarComponent({
<SyncOutlined /> <SyncOutlined />
</Button> </Button>
<Button
className="imex-flex-row__margin"
onClick={() => {
setScheduleContext({
actions: { refetch: refetch },
context: {
jobId: null,
},
});
}}
>
{t("appointments.actions.new")}
</Button>
<ScheduleProductionList /> <ScheduleProductionList />
</div> </div>
@@ -54,4 +27,3 @@ export function ScheduleCalendarComponent({
</div> </div>
); );
} }
export default connect(null, mapDispatchToProps)(ScheduleCalendarComponent);

View File

@@ -1,16 +1,16 @@
import { Button, Checkbox, Col, Row } from "antd"; import { Button, Checkbox, Col, Row } from "antd";
import axios from "axios"; import axios from "axios";
import moment from "moment";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { auth } from "../../firebase/firebase.utils";
import { DateFormatter } from "../../utils/DateFormatter"; import { DateFormatter } from "../../utils/DateFormatter";
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
import EmailInput from "../form-items-formatted/email-form-item.component"; import EmailInput from "../form-items-formatted/email-form-item.component";
import ScheduleDayViewContainer from "../schedule-day-view/schedule-day-view.container"; import ScheduleDayViewContainer from "../schedule-day-view/schedule-day-view.container";
import ScheduleExistingAppointmentsList from "../schedule-existing-appointments-list/schedule-existing-appointments-list.component"; import ScheduleExistingAppointmentsList from "../schedule-existing-appointments-list/schedule-existing-appointments-list.component";
import moment from "moment";
export default function ScheduleJobModalComponent({ export default function ScheduleJobModalComponent({
jobId,
existingAppointments, existingAppointments,
appData, appData,
setAppData, setAppData,
@@ -20,15 +20,9 @@ export default function ScheduleJobModalComponent({
const handleAuto = async () => { const handleAuto = async () => {
setLoading(true); setLoading(true);
try { try {
const response = await axios.post( const response = await axios.post("/scheduling/job", {
"/scheduling/job", jobId: "661dd1d5-bf06-426f-8bd2-bd9e41de8eb1",
{ jobId: "661dd1d5-bf06-426f-8bd2-bd9e41de8eb1" }, });
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken(true)}`,
},
}
);
setAppData({ ...appData, smartDates: response.data }); setAppData({ ...appData, smartDates: response.data });
} catch (error) { } catch (error) {
console.log("error", error, error.message); console.log("error", error, error.message);

View File

@@ -27,6 +27,7 @@ const mapDispatchToProps = (dispatch) => ({
toggleModalVisible: () => dispatch(toggleModalVisible("schedule")), toggleModalVisible: () => dispatch(toggleModalVisible("schedule")),
setEmailOptions: (e) => dispatch(setEmailOptions(e)), setEmailOptions: (e) => dispatch(setEmailOptions(e)),
}); });
export function ScheduleJobModalContainer({ export function ScheduleJobModalContainer({
scheduleModal, scheduleModal,
bodyshop, bodyshop,
@@ -163,6 +164,7 @@ export function ScheduleJobModalContainer({
}} }}
> >
<ScheduleJobModalComponent <ScheduleJobModalComponent
jobId={jobId}
existingAppointments={existingAppointments} existingAppointments={existingAppointments}
appData={appData} appData={appData}
setAppData={setAppData} setAppData={setAppData}

View File

@@ -1,4 +1,5 @@
import { Button, Card, Popover } from "antd"; import { DownOutlined } from "@ant-design/icons";
import { Card, Popover } from "antd";
import React from "react"; import React from "react";
import { useLazyQuery } from "react-apollo"; import { useLazyQuery } from "react-apollo";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -59,9 +60,10 @@ export default function ScheduleProductionList() {
return ( return (
<Popover content={content} trigger="click" placement="bottomRight"> <Popover content={content} trigger="click" placement="bottomRight">
<Button onClick={() => callQuery()}> <a href=" #" onClick={() => callQuery()}>
{t("appointments.labels.inproduction")} {t("appointments.labels.inproduction")}
</Button> <DownOutlined />
</a>
</Popover> </Popover>
); );
} }

View File

@@ -127,7 +127,7 @@ const TimeTicketsAll = lazy(() =>
import("../time-tickets/time-tickets.container") import("../time-tickets/time-tickets.container")
); );
const { Content } = Layout; const { Content, Header } = Layout;
const stripePromise = new Promise((resolve, reject) => { const stripePromise = new Promise((resolve, reject) => {
client.query({ query: QUERY_STRIPE_ID }).then((resp) => { client.query({ query: QUERY_STRIPE_ID }).then((resp) => {
@@ -152,8 +152,9 @@ export function Manage({ match, conflict }) {
return ( return (
<Layout className="layout-container"> <Layout className="layout-container">
<HeaderContainer /> <Header>
<HeaderContainer />
</Header>
<Content className="content-container"> <Content className="content-container">
<FcmNotification /> <FcmNotification />
<ErrorBoundary> <ErrorBoundary>