Added appointment reminder email + gql fragments for emails.

This commit is contained in:
Patrick Fic
2020-03-04 14:39:19 -08:00
parent dc59d6bd7e
commit 4e214041ae
13 changed files with 121 additions and 32 deletions

View File

@@ -2,8 +2,10 @@ import React from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { setEmailOptions } from "../../redux/email/email.actions"; import { setEmailOptions } from "../../redux/email/email.actions";
import T from "../../emails/parts-order/parts-order.email"; import T, {
import { REPORT_QUERY_PARTS_ORDER_BY_PK } from "../../emails/parts-order/parts-order.query"; Subject
} from "../../emails/templates/appointment-confirmation/appointment-confirmation.template";
import { EMAIL_APPOINTMENT_CONFIRMATION } from "../../emails/templates/appointment-confirmation/appointment-confirmation.query";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser //currentUser: selectCurrentUser
@@ -20,17 +22,19 @@ export default connect(
onClick={() => onClick={() =>
setEmailOptions({ setEmailOptions({
messageOptions: { messageOptions: {
from: { name: "Kavia Autobdoy", address: "noreply@bodyshop.app" }, from: { name: "Kavia Autobody", address: "noreply@bodyshop.app" },
to: "patrickwf@gmail.com", to: "patrickwf@gmail.com",
replyTo: "snaptsoft@gmail.com" replyTo: "snaptsoft@gmail.com",
subject: Subject
}, },
template: T, template: T,
queryConfig: [ queryConfig: [
REPORT_QUERY_PARTS_ORDER_BY_PK, EMAIL_APPOINTMENT_CONFIRMATION,
{ variables: { id: "46f3aa34-c3bd-46c8-83fc-c93b7ce84f46" } } { variables: { id: "91bb31dd-ea87-4cfc-bbe2-2ec754dcb861" } }
] ]
}) })
}> }
>
Set email config. Set email config.
</button> </button>
); );

View File

@@ -13,19 +13,19 @@ export default function EmailOverlayComponent({
<Input <Input
defaultValue={messageOptions.to} defaultValue={messageOptions.to}
onChange={handleConfigChange} onChange={handleConfigChange}
name='to' name="to"
/> />
CC CC
<Input <Input
defaultValue={messageOptions.cc} defaultValue={messageOptions.cc}
onChange={handleConfigChange} onChange={handleConfigChange}
name='cc' name="cc"
/> />
Subject Subject
<Input <Input
defaultValue={messageOptions.subject} defaultValue={messageOptions.subject}
onChange={handleConfigChange} onChange={handleConfigChange}
name='subject' name="subject"
/> />
<CKEditor <CKEditor
editor={ClassicEditor} editor={ClassicEditor}

View File

@@ -7,7 +7,10 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { toggleEmailOverlayVisible } from "../../redux/email/email.actions"; import { toggleEmailOverlayVisible } from "../../redux/email/email.actions";
import { selectEmailConfig, selectEmailVisible } from "../../redux/email/email.selectors.js"; import {
selectEmailConfig,
selectEmailVisible
} from "../../redux/email/email.selectors.js";
import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import EmailOverlayComponent from "./email-overlay.component"; import EmailOverlayComponent from "./email-overlay.component";
@@ -99,6 +102,14 @@ export default connect(
messageOptions={messageOptions} messageOptions={messageOptions}
handleHtmlChange={handleHtmlChange} handleHtmlChange={handleHtmlChange}
/> />
<button
onClick={() => {
console.log(messageOptions.html);
navigator.clipboard.writeText(messageOptions.html);
}}
>
Get HTML
</button>
</LoadingSpinner> </LoadingSpinner>
</Modal> </Modal>
); );

View File

@@ -18,8 +18,8 @@ import {
setEmailOptions, setEmailOptions,
toggleEmailOverlayVisible toggleEmailOverlayVisible
} from "../../redux/email/email.actions"; } from "../../redux/email/email.actions";
import PartsOrderEmailTemplate from "../../emails/parts-order/parts-order.email"; import PartsOrderEmailTemplate from "../../emails/templates/parts-order/parts-order.email";
import { REPORT_QUERY_PARTS_ORDER_BY_PK } from "../../emails/parts-order/parts-order.query"; import { REPORT_QUERY_PARTS_ORDER_BY_PK } from "../../emails/templates/parts-order/parts-order.query";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser, currentUser: selectCurrentUser,
@@ -131,7 +131,7 @@ export default connect(
if (sendType === "e") { if (sendType === "e") {
//Show the email modal and set the data. //Show the email modal and set the data.
//TODO Remove some of the options below. //TODO Remove hardcoding
setEmailOptions({ setEmailOptions({
messageOptions: { messageOptions: {
from: { from: {
@@ -151,7 +151,7 @@ export default connect(
} }
] ]
}); });
toggleEmailOverlayVisible(); //toggleEmailOverlayVisible();
} }
}) })
.catch(error => { .catch(error => {
@@ -173,8 +173,9 @@ export default connect(
<Modal <Modal
visible={modalVisible} visible={modalVisible}
onCancel={() => setModalVisible(false)} onCancel={() => setModalVisible(false)}
onOk={handleOk}> onOk={handleOk}
{error ? <AlertComponent message={error.message} type='error' /> : null} >
{error ? <AlertComponent message={error.message} type="error" /> : null}
<LoadingSpinner loading={loading}> <LoadingSpinner loading={loading}>
<PartsOrderModalComponent <PartsOrderModalComponent
vendorList={(data && data.vendors) || []} vendorList={(data && data.vendors) || []}

View File

@@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next";
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";
export default function ScheduleJobModalComponent({ export default function ScheduleJobModalComponent({
existingAppointments, existingAppointments,
appData, appData,

View File

@@ -0,0 +1,18 @@
import { gql } from "apollo-boost";
export const shopAttributes = gql`
fragment shopData on query_root {
bodyshops(where: { associations: { active: { _eq: true } } }) {
id
address1
address2
city
email
federal_tax_id
state
shopname
zip_post
logo_img_path
}
}
`;

View File

@@ -0,0 +1,18 @@
import { gql } from "apollo-boost";
import { shopAttributes } from "../../components/fragments.queries";
export const EMAIL_APPOINTMENT_CONFIRMATION = gql`
query EMAIL_APPOINTMENT_CONFIRMATION($id: uuid!) {
appointments_by_pk(id: $id) {
start
title
job {
ownr_fn
ownr_ln
ownr_ea
}
}
...shopData
}
${shopAttributes}
`;

View File

@@ -0,0 +1,42 @@
import React from "react";
import styled from "styled-components";
import Header from "../../components/header/header.component";
import { DateTimeFormatter } from "../../../utils/DateFormatter";
const D = styled.div`
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #dddddd;
}
`;
export const Subject = "Appointment Reminder";
export default function AppointmentConfirmationEmail({ data }) {
const appointment = data.appointments_by_pk;
console.log("appointment", appointment);
return (
<D>
<Header bodyshop={data.bodyshops[0]} />
<strong>Appointment Reminder</strong>
<p> Dear {`${appointment.job.ownr_fn} ${appointment.job.ownr_ln}`},</p>
<p>
You have an appointment at {data.bodyshops[0].shopname} on{" "}
<DateTimeFormatter>{appointment.start}</DateTimeFormatter>.
</p>
<p>Thank you from the team at {data.bodyshops[0].shopname}</p>
</D>
);
}

View File

@@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import Header from "../components/header/header.component"; import Header from "../../components/header/header.component";
const D = styled.div` const D = styled.div`
table { table {

View File

@@ -1,4 +1,5 @@
import { gql } from "apollo-boost"; import { gql } from "apollo-boost";
import { shopAttributes } from "../../components/fragments.queries";
export const REPORT_QUERY_PARTS_ORDER_BY_PK = gql` export const REPORT_QUERY_PARTS_ORDER_BY_PK = gql`
query REPORT_QUERY_PARTS_ORDER_BY_PK($id: uuid!) { query REPORT_QUERY_PARTS_ORDER_BY_PK($id: uuid!) {
@@ -29,17 +30,7 @@ export const REPORT_QUERY_PARTS_ORDER_BY_PK = gql`
status status
user_email user_email
} }
bodyshops(where: { associations: { active: { _eq: true } } }) { ...shopData
id
address1
address2
city
email
federal_tax_id
state
shopname
zip_post
logo_img_path
}
} }
${shopAttributes}
`; `;

View File

@@ -1,10 +1,11 @@
import React from "react"; import React from "react";
import DashboardGridComponent from "../../components/dashboard-grid/dashboard-grid.component"; import DashboardGridComponent from "../../components/dashboard-grid/dashboard-grid.component";
import Test from "../../components/_test/test.component";
export default function ManageRootPageComponent() { export default function ManageRootPageComponent() {
//const client = useApolloClient(); //const client = useApolloClient();
return ( return (
<div> <div>
<Test />
<DashboardGridComponent /> <DashboardGridComponent />
{ {
// <SendEmailButton // <SendEmailButton

View File

@@ -25,7 +25,8 @@ const emailReducer = (state = INITIAL_STATE, action) => {
case EmailActionTypes.SET_EMAIL_OPTIONS: case EmailActionTypes.SET_EMAIL_OPTIONS:
return { return {
...state, ...state,
emailConfig: { ...action.payload } emailConfig: { ...action.payload },
visible: true
}; };
default: default:
return state; return state;