@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.
Files changed (73) hide show
  1. package/dist/components/common/Button.d.ts +14 -0
  2. package/dist/components/common/Card.d.ts +7 -0
  3. package/dist/components/common/Modal.d.ts +9 -0
  4. package/dist/components/common/Pagination.d.ts +9 -0
  5. package/dist/components/common/ToastItem.d.ts +3 -0
  6. package/dist/components/common/Toasts.d.ts +2 -0
  7. package/dist/components/common/index.d.ts +7 -0
  8. package/dist/components/forms/DateOfBirthField.d.ts +7 -0
  9. package/dist/components/forms/Errors.d.ts +10 -0
  10. package/dist/components/forms/FormTester.d.ts +6 -0
  11. package/dist/components/forms/MoneyField.d.ts +11 -0
  12. package/dist/components/forms/RegistrationSearchField.d.ts +23 -0
  13. package/dist/components/forms/index.d.ts +6 -0
  14. package/dist/components/index.d.ts +3 -0
  15. package/dist/components/tables/Table.d.ts +6 -0
  16. package/dist/components/tables/TableActions.d.ts +7 -0
  17. package/dist/components/tables/TableBody.d.ts +7 -0
  18. package/dist/components/tables/TableCell.d.ts +7 -0
  19. package/dist/components/tables/TableHead.d.ts +7 -0
  20. package/dist/components/tables/TableHeader.d.ts +9 -0
  21. package/dist/components/tables/TableRow.d.ts +8 -0
  22. package/dist/components/tables/index.d.ts +8 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/lib/addressFinder.d.ts +54 -0
  25. package/dist/lib/auth.d.ts +2 -0
  26. package/dist/lib/calculateAge.d.ts +5 -0
  27. package/dist/lib/clickOutside.d.ts +1 -0
  28. package/dist/lib/index.d.ts +9 -0
  29. package/dist/lib/inertiaOptions.d.ts +6 -0
  30. package/dist/lib/localStorage.d.ts +1 -0
  31. package/dist/lib/quoteRequestForm.d.ts +19 -0
  32. package/dist/lib/quoteRequestOptions.d.ts +11 -0
  33. package/dist/lib/toast.d.ts +10 -0
  34. package/dist/sdk.cjs.development.js +1844 -0
  35. package/dist/sdk.cjs.development.js.map +1 -1
  36. package/dist/sdk.cjs.production.min.js +1 -1
  37. package/dist/sdk.cjs.production.min.js.map +1 -1
  38. package/dist/sdk.esm.js +1808 -1
  39. package/dist/sdk.esm.js.map +1 -1
  40. package/package.json +12 -2
  41. package/src/components/common/Button.tsx +60 -0
  42. package/src/components/common/Card.tsx +14 -0
  43. package/src/components/common/Modal.tsx +54 -0
  44. package/src/components/common/Pagination.tsx +77 -0
  45. package/src/components/common/ToastItem.tsx +54 -0
  46. package/src/components/common/Toasts.tsx +16 -0
  47. package/src/components/common/index.ts +15 -0
  48. package/src/components/forms/DateOfBirthField.tsx +84 -0
  49. package/src/components/forms/Errors.tsx +32 -0
  50. package/src/components/forms/FormTester.tsx +170 -0
  51. package/src/components/forms/MoneyField.tsx +45 -0
  52. package/src/components/forms/RegistrationSearchField.tsx +186 -0
  53. package/src/components/forms/index.ts +13 -0
  54. package/src/components/index.ts +3 -0
  55. package/src/components/tables/Table.tsx +19 -0
  56. package/src/components/tables/TableActions.tsx +14 -0
  57. package/src/components/tables/TableBody.tsx +14 -0
  58. package/src/components/tables/TableCell.tsx +14 -0
  59. package/src/components/tables/TableHead.tsx +14 -0
  60. package/src/components/tables/TableHeader.tsx +49 -0
  61. package/src/components/tables/TableRow.tsx +17 -0
  62. package/src/components/tables/index.ts +17 -0
  63. package/src/index.ts +1 -0
  64. package/src/lib/addressFinder.tsx +100 -0
  65. package/src/lib/auth.tsx +8 -0
  66. package/src/lib/calculateAge.ts +19 -0
  67. package/src/lib/clickOutside.tsx +24 -0
  68. package/src/lib/index.ts +9 -0
  69. package/src/lib/inertiaOptions.tsx +27 -0
  70. package/src/lib/localStorage.tsx +41 -0
  71. package/src/lib/quoteRequestForm.tsx +144 -0
  72. package/src/lib/quoteRequestOptions.tsx +21 -0
  73. 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
@@ -1,2 +1,3 @@
1
1
  export * from './types';
2
2
  export * from './lib';
3
+ export * from './components';
@@ -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
+ }
@@ -0,0 +1,8 @@
1
+ import { usePage } from '@inertiajs/inertia-react';
2
+ import type { AuthContext, PageProps } from '../types';
3
+
4
+ export function useAuth(): AuthContext {
5
+ const { props } = usePage<PageProps>() as PageProps;
6
+
7
+ return props.auth;
8
+ }
@@ -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);