@licklist/design 0.78.5-dev.2 → 0.78.5-dev.23

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 (72) hide show
  1. package/dist/CustomDatePicker/CustomDatePicker.d.ts +10 -0
  2. package/dist/CustomDatePicker/CustomDatePicker.d.ts.map +1 -0
  3. package/dist/auth/ChangePassword/ChangePasswordComponent.d.ts.map +1 -1
  4. package/dist/auth/ChangePassword/ChangePasswordComponent.js +5 -4
  5. package/dist/auth/Layout/UserNavDropDownToggle.js +3 -0
  6. package/dist/auth/Login/LoginComponent.d.ts.map +1 -1
  7. package/dist/auth/Login/LoginComponent.js +11 -7
  8. package/dist/auth/Register/RegisterComponent.d.ts.map +1 -1
  9. package/dist/auth/Register/RegisterComponent.js +5 -4
  10. package/dist/auth/ResetPassword/ResetPasswordComponent.d.ts.map +1 -1
  11. package/dist/auth/ResetPassword/ResetPasswordComponent.js +5 -4
  12. package/dist/auth/Social/SocialCallbackComponent.d.ts.map +1 -1
  13. package/dist/auth/Social/SocialCallbackComponent.js +5 -2
  14. package/dist/auth/Social/SocialFormComponent.d.ts.map +1 -1
  15. package/dist/auth/Social/SocialFormComponent.js +4 -4
  16. package/dist/custom-fields/field-set/components/CustomFieldSet/CustomFieldSet.d.ts.map +1 -1
  17. package/dist/custom-fields/field-set/components/CustomFieldSet/CustomFieldSet.js +5 -4
  18. package/dist/customRadioButton/RadioButton.d.ts +11 -0
  19. package/dist/customRadioButton/RadioButton.d.ts.map +1 -0
  20. package/dist/customRadioButton/RadioButton.js +93 -0
  21. package/dist/events/edit-event-modal/component/SelectEventProductSet/component/EditEventProductSet.js +1 -1
  22. package/dist/events/edit-recurrent-event-modal/EditRecurrentEventModal.d.ts.map +1 -1
  23. package/dist/events/event-statistic-modal/EventStatisticModal.d.ts.map +1 -1
  24. package/dist/file-upload/FileUpload.d.ts.map +1 -1
  25. package/dist/file-upload/FileUpload.js +4 -4
  26. package/dist/iframe/payment/order-items-table/hooks/useTableData.d.ts.map +1 -1
  27. package/dist/iframe/payment/order-items-table/hooks/useTableData.js +81 -80
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +1 -0
  31. package/dist/modals/dialog/Dialog.d.ts.map +1 -1
  32. package/dist/modals/dialog/Dialog.js +39 -41
  33. package/dist/notification/email-template/card/EmailTemplateCard.d.ts.map +1 -1
  34. package/dist/notification/email-template/control/EmailTemplateControl.d.ts +1 -0
  35. package/dist/notification/email-template/control/EmailTemplateControl.d.ts.map +1 -1
  36. package/dist/notification/email-template/control/EmailTemplateControl.js +4 -4
  37. package/dist/notification/email-template/form/EmailTemplateForm.d.ts +2 -1
  38. package/dist/notification/email-template/form/EmailTemplateForm.d.ts.map +1 -1
  39. package/dist/notification/email-template/form/EmailTemplateForm.js +2 -1
  40. package/dist/product-set/product/advanced-options/AdvancedOptions.js +1 -1
  41. package/dist/recurrence-input/RecurrenceInput.d.ts.map +1 -1
  42. package/dist/recurrence-input/RecurrenceInput.js +1 -1
  43. package/dist/sales/guest-profile/profile/Profile.d.ts.map +1 -1
  44. package/dist/sales/guest-profile/profile/Profile.js +2 -1
  45. package/dist/setting/dashboard/payments/payments-modal/PaymentsModal.d.ts.map +1 -1
  46. package/dist/snippet/snippet-template/preview/Preview.d.ts.map +1 -1
  47. package/dist/snippet/snippet-template/preview/Preview.js +14 -20
  48. package/package.json +6 -6
  49. package/src/CustomDatePicker/CustomDatePicker.tsx +258 -0
  50. package/src/auth/ChangePassword/ChangePasswordComponent.tsx +3 -4
  51. package/src/auth/Layout/UserNavDropDownToggle.tsx +1 -1
  52. package/src/auth/Login/LoginComponent.tsx +7 -5
  53. package/src/auth/Register/RegisterComponent.tsx +3 -4
  54. package/src/auth/ResetPassword/ResetPasswordComponent.tsx +3 -4
  55. package/src/auth/Social/SocialCallbackComponent.tsx +3 -2
  56. package/src/auth/Social/SocialFormComponent.tsx +2 -3
  57. package/src/custom-fields/field-set/components/CustomFieldSet/CustomFieldSet.tsx +3 -4
  58. package/src/customRadioButton/RadioButton.tsx +84 -0
  59. package/src/events/edit-recurrent-event-modal/EditRecurrentEventModal.tsx +1 -0
  60. package/src/events/event-statistic-modal/EventStatisticModal.tsx +1 -0
  61. package/src/file-upload/FileUpload.tsx +2 -3
  62. package/src/iframe/payment/order-items-table/hooks/useTableData.tsx +103 -109
  63. package/src/index.ts +1 -0
  64. package/src/modals/dialog/Dialog.tsx +35 -36
  65. package/src/notification/email-template/card/EmailTemplateCard.tsx +0 -2
  66. package/src/notification/email-template/control/EmailTemplateControl.tsx +7 -5
  67. package/src/notification/email-template/form/EmailTemplateForm.tsx +3 -0
  68. package/src/recurrence-input/RecurrenceInput.tsx +4 -3
  69. package/src/sales/guest-profile/profile/Profile.tsx +2 -5
  70. package/src/setting/dashboard/payments/payments-modal/PaymentsModal.tsx +1 -0
  71. package/src/snippet/snippet-template/preview/Preview.tsx +6 -9
  72. package/yarn.lock +528 -576
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@licklist/design",
3
- "version": "0.78.5-dev.2",
3
+ "version": "0.78.5-dev.23",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+ssh://git@bitbucket.org/artelogicsoft/licklist_design.git"
@@ -42,9 +42,9 @@
42
42
  ]
43
43
  },
44
44
  "peerDependencies": {
45
- "@licklist/core": "0.36.1-dev.1",
45
+ "@licklist/core": "0.36.1-dev.6",
46
46
  "@licklist/eslint-config": "0.5.6",
47
- "@licklist/plugins": "0.36.4-dev.1",
47
+ "@licklist/plugins": "0.36.4-dev.9",
48
48
  "clsx": "2.1.1",
49
49
  "i18next": "25.3.2",
50
50
  "lodash": "4.17.21",
@@ -64,9 +64,9 @@
64
64
  "@dnd-kit/utilities": "2.0.0",
65
65
  "@fortawesome/fontawesome-svg-core": "1.2.34",
66
66
  "@fortawesome/free-solid-svg-icons": "5.15.2",
67
- "@licklist/core": "0.36.1-dev.1",
67
+ "@licklist/core": "0.36.1-dev.6",
68
68
  "@licklist/eslint-config": "0.5.6",
69
- "@licklist/plugins": "0.36.4-dev.1",
69
+ "@licklist/plugins": "0.36.4-dev.8",
70
70
  "@mantine/core": "6.0.22",
71
71
  "@mantine/hooks": "6.0.22",
72
72
  "@mdx-js/react": "1.6.22",
@@ -199,7 +199,7 @@
199
199
  },
200
200
  "resolutions": {
201
201
  "@types/react": "18.3.12",
202
- "@types/react-dom": "17.0.25"
202
+ "@types/react-dom": "18.3.1"
203
203
  },
204
204
  "lint-staged": {
205
205
  "*.{ts,tsx}": [
@@ -0,0 +1,258 @@
1
+ import { TextInput } from '@mantine/core'
2
+ import { useEffect, useState } from 'react'
3
+ import { Controller, useFormContext } from 'react-hook-form'
4
+ import { DateTime } from 'luxon'
5
+ import { useTranslation } from 'react-i18next'
6
+
7
+ type CustomDatePickerProps = {
8
+ name: string
9
+ error?: string
10
+ label?: string
11
+ showAge?: boolean
12
+ required?: boolean
13
+ }
14
+
15
+ export function CustomDatePicker({
16
+ name,
17
+ error,
18
+ showAge = true,
19
+ required = true
20
+ }: CustomDatePickerProps) {
21
+ const { t } = useTranslation()
22
+ const { control, setValue, watch, getValues, trigger, formState } = useFormContext()
23
+ const [age, setAge] = useState<number | null>(null)
24
+ const [localError, setLocalError] = useState<string | null>(null)
25
+
26
+ // Get current field values
27
+ const day = watch(`${name}_day`) || ''
28
+ const month = watch(`${name}_month`) || ''
29
+ const year = watch(`${name}_year`) || ''
30
+
31
+ // Initialize values from existing date
32
+ useEffect(() => {
33
+ const existingDate = getValues(name)
34
+
35
+ if (existingDate instanceof Date && !day && !month && !year) {
36
+ const dateTime = DateTime.fromJSDate(existingDate)
37
+ if (dateTime.isValid) {
38
+ setValue(`${name}_day`, dateTime.day.toString().padStart(2, '0'))
39
+ setValue(`${name}_month`, dateTime.month.toString().padStart(2, '0'))
40
+ setValue(`${name}_year`, dateTime.year.toString())
41
+ }
42
+ }
43
+ }, [name, setValue, getValues, day, month, year])
44
+
45
+ // Check for empty fields after submit attempt
46
+ useEffect(() => {
47
+ if (formState.isSubmitted && required) {
48
+ const hasEmptyFields = !day || !month || !year
49
+
50
+ if (hasEmptyFields) {
51
+ setLocalError(t('Validation:fieldRequired', { attribute: t('App:dateOfBirth') }))
52
+ // Set the main field to null to trigger form validation
53
+ setValue(name, null, { shouldValidate: true })
54
+ } else {
55
+ setLocalError(null)
56
+ }
57
+ }
58
+ }, [formState.isSubmitted, day, month, year, required, name, setValue, t])
59
+
60
+ // Calculate age and validate date when all fields are filled
61
+ useEffect(() => {
62
+ if (day && month && year) {
63
+ try {
64
+ // Create a date object
65
+ const dateObj = DateTime.fromObject({
66
+ day: parseInt(day, 10),
67
+ month: parseInt(month, 10),
68
+ year: parseInt(year, 10)
69
+ })
70
+
71
+ // Only proceed if date is valid
72
+ if (dateObj.isValid) {
73
+ // Set the main field value
74
+ setValue(name, dateObj.toJSDate(), { shouldValidate: true })
75
+ setLocalError(null)
76
+
77
+ // Calculate age
78
+ if (showAge) {
79
+ const now = DateTime.now()
80
+ const diff = now.diff(dateObj, 'years')
81
+ setAge(Math.floor(diff.years))
82
+ }
83
+ } else {
84
+ setLocalError(t('Validation:fieldInvalid', { attribute: t('App:dateOfBirth') }))
85
+ setValue(name, null, { shouldValidate: true })
86
+ setAge(null)
87
+ }
88
+ } catch (err) {
89
+ // If any parsing fails, just reset the age display
90
+ setLocalError(t('Validation:fieldInvalid', { attribute: t('App:dateOfBirth') }))
91
+ setValue(name, null, { shouldValidate: true })
92
+ setAge(null)
93
+ }
94
+ } else if (formState.isSubmitted && required) {
95
+ // If form was submitted and fields are required but not all filled
96
+ setLocalError(t('Validation:fieldRequired', { attribute: t('App:dateOfBirth') }))
97
+ setValue(name, null, { shouldValidate: true })
98
+ setAge(null)
99
+ } else {
100
+ // Reset if not all fields are filled but not submitted yet
101
+ setValue(name, null, { shouldValidate: false })
102
+ setAge(null)
103
+ }
104
+ }, [day, month, year, name, setValue, showAge, formState.isSubmitted, required, t])
105
+
106
+ // After user completes all fields, validate the form
107
+ useEffect(() => {
108
+ if (day && month && year) {
109
+ trigger(name)
110
+ }
111
+ }, [day, month, year, name, trigger])
112
+
113
+ // Display either the form error or our local error
114
+ const displayError = error || localError
115
+
116
+ return (
117
+ <div className="tw-w-full">
118
+ <div className="tw-flex tw-flex-col">
119
+ <div className="tw-mb-2 tw-flex tw-items-center tw-justify-between">
120
+ <label className="tw-font-semibold">
121
+ {t('App:dateOfBirth')}
122
+ {required && <span className="tw-ml-1 tw-text-red-500"></span>}
123
+ </label>
124
+ {age !== null && (
125
+ <span className="tw-text-sm tw-text-gray-600">
126
+ {t('App:Age')}: {age}
127
+ </span>
128
+ )}
129
+ </div>
130
+
131
+ <div className="tw-flex tw-flex-row tw-gap-4">
132
+ <div className="tw-w-1/3">
133
+ <label className="tw-mb-1 tw-block tw-text-sm">{t('App:Day')}</label>
134
+ <Controller
135
+ control={control}
136
+ name={`${name}_day`}
137
+ defaultValue=""
138
+ render={({ field }) => (
139
+ <TextInput
140
+ {...field}
141
+ value={field.value || ''}
142
+ placeholder="DD"
143
+ maxLength={2}
144
+ error={!!displayError}
145
+ classNames={{ input: 'tw-placeholder-[#626A90]' }}
146
+ styles={{ input: { '&::placeholder': { color: '#626A90' } } }}
147
+ onChange={(e) => {
148
+ const value = e.target.value.replace(/[^0-9]/g, '')
149
+ field.onChange(value)
150
+ }}
151
+ onBlur={(e) => {
152
+ // Validate and format on blur
153
+ let value = e.target.value.replace(/[^0-9]/g, '')
154
+ if (value) {
155
+ const num = parseInt(value, 10)
156
+ if (num < 1) value = '01'
157
+ else if (num > 31) value = '31'
158
+ else value = num.toString().padStart(2, '0')
159
+ }
160
+ field.onChange(value)
161
+ }}
162
+ />
163
+ )}
164
+ />
165
+ </div>
166
+
167
+ <div className="tw-w-1/3">
168
+ <label className="tw-mb-1 tw-block tw-text-sm">{t('App:Month')}</label>
169
+ <Controller
170
+ control={control}
171
+ name={`${name}_month`}
172
+ defaultValue=""
173
+ render={({ field }) => (
174
+ <TextInput
175
+ {...field}
176
+ value={field.value || ''}
177
+ placeholder="MM"
178
+ maxLength={2}
179
+ error={!!displayError}
180
+ classNames={{ input: 'tw-placeholder-[#626A90]' }}
181
+ styles={{ input: { '&::placeholder': { color: '#626A90' } } }}
182
+ onChange={(e) => {
183
+ const value = e.target.value.replace(/[^0-9]/g, '')
184
+ field.onChange(value)
185
+ }}
186
+ onBlur={(e) => {
187
+ // Validate and format on blur
188
+ let value = e.target.value.replace(/[^0-9]/g, '')
189
+ if (value) {
190
+ const num = parseInt(value, 10)
191
+ if (num < 1) value = '01'
192
+ else if (num > 12) value = '12'
193
+ else value = num.toString().padStart(2, '0')
194
+ }
195
+ field.onChange(value)
196
+ }}
197
+ />
198
+ )}
199
+ />
200
+ </div>
201
+
202
+ <div className="tw-w-1/3">
203
+ <label className="tw-mb-1 tw-block tw-text-sm">{t('App:Year')}</label>
204
+ <Controller
205
+ control={control}
206
+ name={`${name}_year`}
207
+ defaultValue=""
208
+ render={({ field }) => (
209
+ <TextInput
210
+ {...field}
211
+ value={field.value || ''}
212
+ placeholder="YYYY"
213
+ maxLength={4}
214
+ error={!!displayError}
215
+ classNames={{ input: 'tw-placeholder-[#626A90]' }}
216
+ styles={{ input: { '&::placeholder': { color: '#626A90' } } }}
217
+ onChange={(e) => {
218
+ const value = e.target.value.replace(/[^0-9]/g, '')
219
+ field.onChange(value)
220
+ }}
221
+ onBlur={(e) => {
222
+ // Validate on blur
223
+ const value = e.target.value.replace(/[^0-9]/g, '')
224
+ if (value) {
225
+ const num = parseInt(value, 10)
226
+ const currentYear = new Date().getFullYear()
227
+ if (num > currentYear) {
228
+ field.onChange(currentYear.toString())
229
+ } else if (num < 1900) {
230
+ field.onChange('1900')
231
+ }
232
+ }
233
+ }}
234
+ />
235
+ )}
236
+ />
237
+ </div>
238
+ </div>
239
+ </div>
240
+
241
+ {/* Hidden field to store the actual date value */}
242
+ <Controller
243
+ control={control}
244
+ name={name}
245
+ defaultValue={null}
246
+ rules={{
247
+ validate: value => {
248
+ if (required && !value) {
249
+ return t('Validation:fieldRequired', { attribute: t('App:dateOfBirth') })
250
+ }
251
+ return true
252
+ }
253
+ }}
254
+ render={() => <input type="hidden" />}
255
+ />
256
+ </div>
257
+ )
258
+ }
@@ -1,3 +1,4 @@
1
+ import { showAlert } from '@licklist/plugins/dist/context/app/AlertContext'
1
2
  import { useContext, useEffect, useState } from 'react'
2
3
  import Row from 'react-bootstrap/Row'
3
4
  import Col from 'react-bootstrap/Col'
@@ -6,7 +7,6 @@ import { useLocation, useNavigate } from 'react-router-dom'
6
7
  import { ApiServiceError } from '@licklist/core/dist/Api/ApiService'
7
8
  import RequestContext from '@licklist/plugins/dist/context/app/RequestContext'
8
9
  import useUserApi from '@licklist/plugins/dist/hooks/Api/useUserApi'
9
- import useNotification from '@licklist/plugins/dist/context/app/hooks/useNotification'
10
10
  import { UserChangePasswordRequest } from '@licklist/plugins/dist/types/Request/UserChangePasswordRequest'
11
11
  import { ROUTES } from '@licklist/core/dist/Config'
12
12
  import { ChangePasswordFormComponent } from './ChangePasswordFormComponent'
@@ -16,7 +16,6 @@ import { LoaderIndicator } from '../../static/loader/LoaderIndicator'
16
16
  function ChangePasswordComponent() {
17
17
  const { t } = useTranslation(['Notification', 'User', 'App'])
18
18
  const request = useContext(RequestContext)
19
- const notification = useNotification()
20
19
  const { search } = useLocation()
21
20
  const email = new URLSearchParams(search).get('email')
22
21
  const token = new URLSearchParams(search).get('token')
@@ -27,7 +26,7 @@ function ChangePasswordComponent() {
27
26
  const userApiService = useUserApi(request)
28
27
 
29
28
  const handleError = (error: ApiServiceError<{ message: string }>) => {
30
- notification.danger({
29
+ showAlert({ type: 'error',
31
30
  title: t('App:error'),
32
31
  message: error.response?.data?.message,
33
32
  })
@@ -45,7 +44,7 @@ function ChangePasswordComponent() {
45
44
  return
46
45
  }
47
46
 
48
- notification.success({
47
+ showAlert({ type: 'success',
49
48
  title: 'Success',
50
49
  message: t('Notification:passwordChangedSuccessfully'),
51
50
  })
@@ -13,7 +13,7 @@ function UserNavDropDownToggle(props: UserNavDropDownToggleProps) {
13
13
  return (
14
14
  <>
15
15
  <span className='header-user-name mr-2 d-none d-lg-inline text-gray-600 small'>
16
- <Trans t={t} i18nKey='userPromo'>
16
+ <Trans t={t} i18nKey='userPromo' values={{ name: user?.first_name }}>
17
17
  Hi, {{ name: user?.first_name }}
18
18
  </Trans>
19
19
  </span>
@@ -1,11 +1,11 @@
1
1
  import { useContext, useEffect, useState } from 'react'
2
+ import { showAlert } from '@licklist/plugins/dist/context/app/AlertContext'
2
3
  import Row from 'react-bootstrap/Row'
3
4
  import Col from 'react-bootstrap/Col'
4
5
  import { Trans, useTranslation } from 'react-i18next'
5
6
  import { Link, useNavigate } from 'react-router-dom'
6
7
  import RequestContext from '@licklist/plugins/dist/context/app/RequestContext'
7
8
  import useUserApi from '@licklist/plugins/dist/hooks/Api/useUserApi'
8
- import useNotification from '@licklist/plugins/dist/context/app/hooks/useNotification'
9
9
  import useAuth from '@licklist/plugins/dist/context/user/hooks/useAuth'
10
10
  import useUser from '@licklist/plugins/dist/context/user/hooks/useUser'
11
11
  import useInvite from '@licklist/plugins/dist/context/user/hooks/useInvite'
@@ -30,7 +30,6 @@ const LoginComponent = ({
30
30
  }: LoginComponentProps) => {
31
31
  const { t } = useTranslation(['Notification', 'User'])
32
32
  const request = useContext(RequestContext)
33
- const notification = useNotification()
34
33
  const auth = useAuth()
35
34
  const user = useUser()
36
35
  const invite = useInvite()
@@ -42,9 +41,10 @@ const LoginComponent = ({
42
41
  const userApiService = useUserApi(request)
43
42
 
44
43
  const handleError = (error: any) => {
45
- notification.danger({
44
+ showAlert({ type: 'error',
46
45
  title: 'Error',
47
46
  message: error?.response?.data?.message || error.message,
47
+ timeout: 10000,
48
48
  })
49
49
  }
50
50
 
@@ -82,9 +82,11 @@ const LoginComponent = ({
82
82
  user.login(profile.data as IUser)
83
83
  invite.clearInvitation()
84
84
 
85
- notification.success({
85
+ showAlert({ type: 'success',
86
86
  title: 'Success',
87
87
  message: t('Notification:loggedSuccessfully'),
88
+ timeout: 10000,
89
+ mount: 'global',
88
90
  })
89
91
 
90
92
  navigate('/', { replace: true })
@@ -112,7 +114,7 @@ const LoginComponent = ({
112
114
  <Trans t={t} i18nKey='loginPromo'>
113
115
  {/* TODO fix issue react router types
114
116
  @ts-expect-error */}
115
- Don&apos;t have account? <Link to='/register'>Sign up</Link>.
117
+ Don&apos;t have account? <Link to='/register'>Sign uuup</Link>.
116
118
  </Trans>
117
119
  </h6>
118
120
  )}
@@ -1,9 +1,9 @@
1
+ import { showAlert } from '@licklist/plugins/dist/context/app/AlertContext'
1
2
  import { useContext, useState } from 'react'
2
3
  import { Trans, useTranslation } from 'react-i18next'
3
4
  import { Link, useNavigate } from 'react-router-dom'
4
5
  import { Row, Col } from 'react-bootstrap'
5
6
  import RequestContext from '@licklist/plugins/dist/context/app/RequestContext'
6
- import useNotification from '@licklist/plugins/dist/context/app/hooks/useNotification'
7
7
  import useUser from '@licklist/plugins/dist/context/user/hooks/useUser'
8
8
  import useAuth from '@licklist/plugins/dist/context/user/hooks/useAuth'
9
9
  import useInvite from '@licklist/plugins/dist/context/user/hooks/useInvite'
@@ -26,7 +26,6 @@ function RegisterComponent({
26
26
  }: RegisterComponentProps) {
27
27
  const { t } = useTranslation('User')
28
28
  const request = useContext(RequestContext)
29
- const notification = useNotification()
30
29
  const auth = useAuth()
31
30
  const user = useUser()
32
31
  const invite = useInvite()
@@ -48,7 +47,7 @@ function RegisterComponent({
48
47
  }
49
48
 
50
49
  const handleError = (error: Error) => {
51
- notification.danger({
50
+ showAlert({ type: 'error',
52
51
  title: 'Error',
53
52
  message: error.message,
54
53
  })
@@ -85,7 +84,7 @@ function RegisterComponent({
85
84
 
86
85
  invite.clearInvitation()
87
86
 
88
- notification.success({
87
+ showAlert({ type: 'success',
89
88
  title: 'Success',
90
89
  message: t('Notification:registeredSuccessfully'),
91
90
  })
@@ -1,3 +1,4 @@
1
+ import { showAlert } from '@licklist/plugins/dist/context/app/AlertContext'
1
2
  import { useContext, useState } from 'react'
2
3
  import Row from 'react-bootstrap/Row'
3
4
  import Col from 'react-bootstrap/Col'
@@ -5,7 +6,6 @@ import { useTranslation } from 'react-i18next'
5
6
  import { ApiServiceError } from '@licklist/core/dist/Api/ApiService'
6
7
  import RequestContext from '@licklist/plugins/dist/context/app/RequestContext'
7
8
  import useUserApi from '@licklist/plugins/dist/hooks/Api/useUserApi'
8
- import useNotification from '@licklist/plugins/dist/context/app/hooks/useNotification'
9
9
  import { UserResetPasswordRequest } from '@licklist/plugins/dist/types/Request/UserResetPasswordRequest'
10
10
  import { ROUTES } from '@licklist/core/dist/Config'
11
11
  import { useNavigate } from 'react-router-dom'
@@ -16,7 +16,6 @@ import { LoaderIndicator } from '../../static/loader/LoaderIndicator'
16
16
  function ResetPasswordComponent() {
17
17
  const { t } = useTranslation(['Notification', 'User', 'App'])
18
18
  const request = useContext(RequestContext)
19
- const notification = useNotification()
20
19
  const navigate = useNavigate()
21
20
 
22
21
  const [isLoading, setIsLoading] = useState<boolean>(false)
@@ -24,7 +23,7 @@ function ResetPasswordComponent() {
24
23
  const userApiService = useUserApi(request)
25
24
 
26
25
  const handleError = (error: ApiServiceError<{ message: string }>) => {
27
- notification.danger({
26
+ showAlert({ type: 'error',
28
27
  title: t('App:error'),
29
28
  message: error.response?.data?.message,
30
29
  })
@@ -40,7 +39,7 @@ function ResetPasswordComponent() {
40
39
  return
41
40
  }
42
41
 
43
- notification.success({
42
+ showAlert({ type: 'success',
44
43
  title: 'Success',
45
44
  message: t('Notification:passwordResetedSuccessfully'),
46
45
  })
@@ -1,3 +1,4 @@
1
+ import { showAlert } from '@licklist/plugins/dist/context/app/AlertContext'
1
2
  import { useContext, useEffect, useState } from 'react'
2
3
  import RequestContext from '@licklist/plugins/dist/context/app/RequestContext'
3
4
  import useNotification from '@licklist/plugins/dist/context/app/hooks/useNotification'
@@ -39,7 +40,7 @@ function SocialCallbackComponent() {
39
40
  // Handle social callback
40
41
  useEffect(() => {
41
42
  const handleError = (error: Error) => {
42
- notification.danger({
43
+ showAlert({ type: 'error',
43
44
  title: 'Error',
44
45
  message: error.message,
45
46
  })
@@ -72,7 +73,7 @@ function SocialCallbackComponent() {
72
73
  // Store user profile
73
74
  user.login(profile.message as IUser)
74
75
 
75
- notification.success({
76
+ showAlert({ type: 'success',
76
77
  title: 'Success',
77
78
  message: t('Notification:loggedSuccessfully'),
78
79
  })
@@ -1,6 +1,6 @@
1
+ import { showAlert } from '@licklist/plugins/dist/context/app/AlertContext'
1
2
  /* eslint-disable @typescript-eslint/ban-ts-comment */
2
3
  /* eslint-disable @typescript-eslint/ban-types */
3
- import useNotification from '@licklist/plugins/dist/context/app/hooks/useNotification'
4
4
  import RequestContext from '@licklist/plugins/dist/context/app/RequestContext'
5
5
  import useSocialApi from '@licklist/plugins/dist/hooks/Api/useSocialApi'
6
6
  import RouteService from '@licklist/plugins/dist/services/Route/RouteService'
@@ -20,13 +20,12 @@ function SocialFormComponent(props: SocialFormComponentProps) {
20
20
  const { isLoading, setIsLoading } = props
21
21
 
22
22
  const request = useContext(RequestContext)
23
- const notification = useNotification()
24
23
  const { t } = useTranslation(['App'])
25
24
 
26
25
  const socialService = useSocialApi(request)
27
26
 
28
27
  const handleError = (error: Error) => {
29
- notification.danger({
28
+ showAlert({ type: 'error',
30
29
  title: 'Error',
31
30
  message: error.message,
32
31
  })
@@ -1,3 +1,4 @@
1
+ import { showAlert } from '@licklist/plugins/dist/context/app/AlertContext'
1
2
  import { createElement, useState, useEffect, useContext } from 'react'
2
3
  import { useTranslation } from 'react-i18next'
3
4
  import { Button, Form } from 'react-bootstrap'
@@ -17,7 +18,6 @@ import { HasPermissionProp } from '@licklist/plugins/dist/types/permission/Permi
17
18
  import FormErrorService from '@licklist/plugins/dist/services/Form/FormErrorService'
18
19
  import { ServerError } from '@licklist/plugins/dist/hooks/Api/useHttpQuery'
19
20
  import HookFormService from '@licklist/plugins/dist/services/Form/HookFormService'
20
- import useNotification from '@licklist/plugins/dist/context/app/hooks/useNotification'
21
21
 
22
22
  import {
23
23
  CreateSortableListItem,
@@ -85,7 +85,6 @@ export const CustomFieldSet = ({
85
85
  useEffect(() => {
86
86
  FormErrorService.handleServerErrors(serverErrors, setError)
87
87
  }, [serverErrors, setError])
88
- const notification = useNotification()
89
88
  const { fields, append, remove } = useFieldArray({
90
89
  control,
91
90
  name: CUSTOM_FIELDS,
@@ -98,7 +97,7 @@ export const CustomFieldSet = ({
98
97
 
99
98
  if (!response) return
100
99
 
101
- notification.success({
100
+ showAlert({ type: 'success',
102
101
  title: t('App:success'),
103
102
  message: t('Notification:createSuccessfully', {
104
103
  argument: t('customField'),
@@ -124,7 +123,7 @@ export const CustomFieldSet = ({
124
123
  if (fieldSet.id !== null) {
125
124
  await onFieldSetDelete(fieldSet)
126
125
 
127
- notification.success({
126
+ showAlert({ type: 'success',
128
127
  title: t('App:success'),
129
128
  message: t('Notification:theRemovedSuccessfully', {
130
129
  argument: t('customField'),
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+
3
+ interface RadioButtonProps {
4
+ name: string;
5
+ value: string;
6
+ checked: boolean;
7
+ onChange: (value: string) => void;
8
+ label?: string;
9
+ }
10
+
11
+ const RadioButton: React.FC<RadioButtonProps> = ({
12
+ name,
13
+ value,
14
+ checked,
15
+ onChange,
16
+ label
17
+ }) => {
18
+ // Generate a stable id so label could be connected if needed
19
+ const id = `${name}-${value}`;
20
+
21
+ return (
22
+ <div
23
+ className="tw-flex tw-items-center tw-space-x-3"
24
+ style={{ display: 'flex', alignItems: 'center', gap: 12 }}
25
+ >
26
+ <div
27
+ className="tw-relative tw-cursor-pointer"
28
+ style={{ position: 'relative', cursor: 'pointer' }}
29
+ onClick={() => onChange(value)}
30
+ >
31
+ {/* Hidden native radio input for accessibility */}
32
+ <input
33
+ id={id}
34
+ type="radio"
35
+ name={name}
36
+ value={value}
37
+ checked={checked}
38
+ onChange={() => onChange(value)}
39
+ className="tw-sr-only"
40
+ style={{ position: 'absolute', opacity: 0, pointerEvents: 'none', width: 0, height: 0 }}
41
+ />
42
+
43
+ {/* Custom radio button circle */}
44
+ <div
45
+ className="tw-w-[47px] tw-h-[47px] tw-border-[3px] tw-border-black tw-rounded-full tw-bg-white tw-flex tw-items-center tw-justify-center tw-transition-all tw-duration-200 hover:tw-shadow-sm"
46
+ style={{
47
+ width: 52,
48
+ height: 52,
49
+ borderWidth: 3,
50
+ borderStyle: 'solid',
51
+ borderColor: '#000',
52
+ borderRadius: 9999,
53
+ background: '#fff',
54
+ display: 'flex',
55
+ alignItems: 'center',
56
+ justifyContent: 'center',
57
+ transition: 'all 200ms',
58
+ }}
59
+ >
60
+ {/* Inner filled circle when selected */}
61
+ {checked && (
62
+ <div
63
+ className="tw-w-[30px] tw-h-[30px] tw-bg-slate-900 tw-rounded-full"
64
+ style={{ width: 30, height: 30, background: '#0f172a', borderRadius: 9999 }}
65
+ />
66
+ )}
67
+ </div>
68
+ </div>
69
+
70
+ {label && (
71
+ <label
72
+ htmlFor={id}
73
+ className="tw-cursor-pointer tw-text-gray-700 tw-select-none tw-flex tw-items-center tw-leading-none"
74
+ style={{ cursor: 'pointer', color: '#374151', userSelect: 'none', display: 'inline-flex', alignItems: 'center', lineHeight: 1, position: 'relative', top: 5 }}
75
+ onClick={() => onChange(value)}
76
+ >
77
+ {label}
78
+ </label>
79
+ )}
80
+ </div>
81
+ );
82
+ };
83
+
84
+ export default RadioButton;
@@ -86,6 +86,7 @@ export const EditRecurrentEventModal = ({
86
86
  contentClassName='rounded'
87
87
  >
88
88
  <Form onSubmit={handleSubmit(onSubmit)} noValidate>
89
+ {/* @ts-ignore */}
89
90
  <Modal.Header className='border-0'>
90
91
  <Modal.Title as='h6'>{title}</Modal.Title>
91
92
  <Button
@@ -39,6 +39,7 @@ export const EventStatisticModal = ({
39
39
  contentClassName='rounded'
40
40
  className='event-statistic-modal'
41
41
  >
42
+ {/* @ts-ignore */}
42
43
  <Modal.Header>
43
44
  <Modal.Title as='h6'>{title ?? t('eventStatistic')}</Modal.Title>
44
45
  <Button