forked from M-Labs/web2019
Start refactor of order form
This commit is contained in:
parent
6b92bf9145
commit
59f726e805
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {v4 as uuidv4} from "uuid";
|
import {v4 as uuidv4} from "uuid";
|
||||||
import {Droppable} from "@hello-pangea/dnd";
|
import {Droppable} from "@hello-pangea/dnd";
|
||||||
import {ProductItem} from "./ProductItem.jsx";
|
import {ProductItem} from "./ProductItem";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Droppable} from "@hello-pangea/dnd";
|
import {Droppable} from "@hello-pangea/dnd";
|
||||||
import {cartStyle} from "./utils";
|
import {cartStyle} from "./utils";
|
||||||
import {ProductCartItem} from "./ProductCartItem.jsx";
|
import {ProductCartItem} from "./ProductCartItem";
|
||||||
import {FakePlaceholder} from "./FakePlaceholder.jsx";
|
import {FakePlaceholder} from "./FakePlaceholder";
|
||||||
import {FillExtData} from "./options/utils";
|
import {FillExtData} from "./options/utils";
|
||||||
import {hp_to_slots, resource_counters} from "./count_resources";
|
import {hp_to_slots, resource_counters} from "./count_resources";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Cart} from "./Cart.jsx";
|
import {Cart} from "./Cart";
|
||||||
import {CrateMode} from "./CrateMode.jsx";
|
import {CrateMode} from "./CrateMode";
|
||||||
import {CrateWarnings} from "./CrateWarnings.jsx";
|
import {CrateWarnings} from "./CrateWarnings";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
import {TriggerCrateWarnings} from "./warnings";
|
import {TriggerCrateWarnings} from "./warnings";
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Accordion} from "react-bootstrap";
|
import {Accordion} from "react-bootstrap";
|
||||||
import {Crate} from "./Crate.jsx";
|
import {Crate} from "./Crate";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
|
|
||||||
export function CrateList() {
|
export function CrateList() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export function ImportJSON() {
|
export function ImportJSON() {
|
||||||
return (
|
return (
|
||||||
<div> Import JSON BAOBAO</div>
|
<div> Import JSON PLACEHOLDER</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -1,203 +1,60 @@
|
|||||||
import React, {PureComponent} from 'react'
|
import React from 'react'
|
||||||
import PropTypes from "prop-types";
|
import {validateEmail, Validation} from "./validate.js";
|
||||||
|
import {useShopStore} from "./shop_store";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Components that renders the form to request quote.
|
* Components that renders the form to request quote.
|
||||||
*/
|
*/
|
||||||
export class OrderForm extends PureComponent {
|
export function OrderForm() {
|
||||||
|
|
||||||
static get propTypes() {
|
|
||||||
return {
|
|
||||||
isProcessing: PropTypes.bool,
|
|
||||||
isProcessingComplete: PropTypes.bool,
|
|
||||||
onClickSubmit: PropTypes.func,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
note: '',
|
|
||||||
email: '',
|
|
||||||
error: {
|
|
||||||
note: null,
|
|
||||||
email: null,
|
|
||||||
},
|
|
||||||
empty: {
|
|
||||||
note: null,
|
|
||||||
email: null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleEmail = this.handleEmail.bind(this);
|
|
||||||
this.handleNote = this.handleNote.bind(this);
|
|
||||||
this.handleSubmit = this.handleSubmit.bind(this);
|
|
||||||
this.resetEmptyError = this.resetEmptyError.bind(this);
|
|
||||||
this.checkValidation = this.checkValidation.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkValidation() {
|
|
||||||
let isValid = true;
|
|
||||||
let validationFields = {...this.state};
|
|
||||||
|
|
||||||
const {
|
|
||||||
isEmpty: isEmailEmpty,
|
|
||||||
isError: isEmailError
|
|
||||||
} = this.validateEmail(this.state.email);
|
|
||||||
|
|
||||||
validationFields = {
|
|
||||||
...validationFields,
|
|
||||||
error: {
|
|
||||||
...this.state.error,
|
|
||||||
email: isEmailError,
|
|
||||||
},
|
|
||||||
empty: {
|
|
||||||
...this.state.empty,
|
|
||||||
email: isEmailEmpty,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState(validationFields);
|
|
||||||
|
|
||||||
isValid =
|
|
||||||
!isEmailEmpty &&
|
|
||||||
!isEmailError
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
validateEmail(value) {
|
|
||||||
let isEmpty = null;
|
|
||||||
let isError = null;
|
|
||||||
|
|
||||||
const { t } = this.props;
|
|
||||||
|
|
||||||
if (!value || value.trim() === '') {
|
|
||||||
isEmpty = true;
|
|
||||||
} else if (value && !value.match(/^\w+([\+\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/)) {
|
|
||||||
isError = {
|
|
||||||
message: 'Your email is incomplete',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return { isEmpty, isError };
|
|
||||||
}
|
|
||||||
|
|
||||||
validateNote(value) {
|
|
||||||
let isEmpty = null;
|
|
||||||
|
|
||||||
if (!value || value.trim() === '') {
|
|
||||||
isEmpty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { isEmpty };
|
|
||||||
}
|
|
||||||
|
|
||||||
resetEmptyError(key) {
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
error: {
|
|
||||||
...this.state.error,
|
|
||||||
[key]: null,
|
|
||||||
},
|
|
||||||
empty: {
|
|
||||||
...this.state.empty,
|
|
||||||
[key]: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleEmail(e) {
|
|
||||||
const value = e.target.value;
|
|
||||||
const { isEmpty, isError } = this.validateEmail(value);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
email: value,
|
|
||||||
error: {
|
|
||||||
...this.state.error,
|
|
||||||
email: isError,
|
|
||||||
},
|
|
||||||
empty: {
|
|
||||||
...this.state.empty,
|
|
||||||
email: isEmpty,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleNote(e) {
|
|
||||||
const value = e.target.value;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
note: value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSubmit(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
if (this.props.onClickSubmit) {
|
|
||||||
// check validation input fields
|
|
||||||
const isValidated = this.checkValidation();
|
|
||||||
if (!isValidated) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.onClickSubmit(this.state.note, this.state.email);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
handleEmail,
|
|
||||||
handleNote,
|
|
||||||
resetEmptyError,
|
|
||||||
handleSubmit,
|
|
||||||
} = this;
|
|
||||||
|
|
||||||
const {
|
|
||||||
onClickShow,
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
email,
|
email,
|
||||||
note,
|
note,
|
||||||
error,
|
isProcessing,
|
||||||
empty
|
isProcessingComplete,
|
||||||
} = this.state;
|
showDescription,
|
||||||
|
updateEmail,
|
||||||
|
updateNote,
|
||||||
|
submitForm,
|
||||||
|
} = useShopStore(state => ({
|
||||||
|
email: state.email,
|
||||||
|
note: state.note,
|
||||||
|
isProcessing: state.isProcessing,
|
||||||
|
isProcessingComplete: state.isProcessingComplete,
|
||||||
|
showDescription: state.showDescription,
|
||||||
|
updateEmail: state.updateEmail,
|
||||||
|
updateNote: state.updateNote,
|
||||||
|
submitForm: state.submitForm,
|
||||||
|
}));
|
||||||
|
|
||||||
const { isProcessing, isProcessingComplete } = this.props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="summary-form">
|
<div className="summary-form">
|
||||||
|
|
||||||
<form onSubmit={handleSubmit} noValidate>
|
<form onSubmit={submitForm} noValidate>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
className={`${error && error.email ? 'errorField':''}`}
|
className={`${email.error > 0 ? 'errorField' : ''}`}
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
onFocus={() => resetEmptyError('email')}
|
onChange={(event) => updateEmail(event.target.value)}
|
||||||
onChange={handleEmail}
|
onBlur={(event) => updateEmail(event.target.value)}
|
||||||
onBlur={handleEmail}
|
value={email.value}/>
|
||||||
value={email} />
|
|
||||||
|
|
||||||
{ empty && empty.email ? (
|
{email.error === Validation.Empty ? (
|
||||||
<div className="error">
|
<div className="error">
|
||||||
<small>Required</small>
|
<small>Required</small>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{ error && error.email ? (
|
{email.error === Validation.Invalid ? (
|
||||||
<div className="error">
|
<div className="error">
|
||||||
<small>Your email is incomplete</small>
|
<small>Your email is incomplete</small>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
onChange={handleNote}
|
onChange={(event) => updateNote(event.target.value)}
|
||||||
defaultValue={note}
|
defaultValue={note.value}
|
||||||
rows="5"
|
rows="5"
|
||||||
placeholder="Additional notes"/>
|
placeholder="Additional notes"/>
|
||||||
|
|
||||||
@ -206,15 +63,16 @@ export class OrderForm extends PureComponent {
|
|||||||
className="btn btn-outline-primary w-100 m-0 mb-2 mb-sm-0 me-sm-2"
|
className="btn btn-outline-primary w-100 m-0 mb-2 mb-sm-0 me-sm-2"
|
||||||
style={{'cursor': 'pointer', 'fontWeight': '700'}}
|
style={{'cursor': 'pointer', 'fontWeight': '700'}}
|
||||||
defaultValue="Show JSON"
|
defaultValue="Show JSON"
|
||||||
onClick={onClickShow}
|
onClick={showDescription}
|
||||||
readOnly={true}/>
|
readOnly={true}/>
|
||||||
|
|
||||||
<input className="btn btn-primary w-100 m-0 ms-sm-2" type="submit" value={`${isProcessing ? 'Processing ...' : 'Request quote'}`} />
|
<input className="btn btn-primary w-100 m-0 ms-sm-2" type="submit"
|
||||||
|
value={`${isProcessing ? 'Processing ...' : 'Request quote'}`}/>
|
||||||
</div>
|
</div>
|
||||||
{/*This will open an email window. Send the email to make your request.*/}
|
{/*This will open an email window. Send the email to make your request.*/}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {OrderSummary} from "./OrderSummary.jsx";
|
import {OrderSummary} from "./OrderSummary";
|
||||||
import {OrderForm} from "./OrderForm.jsx";
|
import {OrderForm} from "./OrderForm";
|
||||||
import {CrateList} from "./CrateList.jsx";
|
import {CrateList} from "./CrateList";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {SummaryPopup} from "./options/SummaryPopup.jsx";
|
import {SummaryPopup} from "./options/SummaryPopup";
|
||||||
import {formatMoney} from "./utils";
|
import {formatMoney} from "./utils";
|
||||||
import {WarningIndicator} from "./CardWarnings.jsx";
|
import {WarningIndicator} from "./CardWarnings";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {Draggable} from "@hello-pangea/dnd";
|
import {Draggable} from "@hello-pangea/dnd";
|
||||||
import {DialogPopup} from "./options/DialogPopup.jsx";
|
import {DialogPopup} from "./options/DialogPopup";
|
||||||
import {productStyle} from "./utils";
|
import {productStyle} from "./utils";
|
||||||
import {Resources} from "./Resources.jsx";
|
import {Resources} from "./Resources";
|
||||||
import {CardWarnings} from "./CardWarnings.jsx";
|
import {CardWarnings} from "./CardWarnings";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,9 +2,9 @@ import React, {useEffect} from 'react';
|
|||||||
import {DragDropContext} from "@hello-pangea/dnd";
|
import {DragDropContext} from "@hello-pangea/dnd";
|
||||||
|
|
||||||
|
|
||||||
import {Layout} from "./Layout.jsx";
|
import {Layout} from "./Layout";
|
||||||
import {Backlog} from "./Backlog.jsx";
|
import {Backlog} from "./Backlog";
|
||||||
import {OrderPanel} from "./OrderPanel.jsx";
|
import {OrderPanel} from "./OrderPanel";
|
||||||
import {useShopStore} from "./shop_store";
|
import {useShopStore} from "./shop_store";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
5
static/js/shop/ShowJSON.jsx
Normal file
5
static/js/shop/ShowJSON.jsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export function ShowJSON() {
|
||||||
|
return (
|
||||||
|
<div> SHOW JSON PLACEHOLDER</div>
|
||||||
|
)
|
||||||
|
}
|
47
static/js/shop/json_porter.js
Normal file
47
static/js/shop/json_porter.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import {useShopStore} from "./shop_store";
|
||||||
|
|
||||||
|
|
||||||
|
export function validateJSON(description) {
|
||||||
|
let crates_raw;
|
||||||
|
try {
|
||||||
|
crates_raw = JSON.parse(description);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const crate_modes = useShopStore.getState().crate_modes;
|
||||||
|
const pn_to_card = useShopStore.getState().pn_to_cards;
|
||||||
|
|
||||||
|
for (const crate of crates_raw) {
|
||||||
|
if (!crate.type || !crate.items || !(crate.type in crate_modes)) return false;
|
||||||
|
for (const card of crate.items) {
|
||||||
|
if (!(card.pn in pn_to_card)) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function JSONToCrates(description) {
|
||||||
|
const crates_raw = JSON.parse(description);
|
||||||
|
const pn_to_card = useShopStore.getState().getCardDescriptionByPn;
|
||||||
|
return Array.from(crates_raw.map((crate, c_i) => ({
|
||||||
|
id: "crate" + c_i,
|
||||||
|
crate_mode: crate.type,
|
||||||
|
items: Array.from(crate.items.map((card, i) => ({
|
||||||
|
...pn_to_card(card.pn),
|
||||||
|
options_data: card.options
|
||||||
|
}))),
|
||||||
|
warnings: [],
|
||||||
|
occupiedHP: 0,
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CratesToJSON(crates) {
|
||||||
|
return JSON.stringify(Array.from(crates.map((crate, _i) => ({
|
||||||
|
items: Array.from(crate.items.map((card, _) => ({
|
||||||
|
pn: card.name_number,
|
||||||
|
options: (card.options_data && card.options) ? FilterOptions(card.options, card.options_data) : null
|
||||||
|
}))),
|
||||||
|
type: crate.crate_mode
|
||||||
|
}))), null, 2)
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import React, {useState} from "react";
|
import React, {useState} from "react";
|
||||||
import {useClickAway} from "./useClickAway";
|
import {useClickAway} from "./useClickAway";
|
||||||
import {ProcessOptions} from "./Options.jsx";
|
import {ProcessOptions} from "./Options";
|
||||||
|
|
||||||
export function DialogPopup({options, data, target, id, big, first, last, options_class}) {
|
export function DialogPopup({options, data, target, id, big, first, last, options_class}) {
|
||||||
const [show, setShow] = useState(false);
|
const [show, setShow] = useState(false);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {Tip} from "./Tip.jsx";
|
import {Tip} from "./Tip";
|
||||||
|
|
||||||
class Line extends Component {
|
class Line extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {Tip} from "./Tip.jsx";
|
import {Tip} from "./Tip";
|
||||||
|
|
||||||
class Radio extends Component {
|
class Radio extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {Tip} from "./Tip.jsx";
|
import {Tip} from "./Tip";
|
||||||
|
|
||||||
class Switch extends Component {
|
class Switch extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, {Component} from "react";
|
import React, {Component} from "react";
|
||||||
import {Tip} from "./Tip.jsx";
|
import {Tip} from "./Tip";
|
||||||
|
|
||||||
class SwitchLine extends Component {
|
class SwitchLine extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import {LineWrapper} from "./Line.jsx";
|
import {LineWrapper} from "./Line";
|
||||||
import {RadioWrapper} from "./Radio.jsx";
|
import {RadioWrapper} from "./Radio";
|
||||||
import {SwitchWrapper} from "./Switch.jsx";
|
import {SwitchWrapper} from "./Switch";
|
||||||
import {SwitchLineWrapper} from "./SwitchLine.jsx";
|
import {SwitchLineWrapper} from "./SwitchLine";
|
||||||
import {UnimplementedComponent} from "./UnimplementedComponent.jsx";
|
import {UnimplementedComponent} from "./UnimplementedComponent";
|
||||||
|
|
||||||
export const componentsList = {
|
export const componentsList = {
|
||||||
"Radio": RadioWrapper,
|
"Radio": RadioWrapper,
|
||||||
|
@ -6,14 +6,24 @@ import {true_type_of} from "./options/utils";
|
|||||||
import {v4 as uuidv4} from "uuid";
|
import {v4 as uuidv4} from "uuid";
|
||||||
import {FillResources} from "./count_resources";
|
import {FillResources} from "./count_resources";
|
||||||
import {TriggerCrateWarnings, TriggerWarnings} from "./warnings";
|
import {TriggerCrateWarnings, TriggerWarnings} from "./warnings";
|
||||||
|
import {Validation, validateEmail, validateNote} from "./validate";
|
||||||
|
import {CratesToJSON} from "./json_porter";
|
||||||
|
|
||||||
|
|
||||||
|
const cards_to_pn_map = (cards) => {
|
||||||
|
let result = {};
|
||||||
|
Object.entries(cards).forEach(([key, card], _i) => { result[card.name_number] = key})
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
const useBacklog = ((set, get) => ({
|
const useBacklog = ((set, get) => ({
|
||||||
cards: shared_data.items,
|
cards: shared_data.items,
|
||||||
groups: shared_data.columns.backlog,
|
groups: shared_data.columns.backlog,
|
||||||
cards_list: itemsUnfoldedList,
|
cards_list: itemsUnfoldedList,
|
||||||
currency: shared_data.currency,
|
currency: shared_data.currency,
|
||||||
|
pn_to_cards: cards_to_pn_map(shared_data.items),
|
||||||
getCardDescription: index => get().cards[get().cards_list[index]],
|
getCardDescription: index => get().cards[get().cards_list[index]],
|
||||||
|
getCardDescriptionByPn: pn => get().cards[get().pn_to_cards[pn]],
|
||||||
cardIndexById: card_id => get().cards_list.findIndex((element) => (card_id === element))
|
cardIndexById: card_id => get().cards_list.findIndex((element) => (card_id === element))
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -48,6 +58,42 @@ const useSubmitForm = ((set, get) => ({
|
|||||||
shouldShowRFQFeedback: true,
|
shouldShowRFQFeedback: true,
|
||||||
RFQBodyType: 'email',
|
RFQBodyType: 'email',
|
||||||
isProcessingComplete: true,
|
isProcessingComplete: true,
|
||||||
|
email: {
|
||||||
|
value: "",
|
||||||
|
error: null
|
||||||
|
},
|
||||||
|
note: {
|
||||||
|
value: "",
|
||||||
|
error: Validation.OK
|
||||||
|
},
|
||||||
|
|
||||||
|
description: "",
|
||||||
|
shouldShowDescription: false,
|
||||||
|
|
||||||
|
updateEmail: (new_email) => set(state => ({
|
||||||
|
email: {
|
||||||
|
value: new_email,
|
||||||
|
error: validateEmail(new_email)
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
updateNote: (new_notes) => set(state => ({
|
||||||
|
note: {
|
||||||
|
value: new_notes,
|
||||||
|
error: validateNote(new_notes)
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
|
||||||
|
updateDescription: () => set(state => ({
|
||||||
|
description: CratesToJSON(state.crates)
|
||||||
|
})),
|
||||||
|
showDescription: () => set(state => ({
|
||||||
|
description: CratesToJSON(state.crates),
|
||||||
|
shouldShowDescription: true
|
||||||
|
})),
|
||||||
|
closeDescription: () => set(state => ({
|
||||||
|
shouldShowDescription: false
|
||||||
|
})),
|
||||||
|
submitForm: () => set(state => ({})) // TODO
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const useHighlighted = ((set, get) => ({
|
const useHighlighted = ((set, get) => ({
|
||||||
|
34
static/js/shop/validate.js
Normal file
34
static/js/shop/validate.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
import {validateJSON} from "./json_porter";
|
||||||
|
|
||||||
|
export const Validation = {
|
||||||
|
OK: 0,
|
||||||
|
Empty: 1,
|
||||||
|
Invalid: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function validateEmail(value) {
|
||||||
|
if (!value || value.trim() === '') {
|
||||||
|
return Validation.Empty
|
||||||
|
} else if (value && !value.match(/^\w+([\+\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/)) {
|
||||||
|
return Validation.Invalid;
|
||||||
|
}
|
||||||
|
return Validation.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function validateNote(value) {
|
||||||
|
if (!value || value.trim() === '') {
|
||||||
|
return Validation.Empty
|
||||||
|
}
|
||||||
|
return Validation.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateJSONInput(value) {
|
||||||
|
if (!value || value.trim() === '') {
|
||||||
|
return Validation.Empty
|
||||||
|
} else if (value && !(validateJSON(value))) {
|
||||||
|
return Validation.Invalid;
|
||||||
|
}
|
||||||
|
return Validation.OK;
|
||||||
|
}
|
@ -17,8 +17,11 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
//devtool: "inline-source-map",
|
resolve: {
|
||||||
//mode: "development"
|
extensions: ['.tsx', '.ts', '.js', '.jsx'],
|
||||||
devtool: false,
|
},
|
||||||
mode: "production"
|
devtool: "inline-source-map",
|
||||||
|
mode: "development"
|
||||||
|
//devtool: false,
|
||||||
|
//mode: "production"
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user