@asdp/ferryui 0.1.22-dev.9214 → 0.1.22-dev.9319

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.js CHANGED
@@ -494,7 +494,7 @@ var useStyles2 = reactComponents.makeStyles({
494
494
  display: "flex",
495
495
  gap: `${spacing2[360]}px`,
496
496
  alignItems: "center",
497
- justifyContent: "center",
497
+ justifyContent: "start",
498
498
  [`@media (max-width: ${extendedTokens.breakpointMd})`]: {
499
499
  gap: reactComponents.tokens.spacingVerticalXS
500
500
  }
@@ -502,7 +502,7 @@ var useStyles2 = reactComponents.makeStyles({
502
502
  carouselContainerNoNav: {
503
503
  display: "flex",
504
504
  alignItems: "center",
505
- justifyContent: "center"
505
+ justifyContent: "start"
506
506
  },
507
507
  customCarouselNav: {
508
508
  display: "flex",
@@ -590,6 +590,29 @@ var useStyles2 = reactComponents.makeStyles({
590
590
  height: "10px"
591
591
  }
592
592
  }
593
+ },
594
+ singleIndicatorWrapper: {
595
+ display: "flex",
596
+ justifyContent: "center",
597
+ alignItems: "center",
598
+ marginTop: reactComponents.tokens.spacingVerticalXXL,
599
+ ...reactComponents.shorthands.padding(reactComponents.tokens.spacingVerticalS, reactComponents.tokens.spacingVerticalM),
600
+ borderRadius: reactComponents.tokens.borderRadiusCircular
601
+ },
602
+ singleIndicatorDot: {
603
+ backgroundImage: "linear-gradient(to right,#00B3BD, #8DC63F)",
604
+ display: "inline-block",
605
+ width: "55px",
606
+ height: "16px",
607
+ borderRadius: reactComponents.tokens.borderRadiusCircular,
608
+ "@media (max-width: 768px)": {
609
+ width: "35px",
610
+ height: "13px"
611
+ },
612
+ "@media (max-width: 425px)": {
613
+ width: "25px",
614
+ height: "10px"
615
+ }
593
616
  }
594
617
  });
595
618
  var CarouselWithCustomNav = ({
@@ -615,6 +638,8 @@ var CarouselWithCustomNav = ({
615
638
  }) => {
616
639
  const styles = useStyles2();
617
640
  const [internalIndex, setInternalIndex] = React.useState(0);
641
+ const totalSlides = React__default.default.Children.count(children);
642
+ const isSingleSlide = totalSlides === 1;
618
643
  const labels = React__default.default.useMemo(
619
644
  () => ({
620
645
  ...DEFAULT_LABELS2[language],
@@ -623,20 +648,19 @@ var CarouselWithCustomNav = ({
623
648
  }),
624
649
  [language, customLabels, deprecatedAriaLabel]
625
650
  );
626
- const activeIndex = controlledIndex !== void 0 ? controlledIndex : internalIndex;
651
+ const activeIndex = isSingleSlide ? 0 : controlledIndex !== void 0 ? controlledIndex : internalIndex;
627
652
  const handleIndexChange = React.useCallback(
628
653
  (index) => {
654
+ if (isSingleSlide) return;
629
655
  if (controlledIndex === void 0) {
630
656
  setInternalIndex(index);
631
657
  }
632
658
  onActiveIndexChange?.(index);
633
659
  },
634
- [controlledIndex, onActiveIndexChange]
660
+ [controlledIndex, onActiveIndexChange, isSingleSlide]
635
661
  );
636
662
  React__default.default.useEffect(() => {
637
- if (!autoPlay) return;
638
- const totalSlides = React__default.default.Children.count(children);
639
- if (totalSlides <= 1) return;
663
+ if (!autoPlay || isSingleSlide) return;
640
664
  const intervalId = setInterval(() => {
641
665
  let nextIndex = activeIndex + 1;
642
666
  if (nextIndex >= totalSlides) {
@@ -653,15 +677,16 @@ var CarouselWithCustomNav = ({
653
677
  }, [
654
678
  autoPlay,
655
679
  autoPlayInterval,
656
- children,
680
+ totalSlides,
657
681
  circular,
658
682
  activeIndex,
659
683
  controlledIndex,
660
- onActiveIndexChange
684
+ onActiveIndexChange,
685
+ isSingleSlide
661
686
  ]);
662
687
  const defaultAnnouncement = React.useCallback(
663
- (index, totalSlides) => {
664
- return labels.announcementTemplate.replace("{index}", (index + 1).toString()).replace("{total}", totalSlides.toString());
688
+ (index, totalSlides2) => {
689
+ return labels.announcementTemplate.replace("{index}", (index + 1).toString()).replace("{total}", totalSlides2.toString());
665
690
  },
666
691
  [labels.announcementTemplate]
667
692
  );
@@ -669,7 +694,7 @@ var CarouselWithCustomNav = ({
669
694
  return /* @__PURE__ */ jsxRuntime.jsxs(
670
695
  reactComponents.Carousel,
671
696
  {
672
- circular,
697
+ circular: isSingleSlide ? true : circular,
673
698
  draggable,
674
699
  align,
675
700
  className: reactComponents.mergeClasses(styles.carousel, className),
@@ -678,53 +703,73 @@ var CarouselWithCustomNav = ({
678
703
  activeIndex,
679
704
  onActiveIndexChange: (_, data) => handleIndexChange(data.index),
680
705
  children: [
681
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: showNavButtons ? styles.carouselContainer : styles.carouselContainerNoNav, children: [
682
- showNavButtons && /* @__PURE__ */ jsxRuntime.jsx(
683
- reactComponents.CarouselButton,
684
- {
685
- navType: "prev",
686
- "aria-label": labels.prevButtonAriaLabel,
687
- className: styles.customeCarouselButton
688
- }
689
- ),
690
- /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.CarouselViewport, { style: { overflow: "hidden", paddingBottom: "10px" }, children: [
691
- showCloseButton && /* @__PURE__ */ jsxRuntime.jsx(
692
- reactComponents.Button,
693
- {
694
- icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DismissRegular, {}),
695
- shape: "circular",
696
- onClick: onCloseClick,
697
- "aria-label": labels.closeButtonAriaLabel,
698
- className: reactComponents.mergeClasses(
699
- styles.closeButton,
700
- showNavButtons ? styles.closeButtonWithNav : styles.closeButtonWithoutNav
706
+ /* @__PURE__ */ jsxRuntime.jsxs(
707
+ "div",
708
+ {
709
+ className: showNavButtons ? styles.carouselContainer : styles.carouselContainerNoNav,
710
+ children: [
711
+ showNavButtons && !isSingleSlide && /* @__PURE__ */ jsxRuntime.jsx(
712
+ reactComponents.CarouselButton,
713
+ {
714
+ navType: "prev",
715
+ "aria-label": labels.prevButtonAriaLabel,
716
+ className: styles.customeCarouselButton
717
+ }
718
+ ),
719
+ /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.CarouselViewport, { style: { overflow: "hidden", paddingBottom: "10px" }, children: [
720
+ showCloseButton && /* @__PURE__ */ jsxRuntime.jsx(
721
+ reactComponents.Button,
722
+ {
723
+ icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DismissRegular, {}),
724
+ shape: "circular",
725
+ onClick: onCloseClick,
726
+ "aria-label": labels.closeButtonAriaLabel,
727
+ className: reactComponents.mergeClasses(
728
+ styles.closeButton,
729
+ showNavButtons ? styles.closeButtonWithNav : styles.closeButtonWithoutNav
730
+ )
731
+ }
732
+ ),
733
+ /* @__PURE__ */ jsxRuntime.jsx(
734
+ reactComponents.CarouselSlider,
735
+ {
736
+ cardFocus,
737
+ "aria-label": labels.carouselAriaLabel,
738
+ children: isSingleSlide ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
739
+ children,
740
+ children
741
+ ] }) : children
742
+ }
701
743
  )
702
- }
703
- ),
704
- /* @__PURE__ */ jsxRuntime.jsx(
705
- reactComponents.CarouselSlider,
706
- {
707
- cardFocus,
708
- "aria-label": labels.carouselAriaLabel,
709
- children
710
- }
711
- )
712
- ] }),
713
- showNavButtons && /* @__PURE__ */ jsxRuntime.jsx(
714
- reactComponents.CarouselButton,
715
- {
716
- navType: "next",
717
- "aria-label": labels.nextButtonAriaLabel,
718
- className: styles.customeCarouselButton
719
- }
720
- )
721
- ] }),
722
- /* @__PURE__ */ jsxRuntime.jsx(
744
+ ] }),
745
+ showNavButtons && !isSingleSlide && /* @__PURE__ */ jsxRuntime.jsx(
746
+ reactComponents.CarouselButton,
747
+ {
748
+ navType: "next",
749
+ "aria-label": labels.nextButtonAriaLabel,
750
+ className: styles.customeCarouselButton
751
+ }
752
+ )
753
+ ]
754
+ }
755
+ ),
756
+ isSingleSlide ? /* @__PURE__ */ jsxRuntime.jsx(
757
+ "div",
758
+ {
759
+ className: styles.singleIndicatorWrapper,
760
+ style: {
761
+ backgroundColor: darkNavBackground ? reactComponents.tokens.colorSubtleBackgroundInverted : reactComponents.tokens.colorSubtleBackground,
762
+ justifyContent: align === "start" ? "flex-start" : align === "end" ? "flex-end" : "center"
763
+ },
764
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.singleIndicatorDot })
765
+ }
766
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
723
767
  reactComponents.CarouselNav,
724
768
  {
725
769
  style: {
726
770
  backgroundColor: darkNavBackground ? reactComponents.tokens.colorSubtleBackgroundInverted : reactComponents.tokens.colorSubtleBackground,
727
- marginTop: reactComponents.tokens.spacingVerticalXXL
771
+ marginTop: reactComponents.tokens.spacingVerticalXXL,
772
+ justifyContent: align === "start" ? "flex-start" : align === "end" ? "flex-end" : "center"
728
773
  },
729
774
  appearance: "brand",
730
775
  className: styles.carouselNavButton,
@@ -2477,7 +2522,9 @@ var DatePickerInput = React.forwardRef(
2477
2522
  contentBefore,
2478
2523
  onClick,
2479
2524
  style,
2525
+ min,
2480
2526
  max,
2527
+ disablePastDates = false,
2481
2528
  ...restProps
2482
2529
  }, ref) => {
2483
2530
  const [isOpen, setIsOpen] = React.useState(false);
@@ -2506,6 +2553,12 @@ var DatePickerInput = React.forwardRef(
2506
2553
  }
2507
2554
  onClick?.(e);
2508
2555
  };
2556
+ const getStartOfToday = () => {
2557
+ const today = /* @__PURE__ */ new Date();
2558
+ today.setHours(0, 0, 0, 0);
2559
+ return today;
2560
+ };
2561
+ const minDate = min ? new Date(min) : disablePastDates ? getStartOfToday() : void 0;
2509
2562
  return /* @__PURE__ */ jsxRuntime.jsxs(
2510
2563
  reactComponents.Popover,
2511
2564
  {
@@ -2556,6 +2609,7 @@ var DatePickerInput = React.forwardRef(
2556
2609
  showGoToToday: true,
2557
2610
  highlightSelectedMonth: true,
2558
2611
  showMonthPickerAsOverlay: false,
2612
+ minDate,
2559
2613
  maxDate: max ? new Date(max) : void 0
2560
2614
  }
2561
2615
  ) })
@@ -3138,7 +3192,8 @@ var InputDynamic = ({
3138
3192
  onChange,
3139
3193
  language = "id",
3140
3194
  labels,
3141
- menuPlacement
3195
+ menuPlacement,
3196
+ disablePastDates = false
3142
3197
  }) => {
3143
3198
  const styles = useStyles8();
3144
3199
  const mergedLabels = { ...DEFAULT_LABELS7[language], ...labels };
@@ -3350,7 +3405,8 @@ var InputDynamic = ({
3350
3405
  const getPhoneAppearanceClass = () => {
3351
3406
  if (appearance === "underline") return styles.phoneInputUnderline;
3352
3407
  if (appearance === "filled-darker") return styles.phoneInputFilledDarker;
3353
- if (appearance === "filled-lighter") return styles.phoneInputFilledLighter;
3408
+ if (appearance === "filled-lighter")
3409
+ return styles.phoneInputFilledLighter;
3354
3410
  return "";
3355
3411
  };
3356
3412
  const phoneAppearanceClass = getPhoneAppearanceClass();
@@ -3383,9 +3439,21 @@ var InputDynamic = ({
3383
3439
  const fontSizeValuePhoneInput = size == "small" ? reactComponents.tokens.fontSizeBase200 : size === "medium" ? reactComponents.tokens.fontSizeBase300 : reactComponents.tokens.fontSizeBase400;
3384
3440
  const phoneInputSizeStyle = {
3385
3441
  fontSize: fontSizeValuePhoneInput,
3386
- ...size === "small" && { minHeight: "26px", height: "26px", padding: `0 ${reactComponents.tokens.spacingHorizontalS} 0 48px` },
3387
- ...size === "medium" && { minHeight: "34px", height: "34px", padding: `${reactComponents.tokens.spacingVerticalXXS} ${reactComponents.tokens.spacingHorizontalS} ${reactComponents.tokens.spacingVerticalXXS} 48px` },
3388
- ...size === "large" && { minHeight: "40px", height: "40px", padding: `${reactComponents.tokens.spacingVerticalXS} ${reactComponents.tokens.spacingHorizontalS} ${reactComponents.tokens.spacingVerticalXS} 48px` }
3442
+ ...size === "small" && {
3443
+ minHeight: "26px",
3444
+ height: "26px",
3445
+ padding: `0 ${reactComponents.tokens.spacingHorizontalS} 0 48px`
3446
+ },
3447
+ ...size === "medium" && {
3448
+ minHeight: "34px",
3449
+ height: "34px",
3450
+ padding: `${reactComponents.tokens.spacingVerticalXXS} ${reactComponents.tokens.spacingHorizontalS} ${reactComponents.tokens.spacingVerticalXXS} 48px`
3451
+ },
3452
+ ...size === "large" && {
3453
+ minHeight: "40px",
3454
+ height: "40px",
3455
+ padding: `${reactComponents.tokens.spacingVerticalXS} ${reactComponents.tokens.spacingHorizontalS} ${reactComponents.tokens.spacingVerticalXS} 48px`
3456
+ }
3389
3457
  };
3390
3458
  if (type === "emailOrPhone") {
3391
3459
  updateEmailOrPhoneType(field.value);
@@ -3422,10 +3490,15 @@ var InputDynamic = ({
3422
3490
  "div",
3423
3491
  {
3424
3492
  ref: emailOrPhoneInputRef,
3425
- className: reactComponents.mergeClasses(styles.phoneInputWrapper, phoneAppearanceClass, error ? styles.phoneInputError : ""),
3493
+ className: reactComponents.mergeClasses(
3494
+ styles.phoneInputWrapper,
3495
+ phoneAppearanceClass,
3496
+ error ? styles.phoneInputError : ""
3497
+ ),
3426
3498
  children: /* @__PURE__ */ jsxRuntime.jsx(
3427
3499
  PhoneInput,
3428
3500
  {
3501
+ countryCodeEditable: false,
3429
3502
  inputStyle: phoneInputSizeStyle,
3430
3503
  country: defaultCountry.toLowerCase(),
3431
3504
  value: stringValue.startsWith("+") ? stringValue.substring(1) : stringValue,
@@ -3525,10 +3598,15 @@ var InputDynamic = ({
3525
3598
  "div",
3526
3599
  {
3527
3600
  ref: phoneInputRef,
3528
- className: reactComponents.mergeClasses(styles.phoneInputWrapper, phoneAppearanceClass, error ? styles.phoneInputError : ""),
3601
+ className: reactComponents.mergeClasses(
3602
+ styles.phoneInputWrapper,
3603
+ phoneAppearanceClass,
3604
+ error ? styles.phoneInputError : ""
3605
+ ),
3529
3606
  children: /* @__PURE__ */ jsxRuntime.jsx(
3530
3607
  PhoneInput,
3531
3608
  {
3609
+ countryCodeEditable: false,
3532
3610
  country: defaultCountry.toLowerCase(),
3533
3611
  value: stringValue.startsWith("+") ? stringValue.substring(1) : stringValue,
3534
3612
  onChange: (value, data) => {
@@ -3660,7 +3738,9 @@ var InputDynamic = ({
3660
3738
  autoCapitalize: "off",
3661
3739
  spellCheck: "false"
3662
3740
  },
3663
- value: (options && options.length > 0 ? options : COUNTRIES).find((country) => country.value === field.value) || null,
3741
+ value: (options && options.length > 0 ? options : COUNTRIES).find(
3742
+ (country) => country.value === field.value
3743
+ ) || null,
3664
3744
  onChange: (selectedOption) => {
3665
3745
  field.onChange(selectedOption ? selectedOption.value : "");
3666
3746
  if (onChange) {
@@ -3718,12 +3798,16 @@ var InputDynamic = ({
3718
3798
  return /* @__PURE__ */ jsxRuntime.jsx(
3719
3799
  "div",
3720
3800
  {
3721
- className: reactComponents.mergeClasses(styles.phoneInputWrapper, phoneAppearanceClass, error ? styles.phoneInputError : ""),
3801
+ className: reactComponents.mergeClasses(
3802
+ styles.phoneInputWrapper,
3803
+ phoneAppearanceClass,
3804
+ error ? styles.phoneInputError : ""
3805
+ ),
3722
3806
  children: /* @__PURE__ */ jsxRuntime.jsx(
3723
3807
  PhoneInput,
3724
3808
  {
3809
+ countryCodeEditable: false,
3725
3810
  ...phoneInputProps,
3726
- onlyCountries,
3727
3811
  country: defaultCountry.toLowerCase(),
3728
3812
  disabled,
3729
3813
  disableSearchIcon: true,
@@ -3778,7 +3862,9 @@ var InputDynamic = ({
3778
3862
  size,
3779
3863
  onClick,
3780
3864
  style: inputStyle,
3781
- max: max ? String(max) : void 0
3865
+ max: max ? String(max) : void 0,
3866
+ min: min ? String(min) : void 0,
3867
+ disablePastDates
3782
3868
  }
3783
3869
  );
3784
3870
  }
@@ -4085,7 +4171,9 @@ var InputDynamic = ({
4085
4171
  if (!stringValue) return true;
4086
4172
  const detectedType = detectEmailOrPhoneStrict(stringValue);
4087
4173
  if (detectedType === "email") {
4088
- if (!/^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/i.test(stringValue)) {
4174
+ if (!/^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/i.test(
4175
+ stringValue
4176
+ )) {
4089
4177
  return mergedLabels.invalidEmailFormatError;
4090
4178
  }
4091
4179
  } else if (detectedType === "phone") {
@@ -4114,7 +4202,9 @@ var InputDynamic = ({
4114
4202
  if (!stringValue) return true;
4115
4203
  const detectedType = detectIdentityType(stringValue);
4116
4204
  if (detectedType === "email") {
4117
- if (!/^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/i.test(stringValue)) {
4205
+ if (!/^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/i.test(
4206
+ stringValue
4207
+ )) {
4118
4208
  return mergedLabels.invalidEmailFormatError;
4119
4209
  }
4120
4210
  } else if (detectedType === "phone") {
@@ -4161,29 +4251,40 @@ var InputDynamic = ({
4161
4251
  }
4162
4252
  ),
4163
4253
  renderInput(field, error?.message),
4164
- helperText && !error && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "flex-start", gap: "4px", marginTop: "4px" }, children: [
4165
- helperIcon && /* @__PURE__ */ jsxRuntime.jsx(
4166
- react.Icon,
4167
- {
4168
- icon: helperIcon,
4169
- style: {
4170
- color: reactComponents.tokens.colorNeutralForeground3,
4171
- flexShrink: 0
4172
- },
4173
- width: 16,
4174
- height: 16
4175
- }
4176
- ),
4177
- /* @__PURE__ */ jsxRuntime.jsx(
4178
- reactComponents.Text,
4179
- {
4180
- size: 200,
4181
- style: { textAlign: "left" },
4182
- className: styles.helperText,
4183
- children: helperText
4184
- }
4185
- )
4186
- ] })
4254
+ helperText && !error && /* @__PURE__ */ jsxRuntime.jsxs(
4255
+ "div",
4256
+ {
4257
+ style: {
4258
+ display: "flex",
4259
+ alignItems: "flex-start",
4260
+ gap: "4px",
4261
+ marginTop: "4px"
4262
+ },
4263
+ children: [
4264
+ helperIcon && /* @__PURE__ */ jsxRuntime.jsx(
4265
+ react.Icon,
4266
+ {
4267
+ icon: helperIcon,
4268
+ style: {
4269
+ color: reactComponents.tokens.colorNeutralForeground3,
4270
+ flexShrink: 0
4271
+ },
4272
+ width: 16,
4273
+ height: 16
4274
+ }
4275
+ ),
4276
+ /* @__PURE__ */ jsxRuntime.jsx(
4277
+ reactComponents.Text,
4278
+ {
4279
+ size: 200,
4280
+ style: { textAlign: "left" },
4281
+ className: styles.helperText,
4282
+ children: helperText
4283
+ }
4284
+ )
4285
+ ]
4286
+ }
4287
+ )
4187
4288
  ]
4188
4289
  }
4189
4290
  )
@@ -5298,7 +5399,8 @@ var DEFAULT_LABELS10 = {
5298
5399
  loadingData: "Memuat data...",
5299
5400
  harborNotFound: "Pelabuhan tidak ditemukan",
5300
5401
  closeAriaLabel: "Tutup",
5301
- popularHarborHeader: "Pelabuhan Populer"
5402
+ popularHarborHeader: "Pelabuhan Populer",
5403
+ favoriteHeader: "Favorit"
5302
5404
  },
5303
5405
  en: {
5304
5406
  title: "Select Harbor",
@@ -5309,7 +5411,8 @@ var DEFAULT_LABELS10 = {
5309
5411
  loadingData: "Loading data...",
5310
5412
  harborNotFound: "Harbor not found",
5311
5413
  closeAriaLabel: "Close",
5312
- popularHarborHeader: "Popular Harbor"
5414
+ popularHarborHeader: "Popular Harbor",
5415
+ favoriteHeader: "Favorite"
5313
5416
  }
5314
5417
  };
5315
5418
  var useStyles11 = reactComponents.makeStyles({
@@ -5378,10 +5481,20 @@ var useStyles11 = reactComponents.makeStyles({
5378
5481
  display: "flex",
5379
5482
  gap: "1rem",
5380
5483
  marginBottom: "1rem",
5381
- flexWrap: "wrap"
5484
+ flexWrap: "wrap",
5485
+ marginTop: "1rem"
5382
5486
  },
5383
5487
  circularButton: {
5384
- borderRadius: reactComponents.tokens.borderRadiusCircular
5488
+ borderRadius: reactComponents.tokens.borderRadius3XLarge,
5489
+ border: `1px solid ${reactComponents.tokens.colorBrandBackground}`,
5490
+ backgroundColor: brandColors2["140"],
5491
+ gap: "5px"
5492
+ },
5493
+ buttonContent: {
5494
+ display: "flex",
5495
+ flexDirection: "column",
5496
+ alignItems: "center",
5497
+ justifyContent: "center"
5385
5498
  },
5386
5499
  headerRow: {
5387
5500
  display: "flex",
@@ -5395,11 +5508,13 @@ var useStyles11 = reactComponents.makeStyles({
5395
5508
  historyItem: {
5396
5509
  display: "flex",
5397
5510
  justifyContent: "space-between",
5511
+ alignItems: "center",
5398
5512
  marginTop: "1rem",
5399
5513
  marginBottom: "1rem"
5400
5514
  },
5401
5515
  iconMargin: {
5402
- marginRight: "0.5rem"
5516
+ marginRight: "1rem"
5517
+ // fontSize: tokens.fontSizeBase400
5403
5518
  },
5404
5519
  cursorPointer: {
5405
5520
  cursor: "pointer"
@@ -5416,14 +5531,51 @@ var useStyles11 = reactComponents.makeStyles({
5416
5531
  },
5417
5532
  harborItem: {
5418
5533
  display: "flex",
5419
- justifyContent: "space-between"
5534
+ justifyContent: "space-between",
5535
+ alignItems: "center"
5420
5536
  },
5421
5537
  emptyState: {
5422
5538
  textAlign: "center",
5423
5539
  padding: "32px",
5424
5540
  color: reactComponents.tokens.colorNeutralForeground3
5541
+ },
5542
+ listContent: {
5543
+ cursor: "pointer",
5544
+ display: "flex",
5545
+ justifyContent: "center",
5546
+ alignItems: "center"
5425
5547
  }
5426
5548
  });
5549
+ var HarborListItem = ({
5550
+ harbor,
5551
+ onSelect,
5552
+ trailingIcon,
5553
+ showDivider,
5554
+ containerClassName
5555
+ }) => {
5556
+ const styles = useStyles11();
5557
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5558
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClassName, children: [
5559
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.listContent, onClick: () => onSelect(harbor), children: [
5560
+ /* @__PURE__ */ jsxRuntime.jsx(
5561
+ react.Icon,
5562
+ {
5563
+ icon: "fluent:vehicle-ship-24-regular",
5564
+ fontSize: 20,
5565
+ className: styles.iconMargin
5566
+ }
5567
+ ),
5568
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "left" }, children: [
5569
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1, { children: harbor.portName }),
5570
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
5571
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Caption1, { children: harbor.branchName })
5572
+ ] })
5573
+ ] }),
5574
+ trailingIcon
5575
+ ] }),
5576
+ showDivider && /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Divider, {})
5577
+ ] });
5578
+ };
5427
5579
  var ModalSearchHarbor = ({
5428
5580
  language = "id",
5429
5581
  labels,
@@ -5442,6 +5594,7 @@ var ModalSearchHarbor = ({
5442
5594
  onAddLastSearched,
5443
5595
  onRemoveLastSearched,
5444
5596
  onClearLastSearched,
5597
+ onClearFavorite,
5445
5598
  popularHarbors,
5446
5599
  showButtonFavorite = true
5447
5600
  }) => {
@@ -5500,119 +5653,169 @@ var ModalSearchHarbor = ({
5500
5653
  size: "large"
5501
5654
  }
5502
5655
  ) }),
5503
- favoriteHarbors.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.buttonContainer, children: favoriteHarbors.map((harbor) => /* @__PURE__ */ jsxRuntime.jsx(
5504
- reactComponents.Button,
5505
- {
5506
- onClick: () => handleSelect(harbor),
5507
- size: "medium",
5508
- appearance: "outline",
5509
- iconPosition: "before",
5510
- className: styles.circularButton,
5511
- icon: /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "fluent:ribbon-20-filled" }),
5512
- children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1, { children: harbor.portName + ", " + harbor.branchName })
5513
- },
5514
- harbor.portId
5515
- )) }),
5516
- /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Divider, {}),
5517
5656
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.resultList, children: [
5518
- lastSearchedHarbors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5657
+ favoriteHarbors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5519
5658
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.headerRow, children: [
5520
- /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1Strong, { children: mergedLabels.lastSearchedHeader }),
5659
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1Strong, { children: mergedLabels.favoriteHeader }),
5521
5660
  /* @__PURE__ */ jsxRuntime.jsx(
5522
5661
  reactComponents.Caption1,
5523
5662
  {
5524
- className: `${styles.dangerText} ${styles.cursorPointer}`,
5525
- onClick: onClearLastSearched,
5663
+ className: reactComponents.mergeClasses(
5664
+ styles.dangerText,
5665
+ styles.cursorPointer
5666
+ ),
5667
+ onClick: onClearFavorite,
5526
5668
  children: mergedLabels.clearAllButton
5527
5669
  }
5528
5670
  )
5529
5671
  ] }),
5530
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: lastSearchedHarbors.map((harbor) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.historyItem, children: [
5531
- /* @__PURE__ */ jsxRuntime.jsxs(
5532
- "div",
5533
- {
5534
- style: { cursor: "pointer" },
5535
- onClick: () => handleSelect(harbor),
5536
- children: [
5537
- /* @__PURE__ */ jsxRuntime.jsx(
5538
- react.Icon,
5539
- {
5540
- icon: "fluent:vehicle-ship-24-regular",
5541
- className: styles.iconMargin
5542
- }
5543
- ),
5544
- harbor.portName + ", " + harbor.branchName
5545
- ]
5546
- }
5547
- ),
5548
- /* @__PURE__ */ jsxRuntime.jsx(
5549
- react.Icon,
5550
- {
5551
- onClick: () => onRemoveLastSearched(harbor),
5552
- icon: "fluent:dismiss-24-regular",
5553
- color: reactComponents.tokens.colorStatusDangerForeground1,
5554
- className: styles.cursorPointer
5555
- }
5556
- )
5557
- ] }, harbor.portId)) }),
5558
- /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Divider, {})
5559
- ] }),
5560
- popularHarbors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5561
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.headerRow, children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1Strong, { children: mergedLabels.popularHarborHeader }) }),
5562
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: popularHarbors.map((harbor) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.historyItem, children: /* @__PURE__ */ jsxRuntime.jsxs(
5563
- "div",
5672
+ favoriteHarbors.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.buttonContainer, children: favoriteHarbors.map((harbor) => /* @__PURE__ */ jsxRuntime.jsxs(
5673
+ reactComponents.Button,
5564
5674
  {
5565
- style: { cursor: "pointer" },
5566
5675
  onClick: () => handleSelect(harbor),
5676
+ size: "medium",
5677
+ appearance: "subtle",
5678
+ iconPosition: "before",
5679
+ className: styles.circularButton,
5680
+ icon: /* @__PURE__ */ jsxRuntime.jsx(
5681
+ react.Icon,
5682
+ {
5683
+ icon: "fluent:vehicle-ship-20-regular",
5684
+ fontSize: 20,
5685
+ color: reactComponents.tokens.colorBrandBackground
5686
+ }
5687
+ ),
5567
5688
  children: [
5689
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.buttonContent, children: [
5690
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1, { children: harbor.portName }),
5691
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Caption1, { children: harbor.branchName })
5692
+ ] }),
5568
5693
  /* @__PURE__ */ jsxRuntime.jsx(
5569
5694
  react.Icon,
5570
5695
  {
5571
- icon: "fluent:vehicle-ship-24-regular",
5572
- className: styles.iconMargin
5696
+ icon: "fluent:star-24-filled",
5697
+ fontSize: 20,
5698
+ color: reactComponents.tokens.colorBrandBackground,
5699
+ style: { marginLeft: 5 }
5573
5700
  }
5574
- ),
5575
- harbor.portName + ", " + harbor.branchName
5701
+ )
5576
5702
  ]
5577
- }
5578
- ) }, harbor.portId)) }),
5579
- /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Divider, {})
5703
+ },
5704
+ harbor.portId
5705
+ )) })
5706
+ ] }),
5707
+ lastSearchedHarbors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5708
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.headerRow, children: [
5709
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1Strong, { children: mergedLabels.lastSearchedHeader }),
5710
+ /* @__PURE__ */ jsxRuntime.jsx(
5711
+ reactComponents.Caption1,
5712
+ {
5713
+ className: reactComponents.mergeClasses(
5714
+ styles.dangerText,
5715
+ styles.cursorPointer
5716
+ ),
5717
+ onClick: onClearLastSearched,
5718
+ children: mergedLabels.clearAllButton
5719
+ }
5720
+ )
5721
+ ] }),
5722
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: lastSearchedHarbors.map((harbor) => /* @__PURE__ */ jsxRuntime.jsx(
5723
+ HarborListItem,
5724
+ {
5725
+ harbor,
5726
+ onSelect: handleSelect,
5727
+ containerClassName: styles.historyItem,
5728
+ trailingIcon: /* @__PURE__ */ jsxRuntime.jsx(
5729
+ react.Icon,
5730
+ {
5731
+ onClick: () => onRemoveLastSearched(harbor),
5732
+ icon: "fluent:dismiss-24-regular",
5733
+ fontSize: 20,
5734
+ className: styles.cursorPointer
5735
+ }
5736
+ ),
5737
+ showDivider: true
5738
+ },
5739
+ harbor.portId
5740
+ )) })
5741
+ ] }),
5742
+ popularHarbors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5743
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.headerRow, children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1Strong, { children: mergedLabels.popularHarborHeader }) }),
5744
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: popularHarbors.map((harbor) => /* @__PURE__ */ jsxRuntime.jsx(
5745
+ HarborListItem,
5746
+ {
5747
+ harbor,
5748
+ onSelect: handleSelect,
5749
+ containerClassName: styles.historyItem,
5750
+ showDivider: true
5751
+ },
5752
+ harbor.portId
5753
+ )) })
5580
5754
  ] }),
5581
5755
  /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1Strong, { className: styles.sectionTitle, children: mergedLabels.allHarborsHeader }),
5582
5756
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.harborList, children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: [1, 2, 3, 4, 5].map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.harborItem, children: [
5583
- /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Skeleton, { style: { display: "flex", alignItems: "center", gap: "0.5rem", width: "70%" }, children: [
5584
- /* @__PURE__ */ jsxRuntime.jsx(reactComponents.SkeletonItem, { style: { width: "24px", height: "24px", borderRadius: "4px" } }),
5585
- /* @__PURE__ */ jsxRuntime.jsx(reactComponents.SkeletonItem, { style: { width: "100%", height: "20px", borderRadius: "4px" } })
5586
- ] }),
5587
- showButtonFavorite && /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Skeleton, { children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.SkeletonItem, { style: { width: "24px", height: "24px", borderRadius: "4px" } }) })
5588
- ] }, item)) }) : harbors.length > 0 ? harbors.map((harbor, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.harborItem, children: [
5589
5757
  /* @__PURE__ */ jsxRuntime.jsxs(
5590
- "div",
5758
+ reactComponents.Skeleton,
5591
5759
  {
5592
- className: styles.cursorPointer,
5593
- onClick: () => handleSelect(harbor),
5760
+ style: {
5761
+ display: "flex",
5762
+ alignItems: "center",
5763
+ gap: "0.5rem",
5764
+ width: "70%"
5765
+ },
5594
5766
  children: [
5595
5767
  /* @__PURE__ */ jsxRuntime.jsx(
5596
- react.Icon,
5768
+ reactComponents.SkeletonItem,
5597
5769
  {
5598
- icon: "fluent:vehicle-ship-24-regular",
5599
- className: styles.iconMargin
5770
+ style: {
5771
+ width: "24px",
5772
+ height: "24px",
5773
+ borderRadius: "4px"
5774
+ }
5600
5775
  }
5601
5776
  ),
5602
- harbor.portName + ", " + harbor.branchName
5777
+ /* @__PURE__ */ jsxRuntime.jsx(
5778
+ reactComponents.SkeletonItem,
5779
+ {
5780
+ style: {
5781
+ width: "100%",
5782
+ height: "20px",
5783
+ borderRadius: "4px"
5784
+ }
5785
+ }
5786
+ )
5603
5787
  ]
5604
5788
  }
5605
5789
  ),
5606
- showButtonFavorite && /* @__PURE__ */ jsxRuntime.jsx(
5607
- react.Icon,
5790
+ showButtonFavorite && /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Skeleton, { children: /* @__PURE__ */ jsxRuntime.jsx(
5791
+ reactComponents.SkeletonItem,
5608
5792
  {
5609
- icon: harbor.isFavorite ? "fluent:star-24-filled" : "fluent:star-24-regular",
5610
- color: reactComponents.tokens.colorBrandBackground,
5611
- className: styles.cursorPointer,
5612
- onClick: () => onToggleFavorite(harbor)
5793
+ style: {
5794
+ width: "24px",
5795
+ height: "24px",
5796
+ borderRadius: "4px"
5797
+ }
5613
5798
  }
5614
- )
5615
- ] }, index)) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.emptyState, children: mergedLabels.harborNotFound }) })
5799
+ ) })
5800
+ ] }, item)) }) : harbors.length > 0 ? harbors.map((harbor, index) => /* @__PURE__ */ jsxRuntime.jsx(
5801
+ HarborListItem,
5802
+ {
5803
+ harbor,
5804
+ onSelect: handleSelect,
5805
+ containerClassName: styles.harborItem,
5806
+ trailingIcon: showButtonFavorite && /* @__PURE__ */ jsxRuntime.jsx(
5807
+ react.Icon,
5808
+ {
5809
+ icon: harbor.isFavorite ? "fluent:star-24-filled" : "fluent:star-24-regular",
5810
+ color: reactComponents.tokens.colorBrandBackground,
5811
+ className: styles.cursorPointer,
5812
+ onClick: () => onToggleFavorite(harbor)
5813
+ }
5814
+ ),
5815
+ showDivider: index !== harbors.length - 1
5816
+ },
5817
+ harbor.portId || index
5818
+ )) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.emptyState, children: mergedLabels.harborNotFound }) })
5616
5819
  ] })
5617
5820
  ] })
5618
5821
  ] }) })
@@ -8712,12 +8915,34 @@ var ModalListPassenger = ({
8712
8915
  }
8713
8916
  },
8714
8917
  children: [
8715
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Subtitle2, { children: [
8716
- passenger.fullName,
8717
- " (",
8718
- passenger.ageLabel,
8719
- " )"
8720
- ] }) }),
8918
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8919
+ /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Subtitle2, { children: [
8920
+ passenger.fullName,
8921
+ " ",
8922
+ passenger.isAccountOwner && /* @__PURE__ */ jsxRuntime.jsx(
8923
+ reactComponents.Caption2Strong,
8924
+ {
8925
+ style: {
8926
+ backgroundColor: "#F3F9FD",
8927
+ border: `1px solid #A9D3F2`,
8928
+ borderRadius: "1em",
8929
+ display: "inline-block",
8930
+ color: "#0078D4",
8931
+ padding: ".4em .9em"
8932
+ },
8933
+ children: "Pemilik Akun"
8934
+ }
8935
+ )
8936
+ ] }),
8937
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
8938
+ /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Body1, { children: [
8939
+ passenger.ageLabel,
8940
+ " \xB7 ",
8941
+ passenger.identityTypeCode,
8942
+ " ",
8943
+ passenger.identityId
8944
+ ] })
8945
+ ] }),
8721
8946
  /* @__PURE__ */ jsxRuntime.jsx(
8722
8947
  reactComponents.Button,
8723
8948
  {
@@ -8775,8 +9000,10 @@ var DEFAULT_LABELS22 = {
8775
9000
  idTypePlaceholder: "Pilih",
8776
9001
  idNumberLabel: "Nomor Identitas",
8777
9002
  idNumberPlaceholder: "Masukkan Nomor Identitas",
8778
- ageLabel: "Usia",
8779
- agePlaceholder: "Masukkan Usia",
9003
+ age: "Usia",
9004
+ agePlaceholder: "0 Tahun 0 Bulan",
9005
+ yearLabel: "tahun",
9006
+ monthLabel: "bulan",
8780
9007
  dateLabel: "Tanggal Lahir",
8781
9008
  datePlaceholder: "Masukkan Tanggal Lahir",
8782
9009
  cityLabel: "Kota Kabupaten",
@@ -8821,6 +9048,7 @@ var DEFAULT_LABELS22 = {
8821
9048
  minAge: "Usia minimal 1 tahun",
8822
9049
  maxAge: "Usia maksimal 150 tahun",
8823
9050
  requiredDate: "Tanggal lahir harus diisi",
9051
+ birthDateFuture: "Tanggal lahir tidak boleh di masa depan",
8824
9052
  requiredCity: "Kota/Kabupaten harus diisi",
8825
9053
  requiredCountry: "Negara harus diisi",
8826
9054
  requiredPhoneNumber: "Nomor telepon harus diisi",
@@ -8838,8 +9066,10 @@ var DEFAULT_LABELS22 = {
8838
9066
  idTypePlaceholder: "Select",
8839
9067
  idNumberLabel: "Identity Number",
8840
9068
  idNumberPlaceholder: "Enter Identity Number",
8841
- ageLabel: "Age",
8842
- agePlaceholder: "Enter Age",
9069
+ age: "Age",
9070
+ agePlaceholder: "0 Year 0 Month",
9071
+ yearLabel: "year(s)",
9072
+ monthLabel: "month(s)",
8843
9073
  dateLabel: "Date of Birth",
8844
9074
  datePlaceholder: "Enter Date of Birth",
8845
9075
  cityLabel: "City/Regency",
@@ -8884,6 +9114,7 @@ var DEFAULT_LABELS22 = {
8884
9114
  minAge: "Age must be at least 1 year",
8885
9115
  maxAge: "Age must be at most 150 years",
8886
9116
  requiredDate: "Date of birth is required",
9117
+ birthDateFuture: "Date of birth cannot be in the future",
8887
9118
  requiredCity: "City/Regency is required",
8888
9119
  requiredCountry: "Country is required",
8889
9120
  requiredPhoneNumber: "Phone number is required",
@@ -8892,24 +9123,23 @@ var DEFAULT_LABELS22 = {
8892
9123
  }
8893
9124
  }
8894
9125
  };
8895
- var TYPE_OPTIONS = [
8896
- {
8897
- label: "KTP",
8898
- value: "ktp"
8899
- },
8900
- {
8901
- label: "SIM",
8902
- value: "sim"
8903
- },
8904
- {
8905
- label: "Paspor",
8906
- value: "paspor"
8907
- },
8908
- {
8909
- label: "Lainnya",
8910
- value: "lainnya"
9126
+
9127
+ // src/utils/date.ts
9128
+ var calculateAge = (birthDate) => {
9129
+ const today = /* @__PURE__ */ new Date();
9130
+ const birth = new Date(birthDate);
9131
+ if (isNaN(birth.getTime())) return { years: 0, months: 0 };
9132
+ let years = today.getFullYear() - birth.getFullYear();
9133
+ let months = today.getMonth() - birth.getMonth();
9134
+ if (today.getDate() < birth.getDate()) {
9135
+ months--;
8911
9136
  }
8912
- ];
9137
+ if (months < 0) {
9138
+ years--;
9139
+ months += 12;
9140
+ }
9141
+ return { years: Math.max(0, years), months: Math.max(0, months) };
9142
+ };
8913
9143
  var useStyles23 = reactComponents.makeStyles({
8914
9144
  dialogSurface: {
8915
9145
  maxWidth: "600px",
@@ -9075,16 +9305,18 @@ var useStyles23 = reactComponents.makeStyles({
9075
9305
  }
9076
9306
  });
9077
9307
  var ModalPassengerForm = ({
9308
+ defaultValues,
9078
9309
  language = "id",
9079
9310
  labels,
9080
9311
  open,
9312
+ onChange,
9081
9313
  onClose,
9082
- title,
9083
9314
  onSubmit,
9084
- defaultValues,
9085
- isAdultForm = true,
9315
+ title,
9086
9316
  titleOptions,
9317
+ countryOptions,
9087
9318
  cityOptions,
9319
+ idTypeOptions,
9088
9320
  ticketClassOptions,
9089
9321
  onScanComplete
9090
9322
  }) => {
@@ -9095,7 +9327,6 @@ var ModalPassengerForm = ({
9095
9327
  ...labels?.errors
9096
9328
  };
9097
9329
  const displayTitle = title || mergedLabels.title;
9098
- const idTypes = ["KTP", "SIM", "Paspor"];
9099
9330
  const [isModalSelectIdTypeOpen, setIsModalSelectIdTypeOpen] = React.useState(false);
9100
9331
  const [isModalScanOpen, setIsModalScanOpen] = React.useState(false);
9101
9332
  const [scannedIdType, setScannedIdType] = React.useState(null);
@@ -9107,20 +9338,46 @@ var ModalPassengerForm = ({
9107
9338
  const { control, handleSubmit, reset, watch, setValue } = reactHookForm.useForm({
9108
9339
  defaultValues
9109
9340
  });
9110
- const idType = watch("idType");
9111
- const watchPassportCountry = watch("country");
9341
+ watch();
9342
+ const watchIdentityTypeId = watch("identityTypeId");
9343
+ const watchPassportCountryId = watch("countryId");
9344
+ const watchBirthdate = watch("birthdate");
9345
+ React.useEffect(() => {
9346
+ const subscription = watch((value, { name, type }) => {
9347
+ console.log("Changed field:", name);
9348
+ console.log("Change type:", type);
9349
+ onChange(value);
9350
+ });
9351
+ return () => subscription.unsubscribe();
9352
+ }, [watch, onChange]);
9112
9353
  React.useEffect(() => {
9113
9354
  reset(defaultValues);
9114
9355
  }, [defaultValues, reset]);
9115
9356
  React.useEffect(() => {
9116
- if (idType) {
9117
- setValue("idNumber", "");
9118
- }
9119
- }, [idType, watchPassportCountry, setValue]);
9120
- const stopCamera = React.useCallback(() => {
9121
- if (stream) {
9122
- stream.getTracks().forEach((track) => track.stop());
9123
- setStream(null);
9357
+ if (watchIdentityTypeId) {
9358
+ setValue("identityId", "");
9359
+ }
9360
+ }, [watchIdentityTypeId, watchPassportCountryId, setValue]);
9361
+ React.useEffect(() => {
9362
+ if (watchBirthdate) {
9363
+ const { years, months } = calculateAge(watchBirthdate);
9364
+ setValue(
9365
+ "age",
9366
+ `${years} ${mergedLabels.yearLabel} ${months} ${mergedLabels.monthLabel}`
9367
+ );
9368
+ } else {
9369
+ setValue("age", "");
9370
+ }
9371
+ }, [
9372
+ watchBirthdate,
9373
+ setValue,
9374
+ mergedLabels.yearLabel,
9375
+ mergedLabels.monthLabel
9376
+ ]);
9377
+ const stopCamera = React.useCallback(() => {
9378
+ if (stream) {
9379
+ stream.getTracks().forEach((track) => track.stop());
9380
+ setStream(null);
9124
9381
  }
9125
9382
  if (videoRef.current) {
9126
9383
  videoRef.current.pause();
@@ -9152,7 +9409,7 @@ var ModalPassengerForm = ({
9152
9409
  ctx.drawImage(videoRef.current, 0, 0, canvas.width, canvas.height);
9153
9410
  setCapturedImage(canvas.toDataURL("image/jpeg"));
9154
9411
  stopCamera();
9155
- if (scannedIdType === "KTP") {
9412
+ if (scannedIdType === IDENTITY_TYPE.KTP) {
9156
9413
  setScanStatus("reading");
9157
9414
  } else {
9158
9415
  setScanStatus("error");
@@ -9225,14 +9482,14 @@ var ModalPassengerForm = ({
9225
9482
  }
9226
9483
  stopCamera();
9227
9484
  if (name) {
9228
- setValue("name", name, {
9485
+ setValue("fullName", name, {
9229
9486
  shouldValidate: true,
9230
9487
  shouldDirty: true
9231
9488
  });
9232
9489
  }
9233
9490
  if (idNumber && scannedIdType) {
9234
- setValue("idType", scannedIdType.toLowerCase());
9235
- setValue("idNumber", idNumber);
9491
+ setValue("identityTypeId", scannedIdType.toString());
9492
+ setValue("identityId", idNumber);
9236
9493
  }
9237
9494
  onScanComplete?.({ name, idNumber, city });
9238
9495
  setScanStatus("success");
@@ -9314,22 +9571,22 @@ var ModalPassengerForm = ({
9314
9571
  children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Subtitle1, { children: mergedLabels.selectIdTypeTitle })
9315
9572
  }
9316
9573
  ),
9317
- /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { className: styles.content, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.idTypeList, children: idTypes.map((type) => /* @__PURE__ */ jsxRuntime.jsx(
9574
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { className: styles.content, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.idTypeList, children: idTypeOptions.map((type) => /* @__PURE__ */ jsxRuntime.jsx(
9318
9575
  "div",
9319
9576
  {
9320
9577
  className: styles.idTypeItem,
9321
- onClick: () => handleSelectIdType(type),
9578
+ onClick: () => handleSelectIdType(Number(type.value)),
9322
9579
  onKeyDown: (e) => {
9323
9580
  if (e.key === "Enter" || e.key === " ") {
9324
9581
  e.preventDefault();
9325
- handleSelectIdType(type);
9582
+ handleSelectIdType(Number(type.value));
9326
9583
  }
9327
9584
  },
9328
9585
  role: "button",
9329
9586
  tabIndex: 0,
9330
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.idTypeText, children: type })
9587
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: styles.idTypeText, children: type.label })
9331
9588
  },
9332
- type
9589
+ type.value
9333
9590
  )) }) })
9334
9591
  ] }) })
9335
9592
  }
@@ -9596,7 +9853,7 @@ var ModalPassengerForm = ({
9596
9853
  /* @__PURE__ */ jsxRuntime.jsx(
9597
9854
  InputDynamic_default,
9598
9855
  {
9599
- name: "title",
9856
+ name: "titleId",
9600
9857
  control,
9601
9858
  type: "select",
9602
9859
  label: mergedLabels.titleLabel,
@@ -9612,7 +9869,7 @@ var ModalPassengerForm = ({
9612
9869
  /* @__PURE__ */ jsxRuntime.jsx(
9613
9870
  InputDynamic_default,
9614
9871
  {
9615
- name: "name",
9872
+ name: "fullName",
9616
9873
  control,
9617
9874
  type: "text",
9618
9875
  label: mergedLabels.nameLabel,
@@ -9631,22 +9888,23 @@ var ModalPassengerForm = ({
9631
9888
  /* @__PURE__ */ jsxRuntime.jsx(
9632
9889
  InputDynamic_default,
9633
9890
  {
9634
- name: "age",
9891
+ name: "birthdate",
9635
9892
  control,
9636
- type: "number",
9637
- label: mergedLabels.ageLabel,
9638
- placeholder: mergedLabels.agePlaceholder,
9893
+ type: "date",
9894
+ label: mergedLabels.dateLabel,
9895
+ placeholder: mergedLabels.datePlaceholder,
9639
9896
  size: "large",
9640
9897
  required: true,
9641
9898
  validationRules: {
9642
- required: mergedErrors.requiredAge,
9643
- min: {
9644
- value: 1,
9645
- message: mergedErrors.minAge
9646
- },
9647
- max: {
9648
- value: 150,
9649
- message: mergedErrors.maxAge
9899
+ required: mergedErrors.requiredDate,
9900
+ validate: (value) => {
9901
+ const selectedDate = new Date(value);
9902
+ const today = /* @__PURE__ */ new Date();
9903
+ today.setHours(0, 0, 0, 0);
9904
+ if (selectedDate > today) {
9905
+ return mergedErrors.birthDateFuture;
9906
+ }
9907
+ return true;
9650
9908
  }
9651
9909
  }
9652
9910
  }
@@ -9654,110 +9912,107 @@ var ModalPassengerForm = ({
9654
9912
  /* @__PURE__ */ jsxRuntime.jsx(
9655
9913
  InputDynamic_default,
9656
9914
  {
9657
- name: "cityId",
9915
+ name: "age",
9916
+ control,
9917
+ type: "text",
9918
+ disabled: true,
9919
+ label: mergedLabels.age,
9920
+ placeholder: mergedLabels.agePlaceholder,
9921
+ size: "large"
9922
+ }
9923
+ ),
9924
+ /* @__PURE__ */ jsxRuntime.jsx(
9925
+ InputDynamic_default,
9926
+ {
9927
+ name: "identityTypeId",
9658
9928
  control,
9659
9929
  type: "select",
9660
- label: mergedLabels.cityLabel,
9661
- options: cityOptions,
9662
- placeholder: mergedLabels.cityPlaceholder,
9930
+ label: mergedLabels.idTypeLabel,
9931
+ placeholder: mergedLabels.idTypePlaceholder,
9932
+ options: idTypeOptions,
9663
9933
  size: "large",
9664
9934
  required: true,
9665
9935
  validationRules: {
9666
- required: mergedErrors.requiredCity
9936
+ required: mergedErrors.requiredIdType
9667
9937
  }
9668
9938
  }
9669
9939
  ),
9670
- isAdultForm ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9671
- /* @__PURE__ */ jsxRuntime.jsx(
9940
+ watchIdentityTypeId ? watchIdentityTypeId === "lainnya" ? /* @__PURE__ */ jsxRuntime.jsx(
9941
+ InputDynamic_default,
9942
+ {
9943
+ name: "identityId",
9944
+ control,
9945
+ type: "date",
9946
+ label: mergedLabels.idTypeOtherLabel,
9947
+ placeholder: mergedLabels.idTypeOtherPlaceholder,
9948
+ size: "large",
9949
+ required: true,
9950
+ max: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
9951
+ validationRules: {
9952
+ required: mergedErrors.requiredDate
9953
+ }
9954
+ }
9955
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9956
+ watchIdentityTypeId === IDENTITY_TYPE.PSP.toString() && /* @__PURE__ */ jsxRuntime.jsx(
9672
9957
  InputDynamic_default,
9673
9958
  {
9674
- name: "idType",
9959
+ menuPlacement: "top",
9960
+ name: "countryId",
9675
9961
  control,
9962
+ options: countryOptions,
9676
9963
  type: "select",
9677
- label: mergedLabels.idTypeLabel,
9678
- placeholder: mergedLabels.idTypePlaceholder,
9679
- options: TYPE_OPTIONS,
9964
+ label: mergedLabels.countryLabel,
9965
+ placeholder: mergedLabels.countryPlaceholder,
9680
9966
  size: "large",
9681
9967
  required: true,
9682
9968
  validationRules: {
9683
- required: mergedErrors.requiredIdType
9969
+ required: mergedErrors.requiredCountry
9684
9970
  }
9685
9971
  }
9686
9972
  ),
9687
- idType ? idType === "lainnya" ? /* @__PURE__ */ jsxRuntime.jsx(
9973
+ /* @__PURE__ */ jsxRuntime.jsx(
9688
9974
  InputDynamic_default,
9689
9975
  {
9690
- name: "idNumber",
9976
+ name: "identityId",
9691
9977
  control,
9692
- type: "date",
9693
- label: mergedLabels.idTypeOtherLabel,
9694
- placeholder: mergedLabels.idTypeOtherPlaceholder,
9978
+ type: watchIdentityTypeId === IDENTITY_TYPE.KTP.toString() ? "number" : "text",
9979
+ label: mergedLabels.idNumberLabel,
9980
+ placeholder: mergedLabels.idNumberPlaceholder,
9695
9981
  size: "large",
9696
9982
  required: true,
9697
- max: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
9698
9983
  validationRules: {
9699
- required: mergedErrors.requiredDate
9700
- }
9701
- }
9702
- ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9703
- idType === "paspor" && /* @__PURE__ */ jsxRuntime.jsx(
9704
- InputDynamic_default,
9705
- {
9706
- menuPlacement: "top",
9707
- name: "country",
9708
- control,
9709
- type: "country",
9710
- label: mergedLabels.countryLabel,
9711
- placeholder: mergedLabels.countryPlaceholder,
9712
- size: "large",
9713
- required: true,
9714
- validationRules: {
9715
- required: mergedErrors.requiredCountry
9716
- }
9717
- }
9718
- ),
9719
- /* @__PURE__ */ jsxRuntime.jsx(
9720
- InputDynamic_default,
9721
- {
9722
- name: "idNumber",
9723
- control,
9724
- type: idType === "ktp" ? "number" : "text",
9725
- label: mergedLabels.idNumberLabel,
9726
- placeholder: mergedLabels.idNumberPlaceholder,
9727
- size: "large",
9728
- required: true,
9729
- validationRules: {
9730
- required: mergedErrors.requiredIdNumber,
9731
- minLength: {
9732
- value: 6,
9733
- message: mergedErrors.minLengthIdNumber
9734
- }
9984
+ required: mergedErrors.requiredIdNumber,
9985
+ minLength: {
9986
+ value: 6,
9987
+ message: mergedErrors.minLengthIdNumber
9735
9988
  }
9736
9989
  }
9737
- )
9738
- ] }) : null
9739
- ] }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(
9990
+ }
9991
+ )
9992
+ ] }) : null,
9993
+ /* @__PURE__ */ jsxRuntime.jsx(
9740
9994
  InputDynamic_default,
9741
9995
  {
9742
- name: "date",
9996
+ name: "regencyId",
9743
9997
  control,
9744
- type: "date",
9745
- label: mergedLabels.dateLabel,
9746
- placeholder: mergedLabels.datePlaceholder,
9998
+ type: "select",
9999
+ label: mergedLabels.cityLabel,
10000
+ options: cityOptions,
10001
+ placeholder: mergedLabels.cityPlaceholder,
9747
10002
  size: "large",
9748
10003
  required: true,
9749
10004
  validationRules: {
9750
- required: mergedErrors.requiredDate
10005
+ required: mergedErrors.requiredCity
9751
10006
  }
9752
10007
  }
9753
- ) }),
10008
+ ),
9754
10009
  /* @__PURE__ */ jsxRuntime.jsx("br", {}),
9755
10010
  /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Divider, {}),
9756
10011
  /* @__PURE__ */ jsxRuntime.jsx("br", {}),
9757
10012
  /* @__PURE__ */ jsxRuntime.jsx(
9758
10013
  InputDynamic_default,
9759
10014
  {
9760
- name: "ticketClass",
10015
+ name: "passengerClassId",
9761
10016
  control,
9762
10017
  type: "radiobutton",
9763
10018
  label: mergedLabels.ticketClassLabel,
@@ -11093,11 +11348,16 @@ var DEFAULT_LABELS26 = {
11093
11348
  estimationPrefix: "Estimasi",
11094
11349
  totalPriceLabel: "Total Harga",
11095
11350
  nextButton: "Lanjutkan",
11351
+ cancelButton: "Batalkan Pesanan",
11096
11352
  previousButton: "Sebelumnya",
11097
11353
  viewBookingButton: "Lihat Pemesanan",
11098
11354
  changePaymentButton: "Ubah Metode Pembayaran",
11099
11355
  timezoneLabel: "WIB",
11100
- currencySymbol: "IDR"
11356
+ currencySymbol: "IDR",
11357
+ cancelDialogTitle: "Buang perubahan?",
11358
+ cancelDialogBody: "Perubahan belum disimpan dan akan hilang jika Anda melanjutkan.",
11359
+ cancelDialogConfirm: "Buang Perubahan",
11360
+ cancelDialogDismiss: "Batal"
11101
11361
  },
11102
11362
  en: {
11103
11363
  bookingDetails: "Booking Details",
@@ -11105,11 +11365,16 @@ var DEFAULT_LABELS26 = {
11105
11365
  estimationPrefix: "Estimation",
11106
11366
  totalPriceLabel: "Total Price",
11107
11367
  nextButton: "Continue",
11368
+ cancelButton: "Cancel Booking",
11108
11369
  previousButton: "Previous",
11109
11370
  viewBookingButton: "View Booking",
11110
11371
  changePaymentButton: "Change Payment Method",
11111
11372
  timezoneLabel: "WIB",
11112
- currencySymbol: "IDR"
11373
+ currencySymbol: "IDR",
11374
+ cancelDialogTitle: "Discard changes?",
11375
+ cancelDialogBody: "Changes have not been saved and will be lost if you continue.",
11376
+ cancelDialogConfirm: "Discard Changes",
11377
+ cancelDialogDismiss: "Cancel"
11113
11378
  }
11114
11379
  };
11115
11380
  var useStyles27 = reactComponents.makeStyles({
@@ -11221,6 +11486,35 @@ var useStyles27 = reactComponents.makeStyles({
11221
11486
  border: "1px solid " + reactComponents.tokens.colorBrandStroke1,
11222
11487
  color: reactComponents.tokens.colorBrandBackground,
11223
11488
  width: "100%"
11489
+ },
11490
+ cancelButton: {
11491
+ border: "1px solid #D13438",
11492
+ color: "#D13438",
11493
+ width: "100%"
11494
+ },
11495
+ dialogDismissButton: {
11496
+ border: "1px solid " + reactComponents.tokens.colorBrandStroke1,
11497
+ color: reactComponents.tokens.colorBrandBackground,
11498
+ borderRadius: reactComponents.tokens.borderRadiusCircular,
11499
+ marginTop: "1em",
11500
+ marginBottom: ".5em",
11501
+ width: "100%"
11502
+ },
11503
+ dialogConfirmButton: {
11504
+ backgroundColor: "#D13438",
11505
+ color: reactComponents.tokens.colorNeutralForegroundOnBrand,
11506
+ width: "100%",
11507
+ borderRadius: reactComponents.tokens.borderRadiusCircular,
11508
+ border: "none",
11509
+ "&:hover": {
11510
+ backgroundColor: "#b02020"
11511
+ }
11512
+ },
11513
+ dialogActions: {
11514
+ display: "flex",
11515
+ flexDirection: "column",
11516
+ gap: reactComponents.tokens.spacingVerticalS,
11517
+ width: "100%"
11224
11518
  }
11225
11519
  });
11226
11520
  var CardBookingTicket = ({
@@ -11233,6 +11527,7 @@ var CardBookingTicket = ({
11233
11527
  departureDay,
11234
11528
  departureTime,
11235
11529
  departureLocation,
11530
+ disableNextButton,
11236
11531
  arrivalDay,
11237
11532
  arrivalTime,
11238
11533
  arrivalLocation,
@@ -11241,12 +11536,14 @@ var CardBookingTicket = ({
11241
11536
  reservationStep,
11242
11537
  paymentStep,
11243
11538
  onPriceDetailClick,
11539
+ onCancel,
11244
11540
  onNext,
11245
11541
  onPrevious,
11246
11542
  className
11247
11543
  }) => {
11248
11544
  const styles = useStyles27();
11249
11545
  const mergedLabels = { ...DEFAULT_LABELS26[language], ...labels };
11546
+ const [cancelDialogOpen, setCancelDialogOpen] = React.useState(false);
11250
11547
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${styles.container} ${className || ""}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.bookingDetail, children: [
11251
11548
  /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Card, { className: styles.bookingDetailTop, children: [
11252
11549
  /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Subtitle1, { children: mergedLabels.bookingDetails }),
@@ -11330,6 +11627,7 @@ var CardBookingTicket = ({
11330
11627
  reactComponents.Button,
11331
11628
  {
11332
11629
  appearance: "primary",
11630
+ disabled: disableNextButton,
11333
11631
  onClick: onNext,
11334
11632
  shape: "circular",
11335
11633
  size: "large",
@@ -11353,31 +11651,93 @@ var CardBookingTicket = ({
11353
11651
  iconPosition: "before",
11354
11652
  children: mergedLabels.previousButton
11355
11653
  }
11356
- )
11357
- ] }),
11358
- paymentStep === "pay" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.gapButton, children: [
11359
- /* @__PURE__ */ jsxRuntime.jsx(
11360
- reactComponents.Button,
11361
- {
11362
- appearance: "primary",
11363
- shape: "circular",
11364
- size: "large",
11365
- style: { width: "100%" },
11366
- onClick: onNext,
11367
- children: mergedLabels.viewBookingButton
11368
- }
11369
11654
  ),
11370
- /* @__PURE__ */ jsxRuntime.jsx(
11371
- reactComponents.Button,
11372
- {
11373
- appearance: "secondary",
11374
- shape: "circular",
11375
- size: "large",
11376
- className: styles.secondaryButton,
11377
- onClick: onPrevious,
11378
- children: mergedLabels.changePaymentButton
11379
- }
11380
- )
11655
+ paymentStep === "pay" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11656
+ /* @__PURE__ */ jsxRuntime.jsx(
11657
+ reactComponents.Button,
11658
+ {
11659
+ appearance: "primary",
11660
+ disabled: disableNextButton,
11661
+ onClick: onNext,
11662
+ shape: "circular",
11663
+ size: "large",
11664
+ style: { width: "100%" },
11665
+ children: mergedLabels.viewBookingButton
11666
+ }
11667
+ ),
11668
+ /* @__PURE__ */ jsxRuntime.jsx(
11669
+ reactComponents.Button,
11670
+ {
11671
+ appearance: "secondary",
11672
+ shape: "circular",
11673
+ size: "large",
11674
+ className: styles.secondaryButton,
11675
+ onClick: onPrevious,
11676
+ children: mergedLabels.changePaymentButton
11677
+ }
11678
+ )
11679
+ ] }),
11680
+ reservationStep === "manifest" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
11681
+ /* @__PURE__ */ jsxRuntime.jsx(
11682
+ reactComponents.Button,
11683
+ {
11684
+ appearance: "outline",
11685
+ onClick: () => setCancelDialogOpen(true),
11686
+ shape: "circular",
11687
+ size: "large",
11688
+ className: styles.cancelButton,
11689
+ iconPosition: "before",
11690
+ children: mergedLabels.cancelButton
11691
+ }
11692
+ ),
11693
+ /* @__PURE__ */ jsxRuntime.jsx(
11694
+ reactComponents.Dialog,
11695
+ {
11696
+ open: cancelDialogOpen,
11697
+ onOpenChange: (_, data) => setCancelDialogOpen(data.open),
11698
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: "479px", width: "479px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
11699
+ /* @__PURE__ */ jsxRuntime.jsx(
11700
+ reactComponents.DialogTitle,
11701
+ {
11702
+ action: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { action: "close", children: /* @__PURE__ */ jsxRuntime.jsx(
11703
+ reactComponents.Button,
11704
+ {
11705
+ appearance: "subtle",
11706
+ "aria-label": "close",
11707
+ icon: /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "fluent:dismiss-24-regular" })
11708
+ }
11709
+ ) }),
11710
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Subtitle1, { children: mergedLabels.cancelDialogTitle })
11711
+ }
11712
+ ),
11713
+ /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogContent, { children: [
11714
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1, { children: mergedLabels.cancelDialogBody }),
11715
+ /* @__PURE__ */ jsxRuntime.jsx(
11716
+ reactComponents.Button,
11717
+ {
11718
+ className: styles.dialogDismissButton,
11719
+ size: "large",
11720
+ onClick: () => setCancelDialogOpen(false),
11721
+ children: mergedLabels.cancelDialogDismiss
11722
+ }
11723
+ ),
11724
+ /* @__PURE__ */ jsxRuntime.jsx(
11725
+ reactComponents.Button,
11726
+ {
11727
+ className: styles.dialogConfirmButton,
11728
+ size: "large",
11729
+ onClick: () => {
11730
+ setCancelDialogOpen(false);
11731
+ onCancel();
11732
+ },
11733
+ children: mergedLabels.cancelDialogConfirm
11734
+ }
11735
+ )
11736
+ ] })
11737
+ ] }) })
11738
+ }
11739
+ )
11740
+ ] })
11381
11741
  ] })
11382
11742
  ] })
11383
11743
  ] }) });
@@ -13483,14 +13843,16 @@ var DEFAULT_LABELS38 = {
13483
13843
  maxSizeWarning: "Maksimal {maxSize}MB per file dalam format PDF, JPG, JPEG, PNG.",
13484
13844
  sizeLabel: "Ukuran",
13485
13845
  preview: "Pratinjau",
13486
- requiredError: "wajib diisi"
13846
+ requiredError: "wajib diisi",
13847
+ downloadTemplateDocument: "Download Template Dokumen"
13487
13848
  },
13488
13849
  en: {
13489
13850
  placeholder: "Tap to select a file",
13490
13851
  maxSizeWarning: "Maximum {maxSize}MB per file in PDF, JPG, JPEG, PNG format.",
13491
13852
  sizeLabel: "Size",
13492
13853
  preview: "Preview",
13493
- requiredError: "is required"
13854
+ requiredError: "is required",
13855
+ downloadTemplateDocument: "Download Template Document"
13494
13856
  }
13495
13857
  };
13496
13858
  var useStyles40 = reactComponents.makeStyles({
@@ -13630,7 +13992,8 @@ var FileUpload = React__default.default.forwardRef(
13630
13992
  disabled = false,
13631
13993
  language = "id",
13632
13994
  labels: customLabels,
13633
- pdfIcon
13995
+ pdfIcon,
13996
+ downloadTemplateDocument = false
13634
13997
  }, ref) => {
13635
13998
  const mergedLabels = { ...DEFAULT_LABELS38[language], ...customLabels };
13636
13999
  const styles = uploadStyles();
@@ -13715,6 +14078,20 @@ var FileUpload = React__default.default.forwardRef(
13715
14078
  }
13716
14079
  }
13717
14080
  };
14081
+ const handleDownloadFile = (e, file) => {
14082
+ e.stopPropagation();
14083
+ if (!(file instanceof File)) {
14084
+ return;
14085
+ }
14086
+ const fileUrl = URL.createObjectURL(file);
14087
+ const link = document.createElement("a");
14088
+ link.href = fileUrl;
14089
+ link.download = file.name;
14090
+ document.body.appendChild(link);
14091
+ link.click();
14092
+ document.body.removeChild(link);
14093
+ URL.revokeObjectURL(fileUrl);
14094
+ };
13718
14095
  const getContainerStyle = (hasFile, hasError) => {
13719
14096
  if (disabled && hasFile) return styles.containerDisabled;
13720
14097
  if (hasError) return styles.containerError;
@@ -13824,202 +14201,216 @@ var FileUpload = React__default.default.forwardRef(
13824
14201
  }
13825
14202
  );
13826
14203
  }
13827
- return /* @__PURE__ */ jsxRuntime.jsxs(
13828
- reactComponents.Field,
13829
- {
13830
- ref,
13831
- required,
13832
- label: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1, { children: label }),
13833
- className: styles.fieldContainer,
13834
- children: [
13835
- /* @__PURE__ */ jsxRuntime.jsxs(
13836
- reactGridSystem.Container,
13837
- {
13838
- className: getContainerStyle(!!displayFile, !!(error && (value || currentFile)) || !!sizeError),
13839
- onClick: handleClick,
13840
- onDrop: (e) => handleDrop(e, onChange),
13841
- onDragOver: handleDragOver,
13842
- onDragLeave: handleDragLeave,
13843
- fluid: true,
13844
- children: [
13845
- /* @__PURE__ */ jsxRuntime.jsxs(
13846
- reactGridSystem.Row,
13847
- {
13848
- nogutter: true,
13849
- style: { gap: reactComponents.tokens.spacingVerticalL },
13850
- justify: "center",
13851
- align: "center",
13852
- children: [
13853
- /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: "content", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.uploadIcon, children: sizeError ? /* @__PURE__ */ jsxRuntime.jsx(
13854
- react.Icon,
13855
- {
13856
- icon: "fluent:warning-32-regular",
13857
- style: {
13858
- color: reactComponents.tokens.colorStatusWarningBackground3,
13859
- maxWidth: "32px",
13860
- width: "32px",
13861
- maxHeight: "32px",
13862
- height: "32px"
14204
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14205
+ /* @__PURE__ */ jsxRuntime.jsxs(
14206
+ reactComponents.Field,
14207
+ {
14208
+ ref,
14209
+ required,
14210
+ label: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1, { children: label }),
14211
+ className: styles.fieldContainer,
14212
+ children: [
14213
+ /* @__PURE__ */ jsxRuntime.jsxs(
14214
+ reactGridSystem.Container,
14215
+ {
14216
+ className: getContainerStyle(!!displayFile, !!(error && (value || currentFile)) || !!sizeError),
14217
+ onClick: handleClick,
14218
+ onDrop: (e) => handleDrop(e, onChange),
14219
+ onDragOver: handleDragOver,
14220
+ onDragLeave: handleDragLeave,
14221
+ fluid: true,
14222
+ children: [
14223
+ /* @__PURE__ */ jsxRuntime.jsxs(
14224
+ reactGridSystem.Row,
14225
+ {
14226
+ nogutter: true,
14227
+ style: { gap: reactComponents.tokens.spacingVerticalL },
14228
+ justify: "center",
14229
+ align: "center",
14230
+ children: [
14231
+ /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: "content", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.uploadIcon, children: sizeError ? /* @__PURE__ */ jsxRuntime.jsx(
14232
+ react.Icon,
14233
+ {
14234
+ icon: "fluent:warning-32-regular",
14235
+ style: {
14236
+ color: reactComponents.tokens.colorStatusWarningBackground3,
14237
+ maxWidth: "32px",
14238
+ width: "32px",
14239
+ maxHeight: "32px",
14240
+ height: "32px"
14241
+ }
13863
14242
  }
13864
- }
13865
- ) : /* @__PURE__ */ jsxRuntime.jsx(
13866
- react.Icon,
13867
- {
13868
- icon: "fluent:arrow-upload-32-filled",
13869
- style: {
13870
- color: brandColors2[80],
13871
- maxWidth: "32px",
13872
- width: "32px",
13873
- maxHeight: "32px",
13874
- height: "32px"
14243
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
14244
+ react.Icon,
14245
+ {
14246
+ icon: "fluent:arrow-upload-32-filled",
14247
+ style: {
14248
+ color: brandColors2[80],
14249
+ maxWidth: "32px",
14250
+ width: "32px",
14251
+ maxHeight: "32px",
14252
+ height: "32px"
14253
+ }
13875
14254
  }
13876
- }
13877
- ) }) }),
13878
- /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { children: /* @__PURE__ */ jsxRuntime.jsxs(
13879
- reactGridSystem.Row,
13880
- {
13881
- direction: "column",
13882
- nogutter: true,
13883
- style: { rowGap: reactComponents.tokens.spacingVerticalXS },
13884
- children: [
13885
- /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: "content", children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1Strong, { children: placeholderProp || mergedLabels.placeholder }) }),
13886
- displayFile instanceof File ? /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(reactGridSystem.Row, { nogutter: true, style: { gap: reactComponents.tokens.spacingHorizontalS }, children: [
13887
- /* @__PURE__ */ jsxRuntime.jsx(
13888
- reactGridSystem.Col,
13889
- {
13890
- xs: "content",
13891
- style: {
13892
- display: "flex",
13893
- justifyContent: "center",
13894
- alignItems: "center",
13895
- width: "max-content"
13896
- },
13897
- children: isImageFile(displayFile) && previewUrl ? /* @__PURE__ */ jsxRuntime.jsx(
13898
- "img",
13899
- {
13900
- src: previewUrl,
13901
- alt: "preview",
13902
- className: styles.filePreviewImage
13903
- }
13904
- ) : pdfIcon ? /* @__PURE__ */ jsxRuntime.jsx(
13905
- "img",
13906
- {
13907
- src: pdfIcon,
13908
- alt: "PDF Icon",
13909
- width: 32,
13910
- height: 32,
13911
- style: { flexShrink: 0 }
13912
- }
13913
- ) : /* @__PURE__ */ jsxRuntime.jsx(
13914
- react.Icon,
13915
- {
13916
- icon: "fluent:document-pdf-32-regular",
13917
- width: 32,
13918
- height: 32,
13919
- style: { flexShrink: 0, color: brandColors2[80] }
13920
- }
13921
- )
13922
- }
13923
- ),
13924
- /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { children: /* @__PURE__ */ jsxRuntime.jsxs(
13925
- "div",
13926
- {
13927
- style: { display: "flex", flexDirection: "column" },
13928
- children: [
13929
- /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Caption1Strong, { children: getDisplayFileName(displayFile) }),
13930
- /* @__PURE__ */ jsxRuntime.jsxs(
13931
- reactComponents.Caption2,
14255
+ ) }) }),
14256
+ /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { children: /* @__PURE__ */ jsxRuntime.jsxs(
14257
+ reactGridSystem.Row,
14258
+ {
14259
+ direction: "column",
14260
+ nogutter: true,
14261
+ style: { rowGap: reactComponents.tokens.spacingVerticalXS },
14262
+ children: [
14263
+ /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: "content", children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Body1Strong, { children: placeholderProp || mergedLabels.placeholder }) }),
14264
+ displayFile instanceof File ? /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(reactGridSystem.Row, { nogutter: true, style: { gap: reactComponents.tokens.spacingHorizontalS }, children: [
14265
+ /* @__PURE__ */ jsxRuntime.jsx(
14266
+ reactGridSystem.Col,
14267
+ {
14268
+ xs: "content",
14269
+ style: {
14270
+ display: "flex",
14271
+ justifyContent: "center",
14272
+ alignItems: "center",
14273
+ width: "max-content"
14274
+ },
14275
+ children: isImageFile(displayFile) && previewUrl ? /* @__PURE__ */ jsxRuntime.jsx(
14276
+ "img",
13932
14277
  {
13933
- style: { color: reactComponents.tokens.colorNeutralForeground3 },
13934
- children: [
13935
- mergedLabels.sizeLabel,
13936
- ": ",
13937
- formatFileSize(displayFile.size),
13938
- (error || sizeError) && /* @__PURE__ */ jsxRuntime.jsxs(
13939
- "span",
13940
- {
13941
- style: {
13942
- color: reactComponents.tokens.colorStatusWarningForeground1,
13943
- marginLeft: reactComponents.tokens.spacingHorizontalXS
13944
- },
13945
- children: [
13946
- "(",
13947
- sizeError || error?.message,
13948
- ")"
13949
- ]
13950
- }
13951
- )
13952
- ]
14278
+ src: previewUrl,
14279
+ alt: "preview",
14280
+ className: styles.filePreviewImage
13953
14281
  }
13954
- )
13955
- ]
13956
- }
13957
- ) }),
13958
- /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: "content", children: /* @__PURE__ */ jsxRuntime.jsxs(
13959
- "div",
13960
- {
13961
- style: {
13962
- display: "flex",
13963
- gap: reactComponents.tokens.spacingVerticalS,
13964
- justifyContent: "center",
13965
- alignItems: "center",
13966
- width: "max-content",
13967
- height: "100%"
13968
- },
13969
- children: [
13970
- /* @__PURE__ */ jsxRuntime.jsx(
13971
- reactComponents.Button,
14282
+ ) : pdfIcon ? /* @__PURE__ */ jsxRuntime.jsx(
14283
+ "img",
13972
14284
  {
13973
- appearance: "transparent",
13974
- size: "small",
13975
- style: { color: brandColors2[80] },
13976
- onClick: (e) => handlePreview(e, displayFile),
13977
- children: mergedLabels.preview
14285
+ src: pdfIcon,
14286
+ alt: "PDF Icon",
14287
+ width: 32,
14288
+ height: 32,
14289
+ style: { flexShrink: 0 }
13978
14290
  }
13979
- ),
13980
- /* @__PURE__ */ jsxRuntime.jsx(
13981
- reactComponents.Button,
14291
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
14292
+ react.Icon,
13982
14293
  {
13983
- appearance: "transparent",
13984
- size: "small",
13985
- onClick: (e) => handleRemoveFile(e, onChange),
13986
- icon: /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "fluent:dismiss-16-regular" })
14294
+ icon: "fluent:document-pdf-32-regular",
14295
+ width: 32,
14296
+ height: 32,
14297
+ style: { flexShrink: 0, color: brandColors2[80] }
13987
14298
  }
13988
14299
  )
13989
- ]
14300
+ }
14301
+ ),
14302
+ /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { children: /* @__PURE__ */ jsxRuntime.jsxs(
14303
+ "div",
14304
+ {
14305
+ style: { display: "flex", flexDirection: "column" },
14306
+ children: [
14307
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Caption1Strong, { children: getDisplayFileName(displayFile) }),
14308
+ /* @__PURE__ */ jsxRuntime.jsxs(
14309
+ reactComponents.Caption2,
14310
+ {
14311
+ style: { color: reactComponents.tokens.colorNeutralForeground3 },
14312
+ children: [
14313
+ mergedLabels.sizeLabel,
14314
+ ": ",
14315
+ formatFileSize(displayFile.size),
14316
+ (error || sizeError) && /* @__PURE__ */ jsxRuntime.jsxs(
14317
+ "span",
14318
+ {
14319
+ style: {
14320
+ color: reactComponents.tokens.colorStatusWarningForeground1,
14321
+ marginLeft: reactComponents.tokens.spacingHorizontalXS
14322
+ },
14323
+ children: [
14324
+ "(",
14325
+ sizeError || error?.message,
14326
+ ")"
14327
+ ]
14328
+ }
14329
+ )
14330
+ ]
14331
+ }
14332
+ )
14333
+ ]
14334
+ }
14335
+ ) }),
14336
+ /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: "content", children: /* @__PURE__ */ jsxRuntime.jsxs(
14337
+ "div",
14338
+ {
14339
+ style: {
14340
+ display: "flex",
14341
+ gap: reactComponents.tokens.spacingVerticalS,
14342
+ justifyContent: "center",
14343
+ alignItems: "center",
14344
+ width: "max-content",
14345
+ height: "100%"
14346
+ },
14347
+ children: [
14348
+ /* @__PURE__ */ jsxRuntime.jsx(
14349
+ reactComponents.Button,
14350
+ {
14351
+ appearance: "transparent",
14352
+ size: "small",
14353
+ style: { color: brandColors2[80] },
14354
+ onClick: (e) => handlePreview(e, displayFile),
14355
+ children: mergedLabels.preview
14356
+ }
14357
+ ),
14358
+ /* @__PURE__ */ jsxRuntime.jsx(
14359
+ reactComponents.Button,
14360
+ {
14361
+ appearance: "transparent",
14362
+ size: "small",
14363
+ onClick: (e) => handleRemoveFile(e, onChange),
14364
+ icon: /* @__PURE__ */ jsxRuntime.jsx(react.Icon, { icon: "fluent:dismiss-16-regular" })
14365
+ }
14366
+ )
14367
+ ]
14368
+ }
14369
+ ) })
14370
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
14371
+ reactComponents.Caption1,
14372
+ {
14373
+ style: { color: reactComponents.tokens.colorNeutralForeground3 },
14374
+ children: mergedLabels.maxSizeWarning.replace("{maxSize}", String(maxSize))
13990
14375
  }
13991
14376
  ) })
13992
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(reactGridSystem.Col, { xs: 12, children: /* @__PURE__ */ jsxRuntime.jsx(
13993
- reactComponents.Caption1,
13994
- {
13995
- style: { color: reactComponents.tokens.colorNeutralForeground3 },
13996
- children: mergedLabels.maxSizeWarning.replace("{maxSize}", String(maxSize))
13997
- }
13998
- ) })
13999
- ]
14000
- }
14001
- ) })
14002
- ]
14003
- }
14004
- ),
14005
- /* @__PURE__ */ jsxRuntime.jsx(
14006
- "input",
14007
- {
14008
- ref: fileInputRef,
14009
- type: "file",
14010
- accept,
14011
- onChange: (e) => handleFileSelect(e.target.files, onChange),
14012
- className: styles.hiddenInput,
14013
- disabled
14014
- }
14015
- )
14016
- ]
14017
- }
14018
- ),
14019
- /* @__PURE__ */ jsxRuntime.jsx(ModalPreviewImage, { imageUrl: previewUrl, open: isPreviewOpen, onOpenChange: setIsPreviewOpen })
14020
- ]
14021
- }
14022
- );
14377
+ ]
14378
+ }
14379
+ ) })
14380
+ ]
14381
+ }
14382
+ ),
14383
+ /* @__PURE__ */ jsxRuntime.jsx(
14384
+ "input",
14385
+ {
14386
+ ref: fileInputRef,
14387
+ type: "file",
14388
+ accept,
14389
+ onChange: (e) => handleFileSelect(e.target.files, onChange),
14390
+ className: styles.hiddenInput,
14391
+ disabled
14392
+ }
14393
+ )
14394
+ ]
14395
+ }
14396
+ ),
14397
+ /* @__PURE__ */ jsxRuntime.jsx(ModalPreviewImage, { imageUrl: previewUrl, open: isPreviewOpen, onOpenChange: setIsPreviewOpen })
14398
+ ]
14399
+ }
14400
+ ),
14401
+ downloadTemplateDocument && /* @__PURE__ */ jsxRuntime.jsx(
14402
+ reactComponents.Button,
14403
+ {
14404
+ appearance: "transparent",
14405
+ size: "small",
14406
+ icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowDownloadRegular, {}),
14407
+ style: { display: "flex", justifyContent: "end", color: brandColors2[80], width: "100%" },
14408
+ onClick: (e) => handleDownloadFile(e, displayFile),
14409
+ disabled: !(displayFile instanceof File),
14410
+ children: mergedLabels.downloadTemplateDocument
14411
+ }
14412
+ )
14413
+ ] });
14023
14414
  }
14024
14415
  }
14025
14416
  );
@@ -14028,6 +14419,19 @@ var FileUpload = React__default.default.forwardRef(
14028
14419
  FileUpload.displayName = "FileUpload";
14029
14420
  var FileUpload_default = FileUpload;
14030
14421
 
14422
+ // src/utils/color.ts
14423
+ function hexToRgba(hex, alpha = 1) {
14424
+ hex = hex.replace("#", "");
14425
+ if (hex.length === 3) {
14426
+ hex = hex.split("").map((c) => c + c).join("");
14427
+ }
14428
+ const bigint = parseInt(hex, 16);
14429
+ const r = bigint >> 16 & 255;
14430
+ const g = bigint >> 8 & 255;
14431
+ const b = bigint & 255;
14432
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
14433
+ }
14434
+
14031
14435
  // src/components/CardProfileMenu/CardProfileMenu.constants.ts
14032
14436
  var DEFAULT_LABELS39 = {
14033
14437
  id: {},
@@ -14189,8 +14593,10 @@ exports.ModalTypeOfService = ModalTypeOfService;
14189
14593
  exports.PASSENGER_TYPE = PASSENGER_TYPE;
14190
14594
  exports.SortMenu = SortMenu;
14191
14595
  exports.Stepper = Stepper;
14596
+ exports.calculateAge = calculateAge;
14192
14597
  exports.getBadgeConfig = getBadgeConfig;
14193
14598
  exports.getModalPreset = getModalPreset;
14194
14599
  exports.getSortLabel = getSortLabel;
14600
+ exports.hexToRgba = hexToRgba;
14195
14601
  //# sourceMappingURL=index.js.map
14196
14602
  //# sourceMappingURL=index.js.map