- Eula finished

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-01-19 22:27:03 -05:00
parent 6937f33134
commit 2ada4ac44b
5 changed files with 327 additions and 170 deletions

View File

@@ -1,58 +1,27 @@
import React, {useCallback, useEffect, useRef, useState} from "react"; import React, { useCallback, useEffect, useRef, useState } from "react";
import {Button, Card, Checkbox, Col, Form, Input, Modal, Row, Space} from "antd"; import {Button, Card, Checkbox, Col, Form, Input, Modal, notification, Row, Space} from "antd";
import Markdown from "react-markdown"; import Markdown from "react-markdown";
import {createStructuredSelector} from "reselect"; import { createStructuredSelector } from "reselect";
import {selectCurrentEula, selectCurrentUser} from "../../redux/user/user.selectors"; import { selectCurrentEula, selectCurrentUser } from "../../redux/user/user.selectors";
import {connect} from "react-redux"; import { connect } from "react-redux";
import {FormDatePicker} from "../form-date-picker/form-date-picker.component"; import { FormDatePicker } from "../form-date-picker/form-date-picker.component";
import {INSERT_EULA_ACCEPTANCE} from "../../graphql/user.queries"; import { INSERT_EULA_ACCEPTANCE } from "../../graphql/user.queries";
import {useMutation} from "@apollo/client"; import { useMutation } from "@apollo/client";
import {acceptEula} from "../../redux/user/user.actions"; import { acceptEula } from "../../redux/user/user.actions";
import { useTranslation } from "react-i18next";
import day from '../../utils/day';
import './eula.styles.scss';
const mapStateToProps = createStructuredSelector({ const Eula = ({ currentEula, currentUser, acceptEula }) => {
currentEula: selectCurrentEula, const [formReady, setFormReady] = useState(false);
currentUser: selectCurrentUser,
});
const mapDispatchToProps = (dispatch) => ({
acceptEula: () => dispatch(acceptEula()),
});
export function Eula({currentEula, currentUser, acceptEula}) {
const [formReady, setFormReady] = useState(false); // [formReady, setFormReady
const [hasEverScrolledToBottom, setHasEverScrolledToBottom] = useState(false); const [hasEverScrolledToBottom, setHasEverScrolledToBottom] = useState(false);
const [insertEulaAcceptance] = useMutation(INSERT_EULA_ACCEPTANCE); const [insertEulaAcceptance] = useMutation(INSERT_EULA_ACCEPTANCE);
const [form] = Form.useForm(); const [form] = Form.useForm();
const markdownDivRef = useRef(null); const markdownCardRef = useRef(null);
const { t } = useTranslation();
const [api, contextHolder] = notification.useNotification();
const handleAccept = async ({acceptTerms, ...formValues}) => {
const eulaId = currentEula.id;
const useremail = currentUser.email;
try {
await insertEulaAcceptance({
variables: {
eulaAcceptance: {
eulaid: eulaId,
useremail,
...formValues,
date_accepted: new Date(),
}
}
});
acceptEula();
} catch (err) {
// Pop notification with error, pop console
console.error(err);
}
//R
// setIsModalOpen(false);
//Insert and Dispatch the action to recheck force acceptance.
};
const handleScroll = (e) => { const handleScroll = (e) => {
const bottom = e.target.scrollHeight - 100 <= e.target.scrollTop + e.target.clientHeight; const bottom = e.target.scrollHeight - 100 <= e.target.scrollTop + e.target.clientHeight;
if (bottom && !hasEverScrolledToBottom) { if (bottom && !hasEverScrolledToBottom) {
@@ -61,135 +30,197 @@ export function Eula({currentEula, currentUser, acceptEula}) {
}; };
const handleChange = useCallback(() => { const handleChange = useCallback(() => {
form.validateFields({ form.validateFields({ validateOnly: true })
validateOnly: true, .then(() => setFormReady(hasEverScrolledToBottom))
}).then(() => { .catch(() => setFormReady(false));
setFormReady(hasEverScrolledToBottom);
}).catch(() => {
setFormReady(false);
});
}, [form, hasEverScrolledToBottom]); }, [form, hasEverScrolledToBottom]);
useEffect(() => { useEffect(() => {
handleChange(); handleChange();
}, [handleChange, hasEverScrolledToBottom, form]); }, [handleChange, hasEverScrolledToBottom, form]);
const onFinish = async ({ acceptTerms, ...formValues }) => {
const eulaId = currentEula.id;
const useremail = currentUser.email;
return <Modal try {
title="Terms and Conditions" const { accepted_terms, ...otherFormValues } = formValues;
style={{top: 20}} await insertEulaAcceptance({
width={'100vh'} variables: {
open={currentEula} eulaAcceptance: {
footer={() => ( eulaid: eulaId,
<Button style={{width: '100%'}} form='tosForm' type="primary" size='large' htmlType="submit" useremail,
disabled={!formReady}>Accept</Button> ...otherFormValues,
)} date_accepted: new Date(),
closable={false} }
> }
<Space direction='vertical'> });
<Card type='inner' style={{ acceptEula();
maxHeight: '50vh', } catch (err) {
overflowY: 'auto', api.error({
backgroundColor: 'lightgray', message: t('eula.errors.acceptance.message'),
}} onScroll={handleScroll} ref={markdownDivRef}> description: t('eula.errors.acceptance.description'),
<div id='markdowndiv' style={{ placement: 'bottomRight',
padding: '0 10px 0 10px' duration: 5000,
}}>
<Markdown children={currentEula?.content?.replace(/\\n/g, '\n')}/> });
</div> console.log(`${t('eula.errors.acceptance.message')}`);
</Card> console.dir({
<Card type='inner' title='Acknowledgement'> message: err.message,
<Form id='tosForm' onChange={handleChange} onFinish={handleAccept} form={form}> stack: err.stack,
<Row gutter={24}> });
<Col span={12}> }
<Form.Item };
label="First Name"
name="first_name" return (
rules={[{required: true, message: 'Please input your first name!'}]} <>
> {contextHolder}
<Input placeholder="First Name" aria-label="First Name"/> <Modal
</Form.Item> title={t('eula.titles.modal')}
</Col> className='eula-modal'
<Col span={12}> width={'100vh'}
<Form.Item open={currentEula}
label="Last Name" footer={() => (
name="last_name" <Button
rules={[{required: true, message: 'Please input your last name!'}]} className='eula-accept-button'
> form='tosForm'
<Input placeholder="Last Name" aria-label="Last Name"/> type="primary"
</Form.Item> size='large'
</Col> htmlType="submit"
</Row> disabled={!formReady}
<Row gutter={24}> children={t('eula.buttons.accept')}
<Col span={12}> />
<Form.Item )}
label="Legal Business Name" closable={false}
name="business_name" >
rules={[{required: true, message: 'Please input your legal business name!'}]} <Space direction='vertical'>
> <Card type='inner' className='eula-markdown-card' onScroll={handleScroll} ref={markdownCardRef}>
<Input placeholder="Legal Business Name" aria-label="Legal Business Name"/> <div id='markdowndiv' className='eula-markdown-div'>
</Form.Item> <Markdown children={currentEula?.content?.replace(/\\n/g, '\n')} />
</Col> </div>
<Col span={12}> </Card>
<Form.Item <EulaFormComponent form={form} handleChange={handleChange} onFinish={onFinish} t={t} />
label="Phone" {!hasEverScrolledToBottom && (
name="phone_number" <Card className='eula-never-scrolled' type='inner'>
rules={[ <h3>{t('eula.content.never_scrolled')}</h3>
{ </Card>
pattern: /^(\+\d{1,2}\s?)?1?-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/, )}
message: 'Please enter a valid phone number!' </Space>
} </Modal>
]} </>
> )
<Input placeholder="Phone" aria-label="Phone"/>
</Form.Item>
</Col>
</Row>
<Row gutter={24}>
<Col span={12}>
<Form.Item
label="Address"
name="address"
>
<Input placeholder="Address" aria-label="Address"/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="Date"
name="date_accepted"
rules={[{required: true},]}
>
<FormDatePicker onChange={handleChange} onlyFuture/>
</Form.Item>
</Col>
</Row>
<Row gutter={24}>
<Col span={24}>
<Form.Item
name="acceptTerms"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value ? Promise.resolve() : Promise.reject(new Error('You must accept the terms and conditions')),
},
]}
>
<Checkbox aria-label="Accept Terms">I accept the terms and conditions</Checkbox>
</Form.Item>
</Col>
</Row>
</Form>
</Card>
{!hasEverScrolledToBottom && (
<Card style={{textAlign: 'center'}} type='inner'>
<h3>You must scroll to the bottom of the Terms and Conditions before accepting.</h3>
</Card>
)}
</Space>
</Modal>
} }
const EulaFormComponent = ({ form, handleChange, onFinish, t }) => (
<Card type='inner' title={t('eula.titles.upper_card')}>
<Form id='tosForm' onChange={handleChange} onFinish={onFinish} form={form}>
<Row gutter={24}>
<Col span={12}>
<Form.Item
label={t('eula.labels.first_name')}
name="first_name"
rules={[{ required: true, message: t('eula.messages.first_name') }]}
>
<Input placeholder={t('eula.labels.first_name')}
aria-label={t('eula.labels.first_name')} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label={t('eula.labels.last_name')}
name="last_name"
rules={[{ required: true, message: t('eula.messages.last_name') }]}
>
<Input placeholder={t('eula.labels.last_name')}
aria-label={t('eula.labels.last_name')} />
</Form.Item>
</Col>
</Row>
<Row gutter={24}>
<Col span={12}>
<Form.Item
label={t('eula.labels.business_name')}
name="business_name"
rules={[{ required: true, message: t('eula.messages.business_name') }]}
>
<Input placeholder={t('eula.labels.business_name')}
aria-label={t('eula.labels.business_name')} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label={t('eula.labels.phone_number')}
name="phone_number"
rules={[
{
pattern: /^(\+\d{1,2}\s?)?1?-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$/,
message: t('eula.messages.phone_number'),
}
]}
>
<Input placeholder={t('eula.labels.phone_number')}
aria-label={t('eula.labels.phone_number')} />
</Form.Item>
</Col>
</Row>
<Row gutter={24}>
<Col span={12}>
<Form.Item
label={t('eula.labels.address')}
name="address"
>
<Input placeholder={t('eula.labels.address')} aria-label={t('eula.labels.address')} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label={t('eula.labels.date_accepted')}
name="date_accepted"
rules={[
{ required: true },
{
validator: (_, value) => {
if (day(value).isSame(day(), 'day')) {
return Promise.resolve();
}
return Promise.reject(new Error(t('eula.messages.date_accepted')));
}
},
]}
>
<FormDatePicker onChange={handleChange} onlyFuture
aria-label={t('eula.labels.date_accepted')} />
</Form.Item>
</Col>
</Row>
<Row gutter={24}>
<Col span={24}>
<Form.Item
name="accepted_terms"
valuePropName="checked"
rules={[
{
validator: (_, value) =>
value ? Promise.resolve() : Promise.reject(new Error(t('eula.messages.accepted_terms'))),
},
]}
>
<Checkbox
aria-label={t('eula.labels.accepted_terms')}>{t('eula.labels.accepted_terms')}</Checkbox>
</Form.Item>
</Col>
</Row>
</Form>
</Card>
);
const mapStateToProps = createStructuredSelector({
currentEula: selectCurrentEula,
currentUser: selectCurrentUser,
});
const mapDispatchToProps = (dispatch) => ({
acceptEula: () => dispatch(acceptEula()),
});
export default connect(mapStateToProps, mapDispatchToProps)(Eula); export default connect(mapStateToProps, mapDispatchToProps)(Eula);

View File

@@ -0,0 +1,21 @@
.eula-modal {
top: 20px;
}
.eula-markdown-card {
max-height: 50vh;
overflow-y: auto;
background-color: lightgray;
}
.eula-markdown-div {
padding: 0 10px 0 10px;
}
.eula-never-scrolled {
text-align: center;
}
.eula-accept-button {
width: 100%;
}

View File

@@ -933,6 +933,41 @@
"updated": "Document updated successfully. " "updated": "Document updated successfully. "
} }
}, },
"eula": {
"titles": {
"modal": "Terms and Conditions",
"upper_card": "Acknowledgement"
},
"messages": {
"first_name": "Please enter your first name.",
"last_name": "Please enter your last name.",
"business_name": "Please enter your legal business name.",
"phone_number": "Please enter your phone number.",
"date_accepted": "Please enter Today's Date.",
"accepted_terms": "Please accept the terms and conditions of this agreement."
},
"buttons": {
"accept": "Accept EULA"
},
"labels": {
"first_name": "First Name",
"last_name": "Last Name",
"business_name": "Legal Business Name",
"phone_number": "Phone Number",
"address": "Address",
"date_accepted": "Date Accepted",
"accepted_terms": "I accept the terms and conditions of this agreement."
},
"content": {
"never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
},
"errors": {
"acceptance": {
"message": "Eula Acceptance Error",
"description": "Something went wrong while accepting the EULA. Please try again."
}
}
},
"emails": { "emails": {
"errors": { "errors": {
"notsent": "Email not sent. Error encountered while sending {{message}}" "notsent": "Email not sent. Error encountered while sending {{message}}"

View File

@@ -933,6 +933,41 @@
"updated": "" "updated": ""
} }
}, },
"eula": {
"titles": {
"modal": "Terms and Conditions",
"upper_card": "Acknowledgement"
},
"messages": {
"first_name": "Please enter your first name.",
"last_name": "Please enter your last name.",
"business_name": "Please enter your legal business name.",
"phone_number": "Please enter your phone number.",
"date_accepted": "Please enter Today's Date.",
"accepted_terms": "Please accept the terms and conditions of this agreement."
},
"buttons": {
"accept": "Accept EULA"
},
"labels": {
"first_name": "First Name",
"last_name": "Last Name",
"business_name": "Legal Business Name",
"phone_number": "Phone Number",
"address": "Address",
"date_accepted": "Date Accepted",
"accepted_terms": "I accept the terms and conditions of this agreement."
},
"content": {
"never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
},
"errors": {
"acceptance": {
"message": "Eula Acceptance Error",
"description": "Something went wrong while accepting the EULA. Please try again."
}
}
},
"emails": { "emails": {
"errors": { "errors": {
"notsent": "Correo electrónico no enviado Se encontró un error al enviar {{message}}" "notsent": "Correo electrónico no enviado Se encontró un error al enviar {{message}}"

View File

@@ -933,6 +933,41 @@
"updated": "" "updated": ""
} }
}, },
"eula": {
"titles": {
"modal": "Terms and Conditions",
"upper_card": "Acknowledgement"
},
"messages": {
"first_name": "Please enter your first name.",
"last_name": "Please enter your last name.",
"business_name": "Please enter your legal business name.",
"phone_number": "Please enter your phone number.",
"date_accepted": "Please enter Today's Date.",
"accepted_terms": "Please accept the terms and conditions of this agreement."
},
"buttons": {
"accept": "Accept EULA"
},
"labels": {
"first_name": "First Name",
"last_name": "Last Name",
"business_name": "Legal Business Name",
"phone_number": "Phone Number",
"address": "Address",
"date_accepted": "Date Accepted",
"accepted_terms": "I accept the terms and conditions of this agreement."
},
"content": {
"never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
},
"errors": {
"acceptance": {
"message": "Eula Acceptance Error",
"description": "Something went wrong while accepting the EULA. Please try again."
}
}
},
"emails": { "emails": {
"errors": { "errors": {
"notsent": "Courriel non envoyé. Erreur rencontrée lors de l'envoi de {{message}}" "notsent": "Courriel non envoyé. Erreur rencontrée lors de l'envoi de {{message}}"