@star-insure/sdk 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/common/Button.d.ts +14 -0
- package/dist/components/common/Card.d.ts +7 -0
- package/dist/components/common/Modal.d.ts +9 -0
- package/dist/components/common/Pagination.d.ts +9 -0
- package/dist/components/common/ToastItem.d.ts +3 -0
- package/dist/components/common/Toasts.d.ts +2 -0
- package/dist/components/common/index.d.ts +7 -0
- package/dist/components/forms/DateOfBirthField.d.ts +7 -0
- package/dist/components/forms/Errors.d.ts +10 -0
- package/dist/components/forms/FormTester.d.ts +6 -0
- package/dist/components/forms/MoneyField.d.ts +11 -0
- package/dist/components/forms/RegistrationSearchField.d.ts +23 -0
- package/dist/components/forms/index.d.ts +6 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/tables/Table.d.ts +6 -0
- package/dist/components/tables/TableActions.d.ts +7 -0
- package/dist/components/tables/TableBody.d.ts +7 -0
- package/dist/components/tables/TableCell.d.ts +7 -0
- package/dist/components/tables/TableHead.d.ts +7 -0
- package/dist/components/tables/TableHeader.d.ts +9 -0
- package/dist/components/tables/TableRow.d.ts +8 -0
- package/dist/components/tables/index.d.ts +8 -0
- package/dist/index.d.ts +1 -0
- package/dist/lib/addressFinder.d.ts +54 -0
- package/dist/lib/auth.d.ts +2 -0
- package/dist/lib/calculateAge.d.ts +5 -0
- package/dist/lib/clickOutside.d.ts +1 -0
- package/dist/lib/index.d.ts +9 -0
- package/dist/lib/inertiaOptions.d.ts +6 -0
- package/dist/lib/localStorage.d.ts +1 -0
- package/dist/lib/quoteRequestForm.d.ts +19 -0
- package/dist/lib/quoteRequestOptions.d.ts +11 -0
- package/dist/lib/toast.d.ts +10 -0
- package/dist/sdk.cjs.development.js +1844 -0
- package/dist/sdk.cjs.development.js.map +1 -1
- package/dist/sdk.cjs.production.min.js +1 -1
- package/dist/sdk.cjs.production.min.js.map +1 -1
- package/dist/sdk.esm.js +1808 -1
- package/dist/sdk.esm.js.map +1 -1
- package/package.json +12 -2
- package/src/components/common/Button.tsx +60 -0
- package/src/components/common/Card.tsx +14 -0
- package/src/components/common/Modal.tsx +54 -0
- package/src/components/common/Pagination.tsx +77 -0
- package/src/components/common/ToastItem.tsx +54 -0
- package/src/components/common/Toasts.tsx +16 -0
- package/src/components/common/index.ts +15 -0
- package/src/components/forms/DateOfBirthField.tsx +84 -0
- package/src/components/forms/Errors.tsx +32 -0
- package/src/components/forms/FormTester.tsx +170 -0
- package/src/components/forms/MoneyField.tsx +45 -0
- package/src/components/forms/RegistrationSearchField.tsx +186 -0
- package/src/components/forms/index.ts +13 -0
- package/src/components/index.ts +3 -0
- package/src/components/tables/Table.tsx +19 -0
- package/src/components/tables/TableActions.tsx +14 -0
- package/src/components/tables/TableBody.tsx +14 -0
- package/src/components/tables/TableCell.tsx +14 -0
- package/src/components/tables/TableHead.tsx +14 -0
- package/src/components/tables/TableHeader.tsx +49 -0
- package/src/components/tables/TableRow.tsx +17 -0
- package/src/components/tables/index.ts +17 -0
- package/src/index.ts +1 -0
- package/src/lib/addressFinder.tsx +100 -0
- package/src/lib/auth.tsx +8 -0
- package/src/lib/calculateAge.ts +19 -0
- package/src/lib/clickOutside.tsx +24 -0
- package/src/lib/index.ts +9 -0
- package/src/lib/inertiaOptions.tsx +27 -0
- package/src/lib/localStorage.tsx +41 -0
- package/src/lib/quoteRequestForm.tsx +144 -0
- package/src/lib/quoteRequestOptions.tsx +21 -0
- package/src/lib/toast.tsx +55 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface Props {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
onClick?: () => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function TableRow({ children, className = '', onClick = () => {} }: Props) {
|
|
10
|
+
const bgClass = className.includes('bg') ? '' : 'bg-white even:bg-gray-50'
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<tr className={`${className} ${bgClass} hover:bg-gray-100`} onClick={onClick}>
|
|
14
|
+
{children}
|
|
15
|
+
</tr>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Table from './Table';
|
|
2
|
+
import TableActions from './TableActions';
|
|
3
|
+
import TableBody from './TableBody';
|
|
4
|
+
import TableCell from './TableCell';
|
|
5
|
+
import TableHead from './TableHead';
|
|
6
|
+
import TableHeader from './TableHeader';
|
|
7
|
+
import TableRow from './TableRow';
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
Table,
|
|
11
|
+
TableActions,
|
|
12
|
+
TableBody,
|
|
13
|
+
TableCell,
|
|
14
|
+
TableHead,
|
|
15
|
+
TableHeader,
|
|
16
|
+
TableRow,
|
|
17
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const prodConfig = {
|
|
2
|
+
key: 'XVAKN4Q9PREJD8CUTFBW',
|
|
3
|
+
baseUrl: 'https://api.addressfinder.io/api/nz/address',
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const config = prodConfig;
|
|
7
|
+
|
|
8
|
+
interface AutocompleteResponse {
|
|
9
|
+
completions: AddressCompletion[];
|
|
10
|
+
paid: boolean;
|
|
11
|
+
demo: boolean;
|
|
12
|
+
success: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AddressCompletion {
|
|
16
|
+
a: string;
|
|
17
|
+
pxid: string;
|
|
18
|
+
v: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface AddressData {
|
|
22
|
+
pxid: string;
|
|
23
|
+
a: string;
|
|
24
|
+
aims_address_id: string;
|
|
25
|
+
sufi: number;
|
|
26
|
+
ta_id: string;
|
|
27
|
+
ta: string;
|
|
28
|
+
tasub_id: string;
|
|
29
|
+
tasub: string;
|
|
30
|
+
number: string;
|
|
31
|
+
x: string;
|
|
32
|
+
y: string;
|
|
33
|
+
postcode: string;
|
|
34
|
+
street: string;
|
|
35
|
+
street_name: string;
|
|
36
|
+
street_type: string;
|
|
37
|
+
city: string;
|
|
38
|
+
suburb: string;
|
|
39
|
+
region_id: string;
|
|
40
|
+
region: string;
|
|
41
|
+
postal_line_1: string;
|
|
42
|
+
postal_line_2: string;
|
|
43
|
+
aims_road_section_id: string;
|
|
44
|
+
rural: string;
|
|
45
|
+
address_line_1: string;
|
|
46
|
+
address_line_2?: string;
|
|
47
|
+
primary_parcel_id: string;
|
|
48
|
+
meshblock: string;
|
|
49
|
+
sa1_id: string;
|
|
50
|
+
sa2_id: string;
|
|
51
|
+
sa2: string;
|
|
52
|
+
cb_id: string;
|
|
53
|
+
cb: string;
|
|
54
|
+
ward_id: string;
|
|
55
|
+
ward: string;
|
|
56
|
+
con_id: string;
|
|
57
|
+
con: string;
|
|
58
|
+
maoricon_id: string;
|
|
59
|
+
maoricon: string;
|
|
60
|
+
iur_id: string;
|
|
61
|
+
iur: string;
|
|
62
|
+
ur_id: string;
|
|
63
|
+
ur: string;
|
|
64
|
+
landwater_id: string;
|
|
65
|
+
landwater: string;
|
|
66
|
+
success: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export async function autocomplete(search: string): Promise<AddressCompletion[]> {
|
|
70
|
+
const { key, baseUrl } = config;
|
|
71
|
+
const q = encodeURIComponent(search);
|
|
72
|
+
|
|
73
|
+
const res = await fetch(`${baseUrl}/autocomplete/?key=${key}&q=${q}&format=json&strict=2`);
|
|
74
|
+
|
|
75
|
+
if (!res.ok) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const data: AutocompleteResponse = await res.json();
|
|
80
|
+
|
|
81
|
+
if (data.completions) {
|
|
82
|
+
return data.completions;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function getAddressData(completion: AddressCompletion): Promise<AddressData|null> {
|
|
89
|
+
const { key, baseUrl } = config;
|
|
90
|
+
|
|
91
|
+
const res = await fetch(`${baseUrl}/metadata/?key=${key}&pxid=${completion.pxid}&format=json`);
|
|
92
|
+
|
|
93
|
+
if (!res.ok) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const data: AddressData = await res.json();
|
|
98
|
+
|
|
99
|
+
return data;
|
|
100
|
+
}
|
package/src/lib/auth.tsx
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate someone's age from a date of birth.
|
|
3
|
+
* @param date YYYY-MM-DD
|
|
4
|
+
*/
|
|
5
|
+
export function calculateAge(date: string): number {
|
|
6
|
+
const today = new Date();
|
|
7
|
+
|
|
8
|
+
const birthDate = new Date(date);
|
|
9
|
+
|
|
10
|
+
const age = today.getFullYear() - birthDate.getFullYear();
|
|
11
|
+
|
|
12
|
+
const m = today.getMonth() - birthDate.getMonth();
|
|
13
|
+
|
|
14
|
+
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
|
|
15
|
+
return age - 1;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return age;
|
|
19
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useClickOutside(ref: any, handler: (e: Event) => void) {
|
|
4
|
+
useEffect(
|
|
5
|
+
() => {
|
|
6
|
+
const listener = (event: Event) => {
|
|
7
|
+
// Do nothing if clicking ref's element or descendent elements
|
|
8
|
+
if (!ref.current || ref.current.contains(event.target)) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
handler(event);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
document.addEventListener('mousedown', listener);
|
|
15
|
+
document.addEventListener('touchstart', listener);
|
|
16
|
+
|
|
17
|
+
return () => {
|
|
18
|
+
document.removeEventListener('mousedown', listener);
|
|
19
|
+
document.removeEventListener('touchstart', listener);
|
|
20
|
+
};
|
|
21
|
+
},
|
|
22
|
+
[ref, handler]
|
|
23
|
+
);
|
|
24
|
+
}
|
package/src/lib/index.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
export * from './dates';
|
|
2
2
|
export * from './money';
|
|
3
3
|
export * from './vehicles';
|
|
4
|
+
export * from './auth';
|
|
5
|
+
export * from './clickOutside';
|
|
6
|
+
export * from './inertiaOptions';
|
|
7
|
+
export * from './localStorage';
|
|
8
|
+
export * from './toast';
|
|
9
|
+
export * from './quoteRequestForm';
|
|
10
|
+
export * from './quoteRequestOptions';
|
|
11
|
+
export * from './addressFinder';
|
|
12
|
+
export * from './calculateAge';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { VisitOptions } from '@inertiajs/inertia/types';
|
|
2
|
+
import { useToast } from './toast';
|
|
3
|
+
|
|
4
|
+
interface Options {
|
|
5
|
+
successMessage?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function useInertiaOptions({ successMessage = '' }: Options): VisitOptions {
|
|
9
|
+
const { addToast } = useToast();
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
onSuccess: () => {
|
|
13
|
+
addToast({
|
|
14
|
+
message: successMessage ?? 'Your request was successful.',
|
|
15
|
+
status: 'success',
|
|
16
|
+
});
|
|
17
|
+
},
|
|
18
|
+
onError: (errors) => {
|
|
19
|
+
Object.values(errors).forEach((err) => {
|
|
20
|
+
addToast({
|
|
21
|
+
message: err,
|
|
22
|
+
status: 'error',
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
|
|
3
|
+
export function useLocalStorage<T>(key: string, initialValue: T) {
|
|
4
|
+
// State to store our value
|
|
5
|
+
// Pass initial state function to useState so logic is only executed once
|
|
6
|
+
const [storedValue, setStoredValue] = useState<T>(() => {
|
|
7
|
+
if (typeof window === "undefined") {
|
|
8
|
+
return initialValue;
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
// Get from local storage by key
|
|
12
|
+
const item = window.localStorage.getItem(key);
|
|
13
|
+
// Parse stored json or if none return initialValue
|
|
14
|
+
return item ? JSON.parse(item) : initialValue;
|
|
15
|
+
} catch (error) {
|
|
16
|
+
// If error also return initialValue
|
|
17
|
+
console.log(error);
|
|
18
|
+
return initialValue;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
// Return a wrapped version of useState's setter function that ...
|
|
22
|
+
// ... persists the new value to localStorage.
|
|
23
|
+
const setValue = (value: T | ((val: T) => T)) => {
|
|
24
|
+
try {
|
|
25
|
+
// Allow value to be a function so we have same API as useState
|
|
26
|
+
const valueToStore =
|
|
27
|
+
value instanceof Function ? value(storedValue) : value;
|
|
28
|
+
// Save state
|
|
29
|
+
setStoredValue(valueToStore);
|
|
30
|
+
// Save to local storage
|
|
31
|
+
if (typeof window !== "undefined") {
|
|
32
|
+
window.localStorage.setItem(key, JSON.stringify(valueToStore));
|
|
33
|
+
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
// A more advanced implementation would handle the error case
|
|
36
|
+
console.log(error);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return [storedValue, setValue] as const;
|
|
41
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { InertiaFormProps, useForm } from "@inertiajs/inertia-react";
|
|
3
|
+
import type { QuoteRequest } from '../types';
|
|
4
|
+
|
|
5
|
+
interface QuoteRequestFormContextInterface {
|
|
6
|
+
form?: InertiaFormProps<QuoteRequest>;
|
|
7
|
+
handleChange?: (e: React.ChangeEvent<HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement>) => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const initialData: QuoteRequest = {
|
|
11
|
+
id: undefined,
|
|
12
|
+
status: 'new',
|
|
13
|
+
source: 'web',
|
|
14
|
+
reference: '',
|
|
15
|
+
client_number: '',
|
|
16
|
+
first_name: '',
|
|
17
|
+
last_name: '',
|
|
18
|
+
phone: '',
|
|
19
|
+
mobile: '',
|
|
20
|
+
email: '',
|
|
21
|
+
licence: '',
|
|
22
|
+
licence_other: '',
|
|
23
|
+
promo_code: '',
|
|
24
|
+
club_membership_number: '',
|
|
25
|
+
length_of_insurance: '',
|
|
26
|
+
dob: '',
|
|
27
|
+
club_id: undefined,
|
|
28
|
+
street_address: {
|
|
29
|
+
address: '',
|
|
30
|
+
unit: '',
|
|
31
|
+
suburb: '',
|
|
32
|
+
city: '',
|
|
33
|
+
post_code: '',
|
|
34
|
+
},
|
|
35
|
+
declaration: {
|
|
36
|
+
had_incident: undefined,
|
|
37
|
+
incidents: [],
|
|
38
|
+
has_demerit_points: undefined,
|
|
39
|
+
demerit_points: '',
|
|
40
|
+
has_lost_licence: undefined,
|
|
41
|
+
lost_licence_details: '',
|
|
42
|
+
was_refused_insurance: undefined,
|
|
43
|
+
refused_insurance_details: '',
|
|
44
|
+
has_criminal_conviction: undefined,
|
|
45
|
+
criminal_conviction_details: '',
|
|
46
|
+
has_vehicle_modifications: undefined,
|
|
47
|
+
vehicle_modifications_details: '',
|
|
48
|
+
has_previous_insurer: undefined,
|
|
49
|
+
previous_insurer_details: '',
|
|
50
|
+
previous_insurer_expires_at: '',
|
|
51
|
+
additional_details: '',
|
|
52
|
+
},
|
|
53
|
+
vehicles: [],
|
|
54
|
+
// Portal specific fields:
|
|
55
|
+
purchase_options: [],
|
|
56
|
+
theme: '',
|
|
57
|
+
broker_fee: undefined,
|
|
58
|
+
broker_id: undefined,
|
|
59
|
+
broker_firm_id: undefined,
|
|
60
|
+
agent_id: undefined,
|
|
61
|
+
agent_firm_id: undefined,
|
|
62
|
+
staff_member_id: undefined,
|
|
63
|
+
sent_at: undefined,
|
|
64
|
+
sold_at: undefined,
|
|
65
|
+
referrer_id: undefined,
|
|
66
|
+
referrer_category_id: undefined,
|
|
67
|
+
pricing_expires_at: undefined,
|
|
68
|
+
follow_up_at: undefined,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const QuoteRequestFormContext = React.createContext<QuoteRequestFormContextInterface>({});
|
|
72
|
+
|
|
73
|
+
export function QuoteRequestFormProvider({ children }: { children: React.ReactNode }) {
|
|
74
|
+
const form = useForm<QuoteRequest>(initialData);
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Handle the change event for all form inputs
|
|
78
|
+
*/
|
|
79
|
+
function handleChange(e: React.SyntheticEvent<HTMLInputElement|HTMLTextAreaElement|HTMLSelectElement>) {
|
|
80
|
+
const { name } = e.currentTarget;
|
|
81
|
+
let value: string|boolean|undefined = e.currentTarget.value;
|
|
82
|
+
|
|
83
|
+
if (e.currentTarget.type === 'checkbox' || e.currentTarget.type === 'radio') {
|
|
84
|
+
const target = e.currentTarget as HTMLInputElement;
|
|
85
|
+
value = target.value === '1' ? true : false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (name.includes('.')) {
|
|
89
|
+
const parts = name.split('.');
|
|
90
|
+
|
|
91
|
+
if (parts.length === 2) {
|
|
92
|
+
return form.setData(prevData => ({
|
|
93
|
+
...prevData,
|
|
94
|
+
[parts[0]]: {
|
|
95
|
+
// @ts-ignore TODO: Maybe fix these TS errors
|
|
96
|
+
...prevData[parts[0]],
|
|
97
|
+
[parts[1]]: value,
|
|
98
|
+
},
|
|
99
|
+
}));
|
|
100
|
+
} else {
|
|
101
|
+
// We don't want to handle anything double-nested. These should be handled by their own local state.
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return form.setData(prevData => ({
|
|
107
|
+
...prevData,
|
|
108
|
+
[name]: value,
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<QuoteRequestFormContext.Provider value={{ form, handleChange }}>
|
|
114
|
+
{children}
|
|
115
|
+
</QuoteRequestFormContext.Provider>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Takes in a quote request and returns data suitable to populate a form
|
|
121
|
+
* by recursively calling this function, converting null to undefined.
|
|
122
|
+
*/
|
|
123
|
+
export function sanitiseQuoteRequestFormData(value: any): any {
|
|
124
|
+
if (Array.isArray(value)) {
|
|
125
|
+
return value.map(item => sanitiseQuoteRequestFormData(item));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (value === null) {
|
|
129
|
+
return "";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (typeof value === 'object') {
|
|
133
|
+
// Map over each property and convert null to undefined
|
|
134
|
+
return Object.keys(value).reduce((acc, key) => {
|
|
135
|
+
// @ts-ignore
|
|
136
|
+
acc[key] = sanitiseQuoteRequestFormData(value[key]);
|
|
137
|
+
return acc;
|
|
138
|
+
}, {});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return value;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const useQuoteRequestForm = () => React.useContext(QuoteRequestFormContext);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { QuoteRequestOptions } from '../';
|
|
3
|
+
|
|
4
|
+
interface QuoteRequestFormContextInterface {
|
|
5
|
+
options?: QuoteRequestOptions;
|
|
6
|
+
setOptions: (options: QuoteRequestOptions) => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const QuoteRequestOptionsContext = React.createContext<QuoteRequestFormContextInterface>({ setOptions: () => {} });
|
|
10
|
+
|
|
11
|
+
export function QuoteRequestOptionsProvider({ children }: { children: React.ReactNode }) {
|
|
12
|
+
const [options, setOptions] = React.useState<QuoteRequestOptions>();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<QuoteRequestOptionsContext.Provider value={{ options, setOptions }}>
|
|
16
|
+
{children}
|
|
17
|
+
</QuoteRequestOptionsContext.Provider>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const useQuoteRequestOptions = () => React.useContext(QuoteRequestOptionsContext);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { Toast } from "../types";
|
|
3
|
+
import { v4 as uuid } from 'uuid';
|
|
4
|
+
|
|
5
|
+
interface ToastContextInterface {
|
|
6
|
+
toasts: Toast[];
|
|
7
|
+
addToast: (toast: Toast) => void;
|
|
8
|
+
removeToast: (id: Toast['_id']) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const ToastContext = React.createContext<ToastContextInterface>({
|
|
12
|
+
toasts: [],
|
|
13
|
+
addToast: (t: Toast) => {t},
|
|
14
|
+
removeToast: (t: Toast['_id']) => {t},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export function ToastProvider({ children }: any) {
|
|
18
|
+
const [toasts, setToasts] = React.useState<Toast[]>([]);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Add a new toast popup message
|
|
22
|
+
*/
|
|
23
|
+
function addToast({ message, status, timeout = 4000 }: Toast) {
|
|
24
|
+
const newToast: Toast = { message, status, timeout };
|
|
25
|
+
|
|
26
|
+
newToast._id = uuid();
|
|
27
|
+
|
|
28
|
+
setToasts(curr => [...curr, newToast]);
|
|
29
|
+
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
removeToast(newToast._id);
|
|
32
|
+
}, timeout);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Remove a toast message
|
|
37
|
+
*/
|
|
38
|
+
function removeToast(id: Toast['_id']) {
|
|
39
|
+
setToasts(curr => curr.filter(toast => toast._id !== id));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const context: ToastContextInterface = {
|
|
43
|
+
toasts,
|
|
44
|
+
addToast,
|
|
45
|
+
removeToast,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<ToastContext.Provider value={context}>
|
|
50
|
+
{children}
|
|
51
|
+
</ToastContext.Provider>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const useToast = () => React.useContext(ToastContext);
|