dauth-context-react 6.2.0 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -24,7 +24,8 @@ var initialDauthState = {
24
24
  deleteAccount: () => Promise.resolve(false),
25
25
  getPasskeyCredentials: () => Promise.resolve([]),
26
26
  registerPasskey: () => Promise.resolve(null),
27
- deletePasskeyCredential: () => Promise.resolve(false)
27
+ deletePasskeyCredential: () => Promise.resolve(false),
28
+ uploadAvatar: () => Promise.resolve(false)
28
29
  };
29
30
  var initialDauthState_default = initialDauthState;
30
31
 
@@ -186,6 +187,18 @@ async function deletePasskeyCredentialAPI(basePath, credentialId) {
186
187
  const data = await response.json();
187
188
  return { response, data };
188
189
  }
190
+ async function uploadAvatarAPI(basePath, file) {
191
+ const formData = new FormData();
192
+ formData.append("avatar", file);
193
+ const response = await fetch(`${basePath}/avatar`, {
194
+ method: "POST",
195
+ headers: { "X-CSRF-Token": getCsrfToken() },
196
+ credentials: "include",
197
+ body: formData
198
+ });
199
+ const data = await response.json();
200
+ return { response, data };
201
+ }
189
202
 
190
203
  // src/webauthn.ts
191
204
  function base64urlToBuffer(base64url) {
@@ -441,6 +454,30 @@ async function deletePasskeyCredentialAction(ctx, credentialId) {
441
454
  return false;
442
455
  }
443
456
  }
457
+ async function uploadAvatarAction(ctx, file) {
458
+ const { dispatch, authProxyPath, onError } = ctx;
459
+ try {
460
+ const result = await uploadAvatarAPI(authProxyPath, file);
461
+ if (result.response.status === 200) {
462
+ dispatch({
463
+ type: UPDATE_USER,
464
+ payload: result.data.user
465
+ });
466
+ return true;
467
+ }
468
+ onError(
469
+ new Error(
470
+ "Avatar upload error: " + result.data.message
471
+ )
472
+ );
473
+ return false;
474
+ } catch (error) {
475
+ onError(
476
+ error instanceof Error ? error : new Error("Avatar upload error")
477
+ );
478
+ return false;
479
+ }
480
+ }
444
481
  var resetUser = (dispatch) => {
445
482
  return dispatch({
446
483
  type: LOGIN,
@@ -750,7 +787,8 @@ function DauthProfileModal({
750
787
  logout,
751
788
  getPasskeyCredentials,
752
789
  registerPasskey,
753
- deletePasskeyCredential
790
+ deletePasskeyCredential,
791
+ uploadAvatar
754
792
  } = useDauth();
755
793
  const isDesktop = useMediaQuery("(min-width: 641px)");
756
794
  const phase = useModalAnimation(open);
@@ -762,6 +800,10 @@ function DauthProfileModal({
762
800
  const [lastname, setLastname] = useState("");
763
801
  const [nickname, setNickname] = useState("");
764
802
  const [country, setCountry] = useState("");
803
+ const [telPrefix, setTelPrefix] = useState("");
804
+ const [telSuffix, setTelSuffix] = useState("");
805
+ const [birthDate, setBirthDate] = useState("");
806
+ const [customFieldValues, setCustomFieldValues] = useState({});
765
807
  const [populated, setPopulated] = useState(false);
766
808
  const [saving, setSaving] = useState(false);
767
809
  const [status, setStatus] = useState(null);
@@ -781,6 +823,16 @@ function DauthProfileModal({
781
823
  setLastname(user.lastname || "");
782
824
  setNickname(user.nickname || "");
783
825
  setCountry(user.country || "");
826
+ setTelPrefix(user.telPrefix || "");
827
+ setTelSuffix(user.telSuffix || "");
828
+ setBirthDate(
829
+ user.birthDate ? new Date(user.birthDate).toISOString().split("T")[0] : ""
830
+ );
831
+ const cf = {};
832
+ for (const f of domain.customFields ?? []) {
833
+ cf[f.key] = user.customFields?.[f.key] ?? "";
834
+ }
835
+ setCustomFieldValues(cf);
784
836
  setPopulated(true);
785
837
  }
786
838
  if (!open) {
@@ -830,8 +882,23 @@ function DauthProfileModal({
830
882
  );
831
883
  const hasChanges = useMemo(() => {
832
884
  if (!user?._id) return false;
833
- return name !== (user.name || "") || lastname !== (user.lastname || "") || nickname !== (user.nickname || "") || country !== (user.country || "");
834
- }, [name, lastname, nickname, country, user]);
885
+ const origBirthDate = user.birthDate ? new Date(user.birthDate).toISOString().split("T")[0] : "";
886
+ const cfChanged = (domain.customFields ?? []).some(
887
+ (f) => (customFieldValues[f.key] ?? "") !== (user.customFields?.[f.key] ?? "")
888
+ );
889
+ return name !== (user.name || "") || lastname !== (user.lastname || "") || nickname !== (user.nickname || "") || country !== (user.country || "") || telPrefix !== (user.telPrefix || "") || telSuffix !== (user.telSuffix || "") || birthDate !== origBirthDate || cfChanged;
890
+ }, [
891
+ name,
892
+ lastname,
893
+ nickname,
894
+ country,
895
+ telPrefix,
896
+ telSuffix,
897
+ birthDate,
898
+ customFieldValues,
899
+ user,
900
+ domain.customFields
901
+ ]);
835
902
  const canSave = name.trim().length > 0 && hasChanges && !saving;
836
903
  const handleSave = useCallback(async () => {
837
904
  setSaving(true);
@@ -840,6 +907,14 @@ function DauthProfileModal({
840
907
  if (hasField("lastname")) fields.lastname = lastname;
841
908
  if (hasField("nickname")) fields.nickname = nickname;
842
909
  if (hasField("country")) fields.country = country;
910
+ if (hasField("tel_prefix"))
911
+ fields.telPrefix = telPrefix;
912
+ if (hasField("tel_suffix"))
913
+ fields.telSuffix = telSuffix;
914
+ if (hasField("birth_date") && birthDate)
915
+ fields.birthDate = birthDate;
916
+ if ((domain.customFields ?? []).length > 0)
917
+ fields.customFields = customFieldValues;
843
918
  const ok = await updateUser(fields);
844
919
  setSaving(false);
845
920
  if (ok) {
@@ -853,7 +928,19 @@ function DauthProfileModal({
853
928
  message: "Something went wrong. Please try again."
854
929
  });
855
930
  }
856
- }, [name, lastname, nickname, country, hasField, updateUser]);
931
+ }, [
932
+ name,
933
+ lastname,
934
+ nickname,
935
+ country,
936
+ telPrefix,
937
+ telSuffix,
938
+ birthDate,
939
+ customFieldValues,
940
+ hasField,
941
+ updateUser,
942
+ domain.customFields
943
+ ]);
857
944
  const handleDelete = useCallback(async () => {
858
945
  setDeleting(true);
859
946
  const ok = await deleteAccount();
@@ -909,19 +996,21 @@ function DauthProfileModal({
909
996
  [deletePasskeyCredential]
910
997
  );
911
998
  const handleAvatarClick = useCallback(() => {
912
- if (onAvatarUpload) {
913
- avatarInputRef.current?.click();
914
- }
915
- }, [onAvatarUpload]);
999
+ avatarInputRef.current?.click();
1000
+ }, []);
916
1001
  const handleAvatarChange = useCallback(
917
1002
  async (e) => {
918
1003
  const file = e.target.files?.[0];
919
- if (!file || !onAvatarUpload) return;
1004
+ if (!file) return;
920
1005
  setUploadingAvatar(true);
921
1006
  try {
922
- const url = await onAvatarUpload(file);
923
- if (url) {
924
- await updateUser({ avatar: url });
1007
+ if (onAvatarUpload) {
1008
+ const url = await onAvatarUpload(file);
1009
+ if (url) {
1010
+ await updateUser({ avatar: url });
1011
+ }
1012
+ } else {
1013
+ await uploadAvatar(file);
925
1014
  }
926
1015
  } catch {
927
1016
  }
@@ -930,7 +1019,7 @@ function DauthProfileModal({
930
1019
  avatarInputRef.current.value = "";
931
1020
  }
932
1021
  },
933
- [onAvatarUpload, updateUser]
1022
+ [onAvatarUpload, updateUser, uploadAvatar]
934
1023
  );
935
1024
  const handleSignOut = useCallback(() => {
936
1025
  logout();
@@ -1072,7 +1161,7 @@ function DauthProfileModal({
1072
1161
  {
1073
1162
  style: {
1074
1163
  ...avatarCircle,
1075
- cursor: onAvatarUpload ? "pointer" : "default",
1164
+ cursor: "pointer",
1076
1165
  position: "relative"
1077
1166
  },
1078
1167
  onClick: handleAvatarClick,
@@ -1089,12 +1178,12 @@ function DauthProfileModal({
1089
1178
  }
1090
1179
  }
1091
1180
  ) : avatarInitial,
1092
- onAvatarUpload && !uploadingAvatar && /* @__PURE__ */ jsx("div", { style: avatarOverlay, children: /* @__PURE__ */ jsx(IconCamera, {}) })
1181
+ !uploadingAvatar && /* @__PURE__ */ jsx("div", { style: avatarOverlay, children: /* @__PURE__ */ jsx(IconCamera, {}) })
1093
1182
  ]
1094
1183
  }
1095
1184
  ),
1096
1185
  /* @__PURE__ */ jsx("div", { style: emailText, children: user.email }),
1097
- onAvatarUpload && /* @__PURE__ */ jsx(
1186
+ /* @__PURE__ */ jsx(
1098
1187
  "input",
1099
1188
  {
1100
1189
  ref: avatarInputRef,
@@ -1219,6 +1308,127 @@ function DauthProfileModal({
1219
1308
  onBlur: inputBlurHandler
1220
1309
  }
1221
1310
  )
1311
+ ] }),
1312
+ (hasField("tel_prefix") || hasField("tel_suffix")) && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1313
+ /* @__PURE__ */ jsxs("div", { style: label, children: [
1314
+ "Phone",
1315
+ isRequired("tel_prefix") || isRequired("tel_suffix") ? " *" : ""
1316
+ ] }),
1317
+ /* @__PURE__ */ jsxs(
1318
+ "div",
1319
+ {
1320
+ style: {
1321
+ display: "flex",
1322
+ gap: 8
1323
+ },
1324
+ children: [
1325
+ hasField("tel_prefix") && /* @__PURE__ */ jsx(
1326
+ "input",
1327
+ {
1328
+ id: "dauth-tel-prefix",
1329
+ type: "text",
1330
+ value: telPrefix,
1331
+ onChange: (e) => setTelPrefix(e.target.value),
1332
+ placeholder: "+34",
1333
+ disabled: saving,
1334
+ style: {
1335
+ ...input,
1336
+ width: 80,
1337
+ flexShrink: 0
1338
+ },
1339
+ onFocus: inputFocusHandler,
1340
+ onBlur: inputBlurHandler,
1341
+ "aria-label": "Phone prefix"
1342
+ }
1343
+ ),
1344
+ hasField("tel_suffix") && /* @__PURE__ */ jsx(
1345
+ "input",
1346
+ {
1347
+ id: "dauth-tel-suffix",
1348
+ type: "tel",
1349
+ value: telSuffix,
1350
+ onChange: (e) => setTelSuffix(e.target.value),
1351
+ placeholder: "612 345 678",
1352
+ disabled: saving,
1353
+ style: {
1354
+ ...input,
1355
+ flex: 1
1356
+ },
1357
+ onFocus: inputFocusHandler,
1358
+ onBlur: inputBlurHandler,
1359
+ "aria-label": "Phone number"
1360
+ }
1361
+ )
1362
+ ]
1363
+ }
1364
+ )
1365
+ ] }),
1366
+ hasField("birth_date") && /* @__PURE__ */ jsxs("div", { style: fieldGroup, children: [
1367
+ /* @__PURE__ */ jsxs(
1368
+ "label",
1369
+ {
1370
+ htmlFor: "dauth-birthdate",
1371
+ style: label,
1372
+ children: [
1373
+ "Birth date",
1374
+ isRequired("birth_date") ? " *" : ""
1375
+ ]
1376
+ }
1377
+ ),
1378
+ /* @__PURE__ */ jsx(
1379
+ "input",
1380
+ {
1381
+ id: "dauth-birthdate",
1382
+ type: "date",
1383
+ value: birthDate,
1384
+ onChange: (e) => setBirthDate(e.target.value),
1385
+ disabled: saving,
1386
+ style: input,
1387
+ onFocus: inputFocusHandler,
1388
+ onBlur: inputBlurHandler
1389
+ }
1390
+ )
1391
+ ] }),
1392
+ (domain.customFields ?? []).length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1393
+ /* @__PURE__ */ jsx("hr", { style: separator }),
1394
+ domain.customFields.map((cf) => /* @__PURE__ */ jsxs(
1395
+ "div",
1396
+ {
1397
+ style: fieldGroup,
1398
+ children: [
1399
+ /* @__PURE__ */ jsxs(
1400
+ "label",
1401
+ {
1402
+ htmlFor: `dauth-cf-${cf.key}`,
1403
+ style: label,
1404
+ children: [
1405
+ cf.label,
1406
+ cf.required ? " *" : ""
1407
+ ]
1408
+ }
1409
+ ),
1410
+ /* @__PURE__ */ jsx(
1411
+ "input",
1412
+ {
1413
+ id: `dauth-cf-${cf.key}`,
1414
+ type: "text",
1415
+ value: customFieldValues[cf.key] ?? "",
1416
+ onChange: (e) => setCustomFieldValues(
1417
+ (prev) => ({
1418
+ ...prev,
1419
+ [cf.key]: e.target.value
1420
+ })
1421
+ ),
1422
+ disabled: saving,
1423
+ style: input,
1424
+ onFocus: inputFocusHandler,
1425
+ onBlur: inputBlurHandler
1426
+ }
1427
+ )
1428
+ ]
1429
+ },
1430
+ cf.key
1431
+ ))
1222
1432
  ] })
1223
1433
  ] }),
1224
1434
  /* @__PURE__ */ jsx("hr", { style: separator }),
@@ -2043,6 +2253,10 @@ var DauthProvider = (props) => {
2043
2253
  (credentialId) => deletePasskeyCredentialAction(ctx, credentialId),
2044
2254
  [ctx]
2045
2255
  );
2256
+ const uploadAvatar = useCallback2(
2257
+ (file) => uploadAvatarAction(ctx, file),
2258
+ [ctx]
2259
+ );
2046
2260
  const memoProvider = useMemo2(
2047
2261
  () => ({
2048
2262
  ...dauthState,
@@ -2052,7 +2266,8 @@ var DauthProvider = (props) => {
2052
2266
  deleteAccount,
2053
2267
  getPasskeyCredentials,
2054
2268
  registerPasskey,
2055
- deletePasskeyCredential
2269
+ deletePasskeyCredential,
2270
+ uploadAvatar
2056
2271
  }),
2057
2272
  [
2058
2273
  dauthState,
@@ -2062,7 +2277,8 @@ var DauthProvider = (props) => {
2062
2277
  deleteAccount,
2063
2278
  getPasskeyCredentials,
2064
2279
  registerPasskey,
2065
- deletePasskeyCredential
2280
+ deletePasskeyCredential,
2281
+ uploadAvatar
2066
2282
  ]
2067
2283
  );
2068
2284
  return /* @__PURE__ */ jsx2(DauthContext.Provider, { value: memoProvider, children });