nitro-web 0.0.29 → 0.0.31

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.
@@ -13,256 +13,258 @@ export default {
13
13
  'post /api/stripe/create-billing-portal-session': ['isUser', 'billingPortalSessionCreate'],
14
14
  'get /api/stripe/upcoming-invoices': ['isUser', 'upcomingInvoicesFind'],
15
15
  },
16
+ setup: setup,
17
+ stripeWebhook: stripeWebhook,
18
+ billingPortalSessionCreate: billingPortalSessionCreate,
19
+ upcomingInvoicesFind: upcomingInvoicesFind,
20
+ }
16
21
 
17
- setup: function (middleware, _config) {
18
- // Set config values
19
- config = {
20
- env: _config.env,
21
- clientUrl: _config.clientUrl,
22
- stripeSecretKey: _config.stripeSecretKey,
23
- stripeWebhookSecret: _config.stripeWebhookSecret,
24
- }
25
- for (let key in config) {
26
- if (!config[key]) {
27
- throw new Error(`Missing config value for stripe.api.js: ${key}`)
28
- }
29
- }
30
- stripe = new Stripe(config.stripeSecretKey)
31
- },
32
-
33
- stripeWebhook: async function (req, res) {
34
- try {
35
- var event = config.env == 'development' ? req.body : stripe.webhooks.constructEvent(
36
- req.rawBody,
37
- req.rawHeaders['stripe-signature'],
38
- config.stripeWebhookSecret
39
- )
40
- } catch (err) {
41
- if (err && err.message) console.log(err.message)
42
- else console.log(err)
43
- return res.error(err)
22
+ function setup(middleware, _config) {
23
+ // Set config values
24
+ config = {
25
+ env: _config.env,
26
+ clientUrl: _config.clientUrl,
27
+ stripeSecretKey: _config.stripeSecretKey,
28
+ stripeWebhookSecret: _config.stripeWebhookSecret,
29
+ }
30
+ for (let key in config) {
31
+ if (!config[key]) {
32
+ throw new Error(`Missing config value for stripe.api.js: ${key}`)
44
33
  }
34
+ }
35
+ stripe = new Stripe(config.stripeSecretKey)
36
+ }
45
37
 
46
- if (!event.data || !event.data.object) {
47
- return res.status(400).send(`Missing webhook data: ${event}.`)
48
- }
38
+ async function stripeWebhook(req, res) {
39
+ try {
40
+ var event = config.env == 'development' ? req.body : stripe.webhooks.constructEvent(
41
+ req.rawBody,
42
+ req.rawHeaders['stripe-signature'],
43
+ config.stripeWebhookSecret
44
+ )
45
+ } catch (err) {
46
+ if (err && err.message) console.log(err.message)
47
+ else console.log(err)
48
+ return res.error(err)
49
+ }
49
50
 
50
- // useful for cleaning failed webhooks
51
- if (req.query.success) return true
52
- // console.log('event.type: ', event.type)
51
+ if (!event.data || !event.data.object) {
52
+ return res.status(400).send(`Missing webhook data: ${event}.`)
53
+ }
53
54
 
54
- // Stripe cannot guarantee event order
55
- switch (event.type) {
56
- case 'customer.subscription.created':
57
- case 'customer.subscription.updated':
58
- case 'customer.subscription.deleted':
59
- // Subscriptions can be renewed which resurrects cancelled subscriptions.. ignore this
60
- console.log('Event: ' + event.type)
61
- this._webhookSubUpdated(req, res, event)
62
- break
63
- case 'customer.created': // customer created by subscribing
64
- case 'customer.updated': // payment method changes
65
- console.log('Event: ' + event.type)
66
- this._webhookCustomerCreatedUpdated(req, res, event)
67
- break
68
- default:
69
- res.status(400).send(`Unsupported type: ${event}.`)
70
- break
71
- }
72
- },
55
+ // useful for cleaning failed webhooks
56
+ if (req.query.success) return true
57
+ // console.log('event.type: ', event.type)
73
58
 
74
- billingPortalSessionCreate: async function (req, res) {
75
- try {
76
- if (!req.user.stripeCustomer?.id) {
77
- throw new Error('No stripe customer found for the user')
78
- }
79
- const session = await stripe.billingPortal.sessions.create({
80
- customer: req.user.stripeCustomer.id,
81
- return_url: config.clientUrl + '/subscriptions',
82
- })
83
- res.json(session.url)
84
- } catch (err) {
85
- this._error(req, res, err)
86
- }
87
- },
59
+ // Stripe cannot guarantee event order
60
+ switch (event.type) {
61
+ case 'customer.subscription.created':
62
+ case 'customer.subscription.updated':
63
+ case 'customer.subscription.deleted':
64
+ // Subscriptions can be renewed which resurrects cancelled subscriptions.. ignore this
65
+ console.log('Event: ' + event.type)
66
+ webhookSubUpdated(req, res, event)
67
+ break
68
+ case 'customer.created': // customer created by subscribing
69
+ case 'customer.updated': // payment method changes
70
+ console.log('Event: ' + event.type)
71
+ webhookCustomerCreatedUpdated(req, res, event)
72
+ break
73
+ default:
74
+ res.status(400).send(`Unsupported type: ${event}.`)
75
+ break
76
+ }
77
+ }
88
78
 
89
- upcomingInvoicesFind: async function (req, res) {
90
- try {
91
- if (!req.user.stripeCustomer?.id) return res.json({})
92
- const nextInvoice = await stripe.invoices.retrieveUpcoming({
93
- customer: req.user.stripeCustomer.id,
94
- })
95
- res.json(nextInvoice)
96
- } catch (err) {
97
- if (err.code == 'invoice_upcoming_none') return res.json({})
98
- this._error(req, res, err)
79
+ async function billingPortalSessionCreate(req, res) {
80
+ try {
81
+ if (!req.user.stripeCustomer?.id) {
82
+ throw new Error('No stripe customer found for the user')
99
83
  }
100
- },
101
-
102
- /* Private webhook actions */
84
+ const session = await stripe.billingPortal.sessions.create({
85
+ customer: req.user.stripeCustomer.id,
86
+ return_url: config.clientUrl + '/subscriptions',
87
+ })
88
+ res.json(session.url)
89
+ } catch (err) {
90
+ error(req, res, err)
91
+ }
92
+ }
103
93
 
104
- _webhookCustomerCreatedUpdated: async function (req, res, event) {
105
- try {
106
- const customer = event.data.object
107
- const user = await this._getUserFromEvent(event)
108
- const customerExpanded = await stripe.customers.retrieve(
109
- customer.id,
110
- { expand: ['invoice_settings.default_payment_method'] }
111
- )
112
- await db.user.update({
113
- query: user._id,
114
- data: { stripeCustomer: customerExpanded },
115
- blacklist: ['-stripeCustomer'],
116
- })
117
- res.json({})
118
- } catch (err) {
119
- console.log(err)
120
- this._error(req, res, err)
121
- }
122
- },
94
+ async function upcomingInvoicesFind(req, res) {
95
+ try {
96
+ if (!req.user.stripeCustomer?.id) return res.json({})
97
+ const nextInvoice = await stripe.invoices.retrieveUpcoming({
98
+ customer: req.user.stripeCustomer.id,
99
+ })
100
+ res.json(nextInvoice)
101
+ } catch (err) {
102
+ if (err.code == 'invoice_upcoming_none') return res.json({})
103
+ error(req, res, err)
104
+ }
105
+ }
123
106
 
124
- _webhookSubUpdated: async function (req, res, event) {
125
- // Update the subscription on the company
126
- try {
127
- const subData = event.data.object
128
- // webhook from deleting a company?
129
- if (subData.cancellation_details.comment == 'company deleted') {
130
- return res.json({})
131
- }
107
+ /* Private webhook actions */
132
108
 
133
- const user = await this._getUserFromEvent(event)
134
- if (!user.company) {
135
- throw new Error(`Subscription user has no company to update the subscription (${subData.id}) onto`)
136
- }
109
+ async function webhookCustomerCreatedUpdated(req, res, event) {
110
+ try {
111
+ const customer = event.data.object
112
+ const user = await getUserFromEvent(event)
113
+ const customerExpanded = await stripe.customers.retrieve(
114
+ customer.id,
115
+ { expand: ['invoice_settings.default_payment_method'] }
116
+ )
117
+ await db.user.update({
118
+ query: user._id,
119
+ data: { stripeCustomer: customerExpanded },
120
+ blacklist: ['-stripeCustomer'],
121
+ })
122
+ res.json({})
123
+ } catch (err) {
124
+ console.log(err)
125
+ error(req, res, err)
126
+ }
127
+ }
137
128
 
138
- // Ignoring incomplete subscriptions
139
- if (subData.status.match(/incomplete/)) {
140
- return res.json({})
141
- // Ignoring subscriptions without companyId (e.g. manual subscriptions)
142
- } else if (!subData.metadata.companyId) {
143
- return res.json({ ignoringManualSubscriptions: true })
144
- // Ignoring old subscriptions
145
- } else if (subData.created < (user.company.stripeSubscription?.created || 0)) {
146
- return res.json({ ignoringOldSubscriptions: true })
147
- }
148
-
149
- // Update company with the updated subscription and users
150
- const sub = await stripe.subscriptions.retrieve(
151
- subData.id,
152
- { expand: ['latest_invoice.payment_intent'] }
153
- )
154
- await db.company.update({
155
- query: user.company._id,
156
- data: { stripeSubscription: sub, users: user.company.users },
157
- blacklist: ['-stripeSubscription', '-users'],
158
- })
159
-
160
- res.json({})
161
- } catch (err) {
162
- console.error(err)
163
- this._error(req, res, err)
129
+ async function webhookSubUpdated(req, res, event) {
130
+ // Update the subscription on the company
131
+ try {
132
+ const subData = event.data.object
133
+ // webhook from deleting a company?
134
+ if (subData.cancellation_details.comment == 'company deleted') {
135
+ return res.json({})
164
136
  }
165
- },
166
-
167
- /* Private */
168
137
 
169
- _getUserFromEvent: async function (event) {
170
- // User retreived from the event's customer.
171
- // The customer is created before the paymentIntent and subscriptionIntent is set up
172
- let object = event.data.object
173
- let customerId = object.object == 'customer'? object.id : object.customer
174
- if (customerId) {
175
- var user = await db.user.findOne({
176
- query: { 'stripeCustomer.id': customerId },
177
- populate: db.user.populate({}),
178
- blacklist: false, // ['-company.users.inviteToken'],
179
- })
138
+ const user = await getUserFromEvent(event)
139
+ if (!user.company) {
140
+ throw new Error(`Subscription user has no company to update the subscription (${subData.id}) onto`)
180
141
  }
181
- if (!user) {
182
- await db.log.insert({ data: {
183
- date: Date.now(),
184
- event: event.type,
185
- message: `Cannot find user with id: ${customerId}.`,
186
- }})
187
- throw new Error(`Cannot find user with id: ${customerId}.`)
188
- }
189
- // populate company owner with user data (handy for _addSubscriptionBillingChange)
190
- if (user.company?.users) {
191
- user.company.users = user.company.users.map(o => {
192
- if (o.role == 'owner' && o._id.toString() == user._id.toString()) {
193
- o.firstName = user.firstName
194
- o.name = user.name
195
- o.email = user.email
196
- }
197
- return o
198
- })
142
+
143
+ // Ignoring incomplete subscriptions
144
+ if (subData.status.match(/incomplete/)) {
145
+ return res.json({})
146
+ // Ignoring subscriptions without companyId (e.g. manual subscriptions)
147
+ } else if (!subData.metadata.companyId) {
148
+ return res.json({ ignoringManualSubscriptions: true })
149
+ // Ignoring old subscriptions
150
+ } else if (subData.created < (user.company.stripeSubscription?.created || 0)) {
151
+ return res.json({ ignoringOldSubscriptions: true })
199
152
  }
200
- return user
201
- },
153
+
154
+ // Update company with the updated subscription and users
155
+ const sub = await stripe.subscriptions.retrieve(
156
+ subData.id,
157
+ { expand: ['latest_invoice.payment_intent'] }
158
+ )
159
+ await db.company.update({
160
+ query: user.company._id,
161
+ data: { stripeSubscription: sub, users: user.company.users },
162
+ blacklist: ['-stripeSubscription', '-users'],
163
+ })
164
+
165
+ res.json({})
166
+ } catch (err) {
167
+ console.error(err)
168
+ error(req, res, err)
169
+ }
170
+ }
202
171
 
203
- _getProducts: async function () {
204
- /**
205
- * Returns all products and caches it on the app
206
- * @returns {Array} products
207
- */
208
- try {
209
- if (stripeProducts) return stripeProducts
210
- if (!config.stripeSecretKey) {
211
- stripeProducts = []
212
- throw new Error('Missing process.env.stripeSecretKey for retrieving products')
172
+ async function getUserFromEvent(event) {
173
+ // User retreived from the event's customer.
174
+ // The customer is created before the paymentIntent and subscriptionIntent is set up
175
+ let object = event.data.object
176
+ let customerId = object.object == 'customer'? object.id : object.customer
177
+ if (customerId) {
178
+ var user = await db.user.findOne({
179
+ query: { 'stripeCustomer.id': customerId },
180
+ populate: db.user.populate({}),
181
+ blacklist: false, // ['-company.users.inviteToken'],
182
+ })
183
+ }
184
+ if (!user) {
185
+ await db.log.insert({ data: {
186
+ date: Date.now(),
187
+ event: event.type,
188
+ message: `Cannot find user with id: ${customerId}.`,
189
+ }})
190
+ throw new Error(`Cannot find user with id: ${customerId}.`)
191
+ }
192
+ // populate company owner with user data (handy for _addSubscriptionBillingChange)
193
+ if (user.company?.users) {
194
+ user.company.users = user.company.users.map(o => {
195
+ if (o.role == 'owner' && o._id.toString() == user._id.toString()) {
196
+ o.firstName = user.firstName
197
+ o.name = user.name
198
+ o.email = user.email
213
199
  }
200
+ return o
201
+ })
202
+ }
203
+ return user
204
+ }
214
205
 
215
- let products = (await stripe.products.list({ limit: 100, active: true })).data
216
- let prices = (await stripe.prices.list({ limit: 100, active: true, expand: ['data.tiers'] })).data
217
-
218
- return (stripeProducts = products.map((product) => ({
219
- // remove default_price when new pricing is ready
220
- ...util.pick(product, ['id', 'created', 'default_price', 'description', 'name', 'metadata']),
221
- type: product.name.match(/housing/i) ? 'project' : 'subscription', // overwriting, was 'service'
222
- prices: prices
223
- .filter((price) => price.product == product.id)
224
- .map((price) => ({
225
- ...util.pick(price, ['id', 'product', 'nickname', 'recurring', 'unit_amount', 'tiers', 'tiers_mode']),
226
- interval: price.recurring?.interval, // 'year', 'month', undefined
227
- })),
228
- })))
229
- } catch (err) {
230
- console.error(new Error(err)) // when stripe throws errors, the callstack is missing.
231
- return []
206
+ export async function getProducts() {
207
+ /**
208
+ * Returns all products and caches it on the app
209
+ * @returns {Array} products
210
+ */
211
+ try {
212
+ if (stripeProducts) return stripeProducts
213
+ if (!config.stripeSecretKey) {
214
+ stripeProducts = []
215
+ throw new Error('Missing process.env.stripeSecretKey for retrieving products')
232
216
  }
233
- },
234
217
 
235
- _createOrUpdateCustomer: async function (user, paymentMethod=null) {
236
- /**
237
- * Creates or updates a stripe customer and saves it to the user
238
- * @param {Object} user - user
239
- * @param {String} paymentMethod - stripe payment method id to save to the customer
240
- * @called before paymentIntent and subscriptionIntent, and after completion with paymentMethod
241
- * @returns mutates user
242
- */
243
- const data = {
244
- email: user.email,
245
- name: user.name,
246
- address: { country: 'NZ' },
247
- ...(!paymentMethod ? {} : { invoice_settings: { default_payment_method: paymentMethod }}),
248
- expand: ['invoice_settings.default_payment_method', 'tax'], // expands card object
249
- }
250
-
251
- if (user.stripeCustomer) var customer = await stripe.customers.update(user.stripeCustomer.id, data)
252
- else customer = await stripe.customers.create({ ...data })
218
+ let products = (await stripe.products.list({ limit: 100, active: true })).data
219
+ let prices = (await stripe.prices.list({ limit: 100, active: true, expand: ['data.tiers'] })).data
253
220
 
254
- user.stripeCustomer = customer
255
- await db.user.update({
256
- query: user._id,
257
- data: { stripeCustomer: customer },
258
- blacklist: ['-stripeCustomer'],
259
- })
260
- },
221
+ return (stripeProducts = products.map((product) => ({
222
+ // remove default_price when new pricing is ready
223
+ ...util.pick(product, ['id', 'created', 'default_price', 'description', 'name', 'metadata']),
224
+ type: product.name.match(/housing/i) ? 'project' : 'subscription', // overwriting, was 'service'
225
+ prices: prices
226
+ .filter((price) => price.product == product.id)
227
+ .map((price) => ({
228
+ ...util.pick(price, ['id', 'product', 'nickname', 'recurring', 'unit_amount', 'tiers', 'tiers_mode']),
229
+ interval: price.recurring?.interval, // 'year', 'month', undefined
230
+ })),
231
+ })))
232
+ } catch (err) {
233
+ console.error(new Error(err)) // when stripe throws errors, the callstack is missing.
234
+ return []
235
+ }
236
+ }
261
237
 
262
- _error: async function (req, res, err) {
263
- if (err && err.response && err.response.body) console.log(err.response.body)
264
- if (util.isString(err) && err.match(/Cannot find company with id/)) {
265
- res.json({ user: 'no company found' })
266
- } else res.error(err)
267
- },
238
+ // async function createOrUpdateCustomer(user, paymentMethod=null) {
239
+ // /**
240
+ // * Creates or updates a stripe customer and saves it to the user
241
+ // * @param {Object} user - user
242
+ // * @param {String} paymentMethod - stripe payment method id to save to the customer
243
+ // * @called before paymentIntent and subscriptionIntent, and after completion with paymentMethod
244
+ // * @returns mutates user
245
+ // */
246
+ // const data = {
247
+ // email: user.email,
248
+ // name: user.name,
249
+ // address: { country: 'NZ' },
250
+ // ...(!paymentMethod ? {} : { invoice_settings: { default_payment_method: paymentMethod }}),
251
+ // expand: ['invoice_settings.default_payment_method', 'tax'], // expands card object
252
+ // }
253
+
254
+ // if (user.stripeCustomer) var customer = await stripe.customers.update(user.stripeCustomer.id, data)
255
+ // else customer = await stripe.customers.create({ ...data })
256
+
257
+ // user.stripeCustomer = customer
258
+ // await db.user.update({
259
+ // query: user._id,
260
+ // data: { stripeCustomer: customer },
261
+ // blacklist: ['-stripeCustomer'],
262
+ // })
263
+ // }
264
+
265
+ async function error(req, res, err) {
266
+ if (err && err.response && err.response.body) console.log(err.response.body)
267
+ if (util.isString(err) && err.match(/Cannot find company with id/)) {
268
+ res.json({ user: 'no company found' })
269
+ } else res.error(err)
268
270
  }
@@ -1,10 +1,11 @@
1
1
  import { css, theme } from 'twin.macro'
2
+ import { injectedConfig } from 'nitro-web'
2
3
 
3
- export function Dashboard({ config }: { config: { isStatic?: boolean } }) {
4
+ export function Dashboard() {
4
5
  const [store] = useTracked()
5
- const textColor = store.apiAvailable ? 'text-green-700' : config.isStatic ? 'text-gray-700' : 'text-pink-700'
6
- const fillColor = store.apiAvailable ? 'fill-green-500' : config.isStatic ? 'fill-gray-500' : 'fill-pink-500'
7
- const bgColor = store.apiAvailable ? 'bg-green-100' : config.isStatic ? 'bg-[#eeeeee]' : 'bg-pink-100'
6
+ const textColor = store.apiAvailable ? 'text-green-700' : injectedConfig.isStatic ? 'text-gray-700' : 'text-pink-700'
7
+ const fillColor = store.apiAvailable ? 'fill-green-500' : injectedConfig.isStatic ? 'fill-gray-500' : 'fill-pink-500'
8
+ const bgColor = store.apiAvailable ? 'bg-green-100' : injectedConfig.isStatic ? 'bg-[#eeeeee]' : 'bg-pink-100'
8
9
 
9
10
  return (
10
11
  <div css={style}>
@@ -17,7 +18,7 @@ export function Dashboard({ config }: { config: { isStatic?: boolean } }) {
17
18
  <svg viewBox="0 0 6 6" aria-hidden="true" className={`size-1.5 ${fillColor}`}>
18
19
  <circle r={3} cx={3} cy={3} />
19
20
  </svg>
20
- { store.apiAvailable ? 'API Available' : `API Unavailable${config.isStatic ? ' (Static Example)' : ''}` }
21
+ { store.apiAvailable ? 'API Available' : `API Unavailable${injectedConfig.isStatic ? ' (Static Example)' : ''}` }
21
22
  </span>
22
23
  </p>
23
24
  </div>
@@ -1,9 +1,8 @@
1
1
  import { Drop, Dropdown, Field, Select, Button, Checkbox, GithubLink, Modal, Calendar, injectedConfig } from 'nitro-web'
2
2
  import { getCountryOptions, getCurrencyOptions, ucFirst } from 'nitro-web/util'
3
3
  import { CheckIcon } from '@heroicons/react/20/solid'
4
- import { Config } from 'nitro-web/types'
5
4
 
6
- export function Styleguide({ config }: { config: Config }) {
5
+ export function Styleguide() {
7
6
  const [customerSearch, setCustomerSearch] = useState('')
8
7
  const [showModal1, setShowModal1] = useState(false)
9
8
  const [state, setState] = useState({
@@ -167,7 +166,7 @@ export function Styleguide({ config }: { config: Config }) {
167
166
  name="country"
168
167
  type="country"
169
168
  state={state}
170
- options={useMemo(() => getCountryOptions(config.countries), [])}
169
+ options={useMemo(() => getCountryOptions(injectedConfig.countries), [])}
171
170
  onChange={onInputChange}
172
171
  />
173
172
  </div>
@@ -204,7 +203,7 @@ export function Styleguide({ config }: { config: Config }) {
204
203
  <Select
205
204
  name="currency"
206
205
  state={state}
207
- options={useMemo(() => getCurrencyOptions(config.currencies), [])}
206
+ options={useMemo(() => getCurrencyOptions(injectedConfig.currencies), [])}
208
207
  onChange={onInputChange}
209
208
  />
210
209
  </div>
@@ -249,7 +248,8 @@ export function Styleguide({ config }: { config: Config }) {
249
248
  </div>
250
249
  <div>
251
250
  <label for="amount">Amount ({state.amount})</label>
252
- <Field name="amount" type="currency" state={state} currency={state.currency || 'nzd'} onChange={onInputChange} config={config} />
251
+ <Field name="amount" type="currency" state={state} currency={state.currency || 'nzd'} onChange={onInputChange}
252
+ config={injectedConfig} />
253
253
  </div>
254
254
  </div>
255
255
 
@@ -273,7 +273,7 @@ export function Styleguide({ config }: { config: Config }) {
273
273
  <div class="grid grid-cols-3 gap-x-6 mb-4">
274
274
  <div>
275
275
  <label for="avatar">Avatar</label>
276
- <Drop class="is-small" name="avatar" state={state} onChange={onInputChange} awsUrl={config.awsUrl} />
276
+ <Drop class="is-small" name="avatar" state={state} onChange={onInputChange} awsUrl={injectedConfig.awsUrl} />
277
277
  </div>
278
278
  <div>
279
279
  <label for="calendar">Calendar</label>
@@ -4,9 +4,9 @@
4
4
  ////// look at the select type error below
5
5
  import * as util from 'nitro-web/util'
6
6
  import SvgTick from 'nitro-web/client/imgs/icons/tick.svg'
7
- import { Button, Field, Select, Topbar, Tabbar } from 'nitro-web'
7
+ import { Button, Field, Select, Topbar, Tabbar, injectedConfig } from 'nitro-web'
8
8
 
9
- export function SettingsBusiness({ config }) {
9
+ export function SettingsBusiness() {
10
10
  const isLoading = useState(false)
11
11
  const [{ user }, setStore] = sharedStore.useTracked()
12
12
  const [state, setState] = useState(() => {
@@ -64,7 +64,7 @@ export function SettingsBusiness({ config }) {
64
64
  name="business.country"
65
65
  type="country"
66
66
  state={state}
67
- options={useMemo(() => util.getCountryOptions(config.countries), [])}
67
+ options={useMemo(() => util.getCountryOptions(injectedConfig.countries), [])}
68
68
  onChange={onChange.bind(setState)}
69
69
  />
70
70
  </div>
@@ -74,7 +74,7 @@ export function SettingsBusiness({ config }) {
74
74
  name="business.currency"
75
75
  type="country"
76
76
  state={state}
77
- options={useMemo(() => util.getCurrencyOptions(config.currencies), [])}
77
+ options={useMemo(() => util.getCurrencyOptions(injectedConfig.currencies), [])}
78
78
  onChange={onChange.bind(setState)}
79
79
  />
80
80
  </div>
@@ -1,16 +1,14 @@
1
1
  // @ts-nocheck
2
2
  // todo: finish tailwind conversion
3
- import { Button, FormError, Field, Modal, Select } from 'nitro-web'
3
+ import { Button, FormError, Field, Modal, Select, injectedConfig } from 'nitro-web'
4
4
  import SvgTick from 'nitro-web/client/imgs/icons/tick.svg'
5
- import { Config } from 'nitro-web/types'
6
5
 
7
6
  type SettingsTeamMemberProps = {
8
7
  showModal: boolean
9
8
  setShowModal: (showModal: boolean) => void
10
- config?: Config
11
9
  }
12
10
 
13
- export function SettingsTeamMember ({ showModal, setShowModal, config }: SettingsTeamMemberProps) {
11
+ export function SettingsTeamMember ({ showModal, setShowModal }: SettingsTeamMemberProps) {
14
12
  // @param {object} showModal - user
15
13
  const [{ user }] = sharedStore.useTracked()
16
14
  const [isLoading] = useState(false)
@@ -34,7 +32,7 @@ export function SettingsTeamMember ({ showModal, setShowModal, config }: Setting
34
32
  <Modal show={showModal} setShow={setShowModal} class="p-modal">
35
33
 
36
34
  <h2 class="h2"><em>Add</em> Team Member</h2>
37
- <p class="subtitle">Invite a new team member to collaborate with you on {config?.name || 'Nitro'}.</p>
35
+ <p class="subtitle">Invite a new team member to collaborate with you on {injectedConfig?.name || 'Nitro'}.</p>
38
36
 
39
37
  <form class="form" onSubmit={onSubmit}>
40
38
  <div class="cols cols-6 cols-gap-2-5">
@@ -89,7 +87,7 @@ export function SettingsTeamMember ({ showModal, setShowModal, config }: Setting
89
87
  <Field
90
88
  name="message"
91
89
  type="textarea"
92
- placeholder={`${user.firstName} is inviting you to collaborate on ${config?.name || 'Nitro'}.`}
90
+ placeholder={`${user.firstName} is inviting you to collaborate on ${injectedConfig?.name || 'Nitro'}.`}
93
91
  state={state} onChange={onChange.bind(setState)}
94
92
  />
95
93
  </div>
@@ -2,9 +2,9 @@
2
2
  // todo: finish tailwind conversion
3
3
  import * as util from 'nitro-web/util'
4
4
  import SvgPlus from 'nitro-web/client/imgs/icons/plus.svg'
5
- import { Button, Table, Avatar, Tabbar, Topbar, SettingsTeamMember } from 'nitro-web'
5
+ import { Button, Table, Avatar, Tabbar, Topbar, SettingsTeamMember, injectedConfig } from 'nitro-web'
6
6
 
7
- export function SettingsTeam({ config }) {
7
+ export function SettingsTeam() {
8
8
  const isLoading = useState(false)
9
9
  const [showModal, setShowModal] = useState()
10
10
  const [{ user }] = sharedStore.useTracked()
@@ -48,7 +48,7 @@ export function SettingsTeam({ config }) {
48
48
  key: user._id,
49
49
  name: (
50
50
  <>
51
- <Avatar awsUrl={config.awsUrl} user={user} isRound={true} class="mt--1 mb--1" />
51
+ <Avatar awsUrl={injectedConfig.awsUrl} user={user} isRound={true} class="mt--1 mb--1" />
52
52
  <b>{util.ucFirst(user.name)}</b>
53
53
  {user.status != 'invited' && <span class="text-grey">(Invitation pending)</span>}
54
54
  </>