nitro-web 0.0.84 → 0.0.86

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/client/app.tsx CHANGED
@@ -94,10 +94,12 @@ function App({ settings, config, storeContainer }: { settings: Settings, config:
94
94
  }, [!!router])
95
95
 
96
96
  return (
97
+ // <StrictMode>
97
98
  <storeContainer.Provider>
98
99
  { router && <RouterProvider router={router}/> }
99
100
  <AfterApp settings={settings} />
100
101
  </storeContainer.Provider>
102
+ // </StrictMode>
101
103
  )
102
104
  }
103
105
 
package/client/index.ts CHANGED
@@ -18,10 +18,6 @@ export { ResetInstructions, ResetPassword } from '../components/auth/reset'
18
18
  export { Dashboard } from '../components/dashboard/dashboard'
19
19
  export { NotFound } from '../components/partials/not-found'
20
20
  export { Styleguide } from '../components/partials/styleguide'
21
- // export { SettingsAccount } from '../components/settings/settings-account'
22
- // export { SettingsBusiness } from '../components/settings/settings-business'
23
- // export { SettingsTeamMember } from '../components/settings/settings-team--member'
24
- // export { SettingsTeam } from '../components/settings/settings-team'
25
21
 
26
22
  // Component Elements
27
23
  export { Accordion } from '../components/partials/element/accordion'
@@ -1,3 +1,4 @@
1
+ // @ts-nocheck
1
2
  import crypto from 'crypto'
2
3
  import bcrypt from 'bcrypt'
3
4
  import passport from 'passport'
@@ -315,7 +316,7 @@ export async function signinAndGetStore(user, isDesktop, getStore) {
315
316
  return { ...store, jwt }
316
317
  }
317
318
 
318
- export async function userCreate({ name, business, email, password }) {
319
+ export async function userCreate({ business, password, ...userDataProp }) {
319
320
  try {
320
321
  if (!this.findUserFromProvider) {
321
322
  throw new Error('this.findUserFromProvider doesn\'t exist, make sure the context is available when calling this function')
@@ -330,14 +331,15 @@ export async function userCreate({ name, business, email, password }) {
330
331
  users: [{ _id: userId, role: 'owner', status: 'active' }],
331
332
  }
332
333
  const userData = {
333
- _id: userId,
334
- email: email,
335
- firstName: fullNameSplit(name)[0],
336
- lastName: fullNameSplit(name)[1],
334
+ ...userDataProp,
335
+ _id: userId,
336
+ ...(userDataProp.name ? {
337
+ firstName: fullNameSplit(userDataProp.name)[0],
338
+ lastName: fullNameSplit(userDataProp.name)[1],
339
+ } : {}),
337
340
  password: password ? await bcrypt.hash(password, 10) : undefined,
338
341
  ...(isMultiTenant ? { company: companyData._id } : {}),
339
342
  }
340
-
341
343
  // First validate the data so we don't have to create a transaction
342
344
  const results = await Promise.allSettled([
343
345
  db.user.validate(userData, options),
@@ -362,10 +364,7 @@ export async function userCreate({ name, business, email, password }) {
362
364
 
363
365
  } catch (err) {
364
366
  if (!isArray(err)) throw err
365
- throw err.map((o) => {
366
- if (o.title == 'firstName') o.title = 'name'
367
- return o
368
- })
367
+ else throw err //...
369
368
  }
370
369
  }
371
370
 
@@ -1,4 +1,4 @@
1
- import { Topbar, Field, FormError, Button, util } from 'nitro-web'
1
+ import { Topbar, Field, FormError, Button, request } from 'nitro-web'
2
2
  import { Errors } from 'nitro-web/types'
3
3
 
4
4
  export function ResetInstructions() {
@@ -9,7 +9,7 @@ export function ResetInstructions() {
9
9
 
10
10
  async function onSubmit (event: React.FormEvent<HTMLFormElement>) {
11
11
  try {
12
- await util.request('post /api/reset-instructions', state, event, isLoading)
12
+ await request('post /api/reset-instructions', state, event, isLoading, setState)
13
13
  setStore((s) => ({ ...s, message: 'Done! Please check your email.' }))
14
14
  navigate('/signin')
15
15
  } catch (e) {
@@ -52,7 +52,7 @@ export function ResetPassword() {
52
52
 
53
53
  async function onSubmit (event: React.FormEvent<HTMLFormElement>) {
54
54
  try {
55
- const data = await util.request('post /api/reset-password', state, event, isLoading)
55
+ const data = await request('post /api/reset-password', state, event, isLoading, setState)
56
56
  setStore((s) => ({ ...s, ...data }))
57
57
  navigate('/')
58
58
  } catch (e) {
@@ -1,4 +1,4 @@
1
- import { Topbar, Field, Button, FormError, util, injectedConfig, updateJwt } from 'nitro-web'
1
+ import { Topbar, Field, Button, FormError, request, queryObject, injectedConfig, updateJwt } from 'nitro-web'
2
2
  import { Errors } from 'nitro-web/types'
3
3
 
4
4
  export function Signin() {
@@ -15,7 +15,7 @@ export function Signin() {
15
15
 
16
16
  useEffect(() => {
17
17
  // Autofill the email input from ?email=
18
- const query = util.queryObject(location.search, true)
18
+ const query = queryObject(location.search, true)
19
19
  if (query.email) setState({ ...state, email: query.email as string })
20
20
  }, [location.search])
21
21
 
@@ -33,7 +33,7 @@ export function Signin() {
33
33
 
34
34
  async function onSubmit (e: React.FormEvent<HTMLFormElement>) {
35
35
  try {
36
- const data = await util.request('post /api/signin', state, e, isLoading)
36
+ const data = await request('post /api/signin', state, e, isLoading, setState)
37
37
  // Keep it loading until we navigate
38
38
  isLoading[1](true)
39
39
  setStore((s) => ({ ...s, ...data }))
@@ -1,4 +1,4 @@
1
- import { Button, Field, FormError, Topbar, util, injectedConfig } from 'nitro-web'
1
+ import { Button, Field, FormError, Topbar, request, injectedConfig } from 'nitro-web'
2
2
  import { Errors } from 'nitro-web/types'
3
3
 
4
4
  export function Signup() {
@@ -15,12 +15,11 @@ export function Signup() {
15
15
 
16
16
  async function onSubmit (e: React.FormEvent<HTMLFormElement>) {
17
17
  try {
18
- setState({ ...state, errors: [] }) // clear errors (optional)
19
- const data = await util.request('post /api/signup', state, e, isLoading)
20
- setStore((s) => ({ ...s, ...data }))
18
+ const data = await request('post /api/signup', state, e, isLoading, setState)
19
+ setStore((prev) => ({ ...prev, ...data }))
21
20
  setTimeout(() => navigate('/'), 0) // wait for setStore
22
21
  } catch (e) {
23
- return setState({ ...state, errors: e as Errors })
22
+ setState((prev) => ({ ...prev, errors: e as Errors }))
24
23
  }
25
24
  }
26
25
 
@@ -32,7 +31,10 @@ export function Signup() {
32
31
  <div class="grid grid-cols-2 gap-6">
33
32
  <div>
34
33
  <label for="name">Your Name</label>
35
- <Field name="name" placeholder="E.g. Bruce Wayne" state={state} onChange={(e) => onChange(setState, e)} />
34
+ <Field name="name" placeholder="E.g. Bruce Wayne" state={state}
35
+ onChange={(e) => onChange(setState, e)}
36
+ errorTitle={/^(name|firstName|lastName)$/} // if different from `name`
37
+ />
36
38
  </div>
37
39
  <div>
38
40
  <label for="business.name">Company Name</label>
@@ -16,14 +16,16 @@ type CheckboxProps = React.InputHTMLAttributes<HTMLInputElement> & {
16
16
  checkboxClassName?: string
17
17
  svgClassName?: string
18
18
  labelClassName?: string
19
+ /** title used to find related error messages */
20
+ errorTitle?: string|RegExp
19
21
  }
20
22
 
21
23
  export function Checkbox({
22
- state, size, subtext, text, type='checkbox', className, checkboxClassName, svgClassName, labelClassName, ...props
24
+ state, size, subtext, text, type='checkbox', className, checkboxClassName, svgClassName, labelClassName, errorTitle, ...props
23
25
  }: CheckboxProps) {
24
26
  // Checkbox/radio/toggle component
25
27
  let value!: boolean
26
- const error = getErrorFromState(state, props.name)
28
+ const error = getErrorFromState(state, errorTitle || props.name)
27
29
  const id = props.id || props.name
28
30
 
29
31
  if (!props.name) throw new Error('Checkbox requires a `name` prop')
@@ -21,16 +21,18 @@ type DropProps = {
21
21
  errors?: Errors
22
22
  [key: string]: unknown
23
23
  }
24
+ /** title used to find related error messages */
25
+ errorTitle?: string|RegExp
24
26
  /** Props to pass to the input element */
25
27
  [key: string]: unknown
26
28
  }
27
29
 
28
30
  type Image = File | FileList | MonasteryImage | null
29
31
 
30
- export function Drop({ awsUrl, className, id, name, onChange, multiple, state, ...props }: DropProps) {
32
+ export function Drop({ awsUrl, className, id, name, onChange, multiple, state, errorTitle, ...props }: DropProps) {
31
33
  if (!name) throw new Error('Drop component requires a `name` prop')
32
34
  let value: Image = null
33
- const error = getErrorFromState(state, name)
35
+ const error = getErrorFromState(state, errorTitle || name)
34
36
  const inputId = id || name
35
37
  const [urls, setUrls] = useState([])
36
38
  const stateRef = useRef(state)
@@ -25,6 +25,8 @@ type FieldExtraProps = {
25
25
  /** Dependencies to break the implicit memoization of onChange/onInputChange */
26
26
  deps?: unknown[]
27
27
  placeholder?: string
28
+ /** title used to find related error messages */
29
+ errorTitle?: string|RegExp
28
30
  }
29
31
  type IconWrapperProps = {
30
32
  iconPos: 'left' | 'right'
@@ -43,17 +45,18 @@ type IsFieldCachedProps = {
43
45
  name: string
44
46
  state?: FieldProps['state']
45
47
  deps?: FieldProps['deps']
48
+ errorTitle?: FieldProps['errorTitle']
46
49
  }
47
50
 
48
51
  export const Field = memo(FieldBase, (prev, next) => {
49
52
  return isFieldCached(prev, next)
50
53
  })
51
54
 
52
- function FieldBase({ state, icon, iconPos: ip, ...props }: FieldProps) {
55
+ function FieldBase({ state, icon, iconPos: ip, errorTitle, ...props }: FieldProps) {
53
56
  // `type` must be kept as props.type for TS to be happy and follow the conditions below
54
57
  let value!: string
55
58
  let Icon!: React.ReactNode
56
- const error = getErrorFromState(state, props.name)
59
+ const error = getErrorFromState(state, errorTitle || props.name)
57
60
  const type = props.type
58
61
  const iconPos = ip == 'left' || (type == 'color' && !ip) ? 'left' : 'right'
59
62
  const id = props.id || props.name
@@ -184,13 +187,9 @@ function ColorSvg({ hex }: { hex?: string }) {
184
187
  export function isFieldCached(prev: IsFieldCachedProps, next: IsFieldCachedProps) {
185
188
  // Check if the field is cached, onChange/onInputChange doesn't affect the cache
186
189
  const path = prev.name
187
- const state = prev.state || {}
188
- // If the state value has changed, re-render!
189
- if (deepFind(state, path) !== deepFind(next.state || {}, path)) return false
190
- // If the state error has changed, re-render!
191
- if (getErrorFromState(state, path) !== getErrorFromState(next.state || {}, path)) return false
192
- // If `deps` have changed, handy for onChange/onInputChange, re-render!
193
- if ((next.deps?.length !== prev.deps?.length) || next.deps?.some((v, i) => v !== prev.deps?.[i])) return false
190
+ const prevState = prev.state || {}
191
+ const nextState = next.state || {}
192
+ const errorTitle = next.errorTitle || path
194
193
 
195
194
  // Check if any prop has changed, except `onChange`/`onInputChange`
196
195
  const allKeys = new Set([...Object.keys(prev), ...Object.keys(next)])
@@ -201,6 +200,16 @@ export function isFieldCached(prev: IsFieldCachedProps, next: IsFieldCachedProps
201
200
  return false
202
201
  }
203
202
  }
203
+
204
+ // If `deps` have changed, handy for onChange/onInputChange, re-render!
205
+ if ((next.deps?.length !== prev.deps?.length) || next.deps?.some((v, i) => v !== prev.deps?.[i])) return false
206
+
207
+ // If the state value has changed, re-render!
208
+ if (deepFind(prevState, path) !== deepFind(nextState, path)) return false
209
+
210
+ // If the state error has changed, re-render!
211
+ if (getErrorFromState(prevState, errorTitle) !== getErrorFromState(nextState, errorTitle)) return false
212
+
204
213
  // All good, use cached version
205
214
  return true
206
215
  }
@@ -43,6 +43,8 @@ export type SelectProps = {
43
43
  mode?: 'country'|'customer'|''
44
44
  /** Pass dependencies to break memoization, handy for onChange/onInputChange **/
45
45
  deps?: unknown[]
46
+ /** title used to find related error messages */
47
+ errorTitle?: string|RegExp
46
48
  /** All other props are passed to react-select **/
47
49
  [key: string]: unknown
48
50
  }
@@ -51,9 +53,11 @@ export const Select = memo(SelectBase, (prev, next) => {
51
53
  return isFieldCached(prev, next)
52
54
  })
53
55
 
54
- function SelectBase({ id, containerId, minMenuWidth, name, prefix='', onChange, options, state, mode='', ...props }: SelectProps) {
56
+ function SelectBase({
57
+ id, containerId, minMenuWidth, name, prefix='', onChange, options, state, mode='', errorTitle, ...props
58
+ }: SelectProps) {
55
59
  let value: unknown|unknown[]
56
- const error = getErrorFromState(state, name)
60
+ const error = getErrorFromState(state, errorTitle || name)
57
61
  if (!name) throw new Error('Select component requires a `name` and `options` prop')
58
62
 
59
63
  // Get value from value or state
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nitro-web",
3
- "version": "0.0.84",
3
+ "version": "0.0.86",
4
4
  "repository": "github:boycce/nitro-web",
5
5
  "homepage": "https://boycce.github.io/nitro-web/",
6
6
  "description": "Nitro is a battle-tested, modular base project to turbocharge your projects, styled using Tailwind 🚀",
package/server/index.js CHANGED
@@ -20,10 +20,8 @@ export { sendEmail } from './email/index.js'
20
20
 
21
21
  // Export API controllers
22
22
  export * from '../components/auth/auth.api.js'
23
- export * from '../components/settings/settings.api.js'
24
23
  export * from '../components/billing/stripe.api.js'
25
24
 
26
25
  export { routes as authRoutes } from '../components/auth/auth.api.js'
27
- export { routes as settingsRoutes } from '../components/settings/settings.api.js'
28
26
  export { routes as stripeRoutes } from '../components/billing/stripe.api.js'
29
27
 
@@ -8,7 +8,7 @@ export default {
8
8
  company: { model: 'company', required: true },
9
9
  email: { type: 'email', required: true, index: 'unique' },
10
10
  firstName: { type: 'string', required: true },
11
- lastName: { type: 'string' },
11
+ lastName: { type: 'string', required: true },
12
12
  password: { type: 'string', minLength: 6 },
13
13
  resetToken: { type: 'string' },
14
14
  status: { type: 'string', default: 'active', enum: ['active', 'deleted', 'inactive'] },
@@ -22,6 +22,12 @@ export default {
22
22
  findBL: ['password', 'resetToken'],
23
23
  updateBL: ['company', 'password', 'resetToken', 'status', 'stripeSubscription', 'type', 'usedFreeTrial'],
24
24
 
25
+ messages: {
26
+ lastName: {
27
+ required: 'A full name is required',
28
+ },
29
+ },
30
+
25
31
  beforeValidate: [
26
32
  async function (data) {
27
33
  if (data.email) data.email = data.email.trim().toLowerCase()
@@ -32,7 +38,7 @@ export default {
32
38
 
33
39
  afterFind: [
34
40
  async function (data) {
35
- if (!data) return
41
+ if (!data) return data
36
42
  data.name = fullName(data)
37
43
  },
38
44
  ],
package/tsconfig.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "jsx": "react-jsx",
11
11
  "lib": ["es6", "dom", "dom.iterable", "esnext"],
12
12
  "module": "esnext",
13
- "moduleResolution": "node",
13
+ "moduleResolution": "bundler",
14
14
  "noEmit": false,
15
15
  "noFallthroughCasesInSwitch": true,
16
16
  "noImplicitAny": true,
@@ -22,6 +22,7 @@
22
22
  "types": ["./types.ts"]
23
23
  },
24
24
  "resolveJsonModule": true,
25
+ "rootDir": "./",
25
26
  "skipLibCheck": true,
26
27
  "sourceMap": true,
27
28
  "strict": true,
@@ -29,9 +30,8 @@
29
30
  },
30
31
  "include": [
31
32
  "client",
32
- "components/**/*.tsx",
33
- "components/**/*.ts",
34
- "server/constants.js",
33
+ "components/**/*.{tsx,ts,js}",
34
+ "server/**/*.js",
35
35
  "types",
36
36
  "./types/core-only-globals.d.ts"
37
37
  ]
package/types/util.d.ts CHANGED
@@ -266,7 +266,7 @@ export function getCurrencyOptions(currencies: {
266
266
  /**
267
267
  * Returns an error from a state object matching the path
268
268
  * @param {{ errors?: { title: string, detail: string }[] }|undefined} state
269
- * @param {string} path
269
+ * @param {string|RegExp} path
270
270
  * @returns {{ title: string, detail: string }|undefined}
271
271
  */
272
272
  export function getErrorFromState(state: {
@@ -274,7 +274,7 @@ export function getErrorFromState(state: {
274
274
  title: string;
275
275
  detail: string;
276
276
  }[];
277
- } | undefined, path: string): {
277
+ } | undefined, path: string | RegExp): {
278
278
  title: string;
279
279
  detail: string;
280
280
  } | undefined;
@@ -621,6 +621,7 @@ export function queryString(obj?: {
621
621
  * @param {{ [key: string]: any }} [data] - payload
622
622
  * @param {{preventDefault?: function}} [event] - event to prevent default
623
623
  * @param {[boolean, (value: boolean) => void]} [isLoading] - [isLoading, setIsLoading]
624
+ * @param {SetState} [setState] - if passed, state.errors will be reset before the request
624
625
  * @returns {Promise<any>}
625
626
  *
626
627
  * @example
@@ -631,7 +632,7 @@ export function request(route: string, data?: {
631
632
  [key: string]: any;
632
633
  }, event?: {
633
634
  preventDefault?: Function;
634
- }, isLoading?: [boolean, (value: boolean) => void]): Promise<any>;
635
+ }, isLoading?: [boolean, (value: boolean) => void], setState?: SetState): Promise<any>;
635
636
  /**
636
637
  * Removes undefined from an array or object
637
638
  * @param {[]|{[key: string]: any}} variable
@@ -784,4 +785,5 @@ export type Image = {
784
785
  base64?: string;
785
786
  date?: number;
786
787
  };
788
+ export type SetState = import("react").Dispatch<import("react").SetStateAction<any>>;
787
789
  //# sourceMappingURL=util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../util.js"],"names":[],"mappings":"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"}
package/util.js CHANGED
@@ -4,6 +4,8 @@ import dateformat from 'dateformat'
4
4
  import { loadStripe } from '@stripe/stripe-js/pure.js' // pure removes ping
5
5
  import { twMerge as _twMerge } from 'tailwind-merge'
6
6
 
7
+ /** @typedef {import('react').Dispatch<import('react').SetStateAction<any>>} SetState */
8
+
7
9
  /** @type {{[key: string]: {[key: string]: string|true}}} */
8
10
  let queryObjectCache = {}
9
11
 
@@ -689,7 +691,7 @@ export function getCurrencyOptions (currencies) {
689
691
  /**
690
692
  * Returns an error from a state object matching the path
691
693
  * @param {{ errors?: { title: string, detail: string }[] }|undefined} state
692
- * @param {string} path
694
+ * @param {string|RegExp} path
693
695
  * @returns {{ title: string, detail: string }|undefined}
694
696
  */
695
697
  export function getErrorFromState (state, path) {
@@ -1403,13 +1405,14 @@ export function queryString (obj, _path='', _output) {
1403
1405
  * @param {{ [key: string]: any }} [data] - payload
1404
1406
  * @param {{preventDefault?: function}} [event] - event to prevent default
1405
1407
  * @param {[boolean, (value: boolean) => void]} [isLoading] - [isLoading, setIsLoading]
1408
+ * @param {SetState} [setState] - if passed, state.errors will be reset before the request
1406
1409
  * @returns {Promise<any>}
1407
1410
  *
1408
1411
  * @example
1409
1412
  * - request('post /api/user', { name: 'John' })
1410
1413
  * - request(`get /api/user/${id}`, undefined, e, isLoading)
1411
1414
  */
1412
- export async function request (route, data, event, isLoading) {
1415
+ export async function request (route, data, event, isLoading, setState) {
1413
1416
  try {
1414
1417
  if (event?.preventDefault) event.preventDefault()
1415
1418
  const uri = route.replace(/^(post|put|delete|get) /, '')
@@ -1426,7 +1429,7 @@ export async function request (route, data, event, isLoading) {
1426
1429
 
1427
1430
  // warning, not persisting through re-renders, but should be fine until loading is finished
1428
1431
  data = data || {}
1429
- delete data.errors
1432
+ if (setState) setState((/** @type {{[key: string]: any}} */prev) => ({ ...prev, errors: [] }))
1430
1433
 
1431
1434
  // Find out if the data has files?
1432
1435
  let hasFiles = false
@@ -1439,7 +1442,7 @@ export async function request (route, data, event, isLoading) {
1439
1442
 
1440
1443
  // If yes, convert to form data
1441
1444
  /** @type {FormData|undefined} */
1442
- const formData2 = hasFiles ? formData(data, { allowEmptyArrays: true, indices: true }) : undefined
1445
+ const formData2 = hasFiles ? formData({ ...data }, { allowEmptyArrays: true, indices: true }) : undefined
1443
1446
 
1444
1447
  // send the request
1445
1448
  const axiosPromise = (method === 'get' || method === 'delete')
@@ -1,139 +0,0 @@
1
- // @ts-nocheck
2
- // todo: finish tailwind conversion
3
- import * as util from 'nitro-web/util'
4
- import SvgTick from 'nitro-web/client/imgs/icons/tick.svg'
5
- import { Button, FormError, Field, Modal, Topbar, Tabbar } from 'nitro-web'
6
-
7
- export function SettingsAccount() {
8
- const isLoading = useState(false)
9
- const [removeModal, setRemoveModal] = useState()
10
- const [{user}, setStore] = sharedStore.useTracked()
11
- const [state, setState] = useState({
12
- avatar: user.avatar || '',
13
- email: user.email || '',
14
- firstName: user.firstName || '',
15
- lastName: user.lastName || '',
16
- })
17
-
18
- async function onSubmit (e) {
19
- try {
20
- const res = await util.request(`put /api/user/${user._id}?files=true`, state, e, isLoading)
21
- setStore((s) => ({ ...s, user: { ...s.user, ...res }, message: 'Saved successfully 👍️' }))
22
- } catch (errors) {
23
- return setState({ ...state, errors })
24
- }
25
- }
26
-
27
- return (
28
- <div css={style}>
29
- <Topbar
30
- title={<>Settings</>}
31
- submenu={
32
- <Tabbar class="is-underline"tabs={[
33
- { label: 'Business', path: '/settings/business' },
34
- { label: 'Team', path: '/settings/team' },
35
- { label: 'Account', path: '/settings/account' },
36
- ]} />
37
- }
38
- btns={
39
- <Button onClick={onSubmit} color="primary-sm" size="wide" IconLeft={SvgTick} isLoading={isLoading[0]}>
40
- Save Settings
41
- </Button>
42
- }
43
- />
44
- <div class="box p-box">
45
- <h3 class="h3">Account Info</h3>
46
-
47
- <form class="form" onSubmit={onSubmit}>
48
- <div class="cols cols-6 cols-gap-3">
49
- <div class="col">
50
- <label for="firstName">First Name(s)</label>
51
- <Field name="firstName" placeholder="E.g. Bruce" state={state} onChange={(e) => onChange(setState, e)} />
52
- </div>
53
- <div class="col">
54
- <label for="lastName">Last Name</label>
55
- <Field name="lastName" placeholder="E.g. Wayne" state={state} onChange={(e) => onChange(setState, e)} />
56
- </div>
57
- <div class="col">
58
- <label for="email">Email Address</label>
59
- <Field name="email" type="email" placeholder="Your email address..." state={state}
60
- onChange={(e) => onChange(setState, e)} />
61
- </div>
62
- <div class="col">
63
- <Link to="/reset" class="label-right link2 underline2 is-active">Reset Password?</Link>
64
- <label for="password">Password</label>
65
- <Field name="password" placeholder="•••••••••••" disabled={true} />
66
- </div>
67
- </div>
68
-
69
- <div class="py-0-5 mb-12">
70
- Warning: to remove all your data and delete your
71
- account, <a href="#" onClick={() => setRemoveModal(user)} class="link2 underline2 is-active">click here</a>.
72
- <FormError state={state} class="pt-2" />
73
- </div>
74
- </form>
75
- </div>
76
-
77
- <RemoveModal show={removeModal} setShow={setRemoveModal} />
78
- </div>
79
- )
80
- }
81
-
82
- export function RemoveModal ({ show, setShow }) {
83
- // @param {object} showModal - user
84
- const navigate = useNavigate()
85
- const isLoading = useState(false)
86
- const [, setStore] = sharedStore.useTracked()
87
- const [state, setState] = useState({})
88
-
89
- useEffect(() => {
90
- if (show?._id) setState({ _id: show._id })
91
- }, [show?._id])
92
-
93
- async function onSubmit (e) {
94
- try {
95
- await util.request(`delete /api/account/${state._id}`, null, e, isLoading)
96
- close()
97
- setStore(o => ({ ...o, message: 'Data deleted successfully, Goodbye 👋...' }))
98
- setTimeout(() => navigate('/signout'), 6000) // wait for setStore
99
- } catch (errors) {
100
- return setState({ ...state, errors })
101
- }
102
- }
103
-
104
- function close() {
105
- setShow(false)
106
- setTimeout(() => setState(false), 300)
107
- }
108
-
109
- return (
110
- <Modal show={show} setShow={close} css={style} class="p-modal-small" maxWidth={560} minHeight={0}>
111
- <h2 class="h2"><em>Delete</em> Your Account?</h2>
112
- <p class="text-paragraph py-2">
113
- This will remove all the data against your account and including all companies owned by you.<br/>
114
- <br/>
115
- <b>Warning:</b> This cannot be undone.
116
- </p>
117
- <form class="form" onSubmit={onSubmit}>
118
- <div class="py-0-5 mb-4">
119
- <FormError state={state} class="pt-2" />
120
- </div>
121
- <Button onClick={onSubmit} color="secondary-sm" isLoading={isLoading[0]}>
122
- Delete Account
123
- </Button>
124
- </form>
125
- </Modal>
126
- )
127
- }
128
-
129
- import { css } from 'twin.macro'
130
- const style = css`
131
- /* input[type='file'] {
132
- padding: 8px 18px;
133
- font-size: 12px;
134
- }
135
- .avatar {
136
- width: 38px;
137
- height: 38px;
138
- } */
139
- `
@@ -1,117 +0,0 @@
1
- //@ts-nocheck
2
- // todo: finish tailwind conversio
3
-
4
- ////// look at the select type error below
5
- import * as util from 'nitro-web/util'
6
- import SvgTick from 'nitro-web/client/imgs/icons/tick.svg'
7
- import { Button, Field, Select, Topbar, Tabbar, injectedConfig } from 'nitro-web'
8
-
9
- export function SettingsBusiness() {
10
- const isLoading = useState(false)
11
- const [{ user }, setStore] = sharedStore.useTracked()
12
- const [state, setState] = useState(() => {
13
- const company = user.company
14
- return {
15
- business: {
16
- address: company.business.address?.full || '',
17
- country: company.business.country || 'nz',
18
- currency: company.business.currency || 'nzd',
19
- name: company.business.name || '',
20
- number: company.business.number || '',
21
- phone: company.business.phone || '',
22
- website: company.business.website || '',
23
- },
24
- }
25
- })
26
-
27
- async function onSubmit (e) {
28
- try {
29
- const company = await util.request(`put /api/company/${user.company._id}`, state, e, isLoading)
30
- setStore((s) => ({ ...s, user: { ...s.user, company }, message: 'Saved successfully 👍️' }))
31
- } catch (errors) {
32
- console.log(errors)
33
- return setState({ ...state, errors })
34
- }
35
- }
36
-
37
- return (
38
- <div>
39
- <Topbar
40
- title={<>Settings</>}
41
- submenu={
42
- <Tabbar class="is-underline" tabs={[
43
- { label: 'Business', path: '/settings/business' },
44
- { label: 'Team', path: '/settings/team' },
45
- { label: 'Account', path: '/settings/account' },
46
- ]} />
47
- }
48
- btns={
49
- <Button onClick={onSubmit} color="primary-sm" size="wide" IconLeft={SvgTick} isLoading={isLoading[0]}>
50
- Save Settings
51
- </Button>
52
- }
53
- />
54
-
55
- <div class="box p-box">
56
- <h3 class="h3">Business Settings</h3>
57
-
58
- <form class="form" onSubmit={onSubmit}>
59
- <div class="cols cols-6 cols-gap-3">
60
- <div class="col">
61
- <label for="business.country">Country</label>
62
- <Select
63
- // https://github.com/lipis/flag-icons
64
- name="business.country"
65
- type="country"
66
- state={state}
67
- options={useMemo(() => util.getCountryOptions(injectedConfig.countries), [])}
68
- onChange={(e) => onChange(setState, e)}
69
- />
70
- </div>
71
- <div class="col">
72
- <label for="business.currency">Currency</label>
73
- <Select
74
- name="business.currency"
75
- type="country"
76
- state={state}
77
- options={useMemo(() => util.getCurrencyOptions(injectedConfig.currencies), [])}
78
- onChange={(e) => onChange(setState, e)}
79
- />
80
- </div>
81
- <div class="col">
82
- <label for="business.name">Trading Name</label>
83
- <Field name="business.name" placeholder="E.g. Wayne Enterprises" state={state} onChange={(e) => onChange(setState, e)} />
84
- </div>
85
- <div class="col">
86
- <Link to="#" class="label-right link2 underline2 is-active">Custom Address</Link>
87
- <label for="business.address">Address (Start Typing...)</label>
88
- <Field name="business.address.full" placeholder="" state={state} onChange={(e) => onChange(setState, e)} />
89
- </div>
90
- <div class="col">
91
- <label for="business.website">Website</label>
92
- <Field name="business.website" placeholder="https://" state={state} onChange={(e) => onChange(setState, e)} />
93
- </div>
94
- <div class="col">
95
- <label for="business.phone">Mobile Number</label>
96
- <Field name="business.phone" placeholder="" state={state} onChange={(e) => onChange(setState, e)} />
97
- </div>
98
- <div class="col">
99
- <Link to="#" class="label-right link2 underline2 is-active">What&apos;s this for?</Link>
100
- <label for="tax.number">GST Number</label>
101
- <Field class="mb-0" name="tax.number" placeholder="Appears on your documents" state={state}
102
- onChange={(e) => onChange(setState, e)} />
103
- </div>
104
- <div class="col">
105
- <Link to="#" class="label-right link2 underline2 is-active">What&apos;s this for?</Link>
106
- <label for="business.number">NZBN</label>
107
- <Field class="mb-0" name="business.number" type="text" rows="23" placeholder="Appears on your documents" state={state}
108
- onChange={(e) => onChange(setState, e)} />
109
- </div>
110
- </div>
111
- </form>
112
- </div>
113
-
114
- </div>
115
- )
116
- }
117
-
@@ -1,106 +0,0 @@
1
- // @ts-nocheck
2
- // todo: finish tailwind conversion
3
- import { Button, FormError, Field, Modal, Select, injectedConfig } from 'nitro-web'
4
- import SvgTick from 'nitro-web/client/imgs/icons/tick.svg'
5
-
6
- type SettingsTeamMemberProps = {
7
- showModal: boolean
8
- setShowModal: (showModal: boolean) => void
9
- }
10
-
11
- export function SettingsTeamMember ({ showModal, setShowModal }: SettingsTeamMemberProps) {
12
- // @param {object} showModal - user
13
- const [{ user }] = sharedStore.useTracked()
14
- const [isLoading] = useState(false)
15
- const [state, setState] = useState({
16
- business: {
17
- name: '',
18
- address: '',
19
- website: '',
20
- phone: '',
21
- },
22
- })
23
-
24
- // permit polit changes
25
- // typescripty,
26
-
27
- function onSubmit(_e) {
28
- //... save
29
- }
30
-
31
- return (
32
- <Modal show={showModal} setShow={setShowModal} class="p-modal">
33
-
34
- <h2 class="h2"><em>Add</em> Team Member</h2>
35
- <p class="subtitle">Invite a new team member to collaborate with you on {injectedConfig?.name || 'Nitro'}.</p>
36
-
37
- <form class="form" onSubmit={onSubmit}>
38
- <div class="cols cols-6 cols-gap-2-5">
39
- <div class="col">
40
- <label for="role">Member Role</label>
41
- <Select
42
- name="role"
43
- isSearchable={false}
44
- placeholder="Select a role"
45
- onChange={(e) => onChange(setState, e)}
46
- state={state}
47
- minMenuWidth={460}
48
- options={[
49
- {
50
- className: 'bb',
51
- value: 'owner',
52
- labelControl: 'Owner',
53
- label: <>
54
- <div class="mb-0-5"><b>Owner</b></div>
55
- <div>Full access.</div>
56
- </>,
57
- },
58
- {
59
- className: 'bb',
60
- value: 'manager',
61
- labelControl: 'Manager',
62
- label: <>
63
- <div class="mb-0-5"><b>Manager</b></div>
64
- <div>No access to billing or the ability to remove your account.</div>
65
- </>,
66
- },
67
- ]}
68
- />
69
- </div>
70
- <div class="col">
71
- <label for="email">Email Address</label>
72
- <Field
73
- name="email" type="email" placeholder="Your email address..." state={state}
74
- onChange={(e) => onChange(setState, e)}
75
- />
76
- </div>
77
- <div class="col">
78
- <label for="firstName">First Name</label>
79
- <Field name="firstName" placeholder="E.g. Bruce" state={state} onChange={(e) => onChange(setState, e)} />
80
- </div>
81
- <div class="col">
82
- <label for="lastName">Last Name</label>
83
- <Field name="lastName" placeholder="E.g. Wayne" state={state} onChange={(e) => onChange(setState, e)} />
84
- </div>
85
- <div class="col-12">
86
- <label for="message">Invitation Message</label>
87
- <Field
88
- name="message"
89
- type="textarea"
90
- placeholder={`${user.firstName} is inviting you to collaborate on ${injectedConfig?.name || 'Nitro'}.`}
91
- state={state}
92
- onChange={(e) => onChange(setState, e)}
93
- />
94
- </div>
95
- </div>
96
-
97
- <div class="py-0-5 mb-4">
98
- <FormError state={state} class="pt-2" />
99
- </div>
100
- <Button onClick={onSubmit} color="primary-sm" IconLeft={SvgTick} isLoading={isLoading[0]}>
101
- Send Invitation
102
- </Button>
103
- </form>
104
- </Modal>
105
- )
106
- }
@@ -1,72 +0,0 @@
1
- // @ts-nocheck
2
- // todo: finish tailwind conversion
3
- import * as util from 'nitro-web/util'
4
- import SvgPlus from 'nitro-web/client/imgs/icons/plus.svg'
5
- import { Button, Table, Avatar, Tabbar, Topbar, SettingsTeamMember, injectedConfig } from 'nitro-web'
6
-
7
- export function SettingsTeam() {
8
- const isLoading = useState(false)
9
- const [showModal, setShowModal] = useState()
10
- const [{ user }] = sharedStore.useTracked()
11
- const [state] = useState({
12
- users: user?.company?.users || [],
13
- })
14
-
15
- function addTeamMember() {
16
- //... open modal
17
- }
18
-
19
- return (
20
- <div>
21
- <Topbar
22
- title={<>Settings</>}
23
- submenu={
24
- <Tabbar class="is-underline" tabs={[
25
- { label: 'Business', path: '/settings/business' },
26
- { label: 'Team', path: '/settings/team' },
27
- { label: 'Account', path: '/settings/account' },
28
- ]} />
29
- }
30
- btns={
31
- <Button onClick={addTeamMember} color="primary-sm" IconLeft={SvgPlus} isLoading={isLoading[0]}>
32
- Add Team Member
33
- </Button>
34
- }
35
- />
36
-
37
- <Table
38
- columns={[
39
- { label: 'Member\'s Name', key: 'name', width: 1 },
40
- { label: 'Email', key: 'email' },
41
- { label: 'Joined On', key: 'joinedOn', align: 'center' },
42
- { label: 'Role', key: 'role', width: '110px' },
43
- ]}
44
- rowOnClick={(e, user) => setShowModal(user)}
45
- rows={
46
- state.users.map(user => ({
47
- ...user,
48
- key: user._id,
49
- name: (
50
- <>
51
- <Avatar awsUrl={injectedConfig.awsUrl} user={user} isRound={true} class="mt--1 mb--1" />
52
- <b>{util.ucFirst(user.name)}</b>
53
- {user.status != 'invited' && <span class="text-grey">(Invitation pending)</span>}
54
- </>
55
- ),
56
- joinedOn: user.status == 'invited' ? <a href="#">Resend Invite</a> : util.date(user.createdAt),
57
- role: util.ucFirst(user.role),
58
- }))
59
- }
60
- actions={[
61
- { label: 'Remove', onClick: (_row, _i) => console.log('remove') },
62
- ]}
63
- actionsAll={[
64
- { label: 'Remove All', onClick: () => console.log('remove all') },
65
- ]}
66
- />
67
-
68
- {/* Member modal */}
69
- <SettingsTeamMember showModal={showModal} setShowModal={setShowModal} />
70
- </div>
71
- )
72
- }
@@ -1,51 +0,0 @@
1
- // @ts-nocheck
2
- import db from 'monastery'
3
-
4
- export const routes = {
5
- 'put /api/company/:cid': ['isCompanyUser', update],
6
- 'put /api/user/:uid': ['isUser', updateUser],
7
- }
8
-
9
- async function update(req, res) {
10
- try {
11
- const update = await db.company.update({
12
- query: req.params.cid,
13
- data: req.body,
14
- files: req.query.files ? req.files : undefined,
15
- })
16
- if (!update) {
17
- throw new Error('Coudln\'t find the company to update')
18
- }
19
- const company = await db.company.findOne({
20
- query: req.params.cid,
21
- populate: db.company.loginPopulate(),
22
- _privateData: true,
23
- })
24
- res.json(company)
25
-
26
- } catch (errs) {
27
- res.error(errs)
28
- }
29
- }
30
-
31
- async function updateUser(req, res) {
32
- try {
33
- const update = await db.user.update({
34
- query: req.params.uid,
35
- data: req.body,
36
- files: req.query.files ? req.files : undefined,
37
- })
38
- if (!update) {
39
- throw new Error('Coudln\'t find the user to update')
40
- }
41
- const user = await db.user.findOne({
42
- query: req.params.uid,
43
- _privateData: true,
44
- blacklist: ['company'], // don't return the company id
45
- })
46
- res.json(user)
47
-
48
- } catch (errs) {
49
- res.error(errs)
50
- }
51
- }