JFIFxxC      C  " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr{ gilour

File "price-form.tsx"

Full Path: /home/markqprx/iniasli.pro/client/admin/plans/crupdate-plan-page/price-form.tsx
File size: 6.1 KB
MIME-type: text/plain
Charset: utf-8

import {useFormContext} from 'react-hook-form';
import {Product} from '@common/billing/product';
import React, {Fragment, useMemo, useState} from 'react';
import {useValueLists} from '@common/http/value-lists';
import {FormTextField} from '@common/ui/forms/input-field/text-field/text-field';
import {Trans} from '@common/i18n/trans';
import {Item} from '@common/ui/forms/listbox/item';
import {FormSelect, Select} from '@common/ui/forms/select/select';
import {Price} from '@common/billing/price';
import {BillingPeriodPresets} from '@common/admin/plans/crupdate-plan-page/billing-period-presets';
import {Button} from '@common/ui/buttons/button';
import {message} from '@common/i18n/message';
import {useTrans} from '@common/i18n/use-trans';

interface PriceFormProps {
  index: number;
  onRemovePrice: () => void;
}
export function PriceForm({index, onRemovePrice}: PriceFormProps) {
  const {trans} = useTrans();
  const query = useValueLists(['currencies']);
  const currencies = useMemo(() => {
    return query.data?.currencies ? Object.values(query.data.currencies) : [];
  }, [query.data]);
  const {watch, getValues} = useFormContext<Product>();
  const isNewProduct = !watch('id');
  const isNewPrice = watch(`prices.${index}.id`) == null;
  const subscriberCount = watch(`prices.${index}.subscriptions_count`) || 0;

  // select billing period preset based on price "interval" and "interval_count"
  const [billingPeriodPreset, setBillingPeriodPreset] = useState(() => {
    const interval = getValues(`prices.${index}.interval`);
    const intervalCount = getValues(`prices.${index}.interval_count`);
    const preset = BillingPeriodPresets.find(
      p => p.key === `${interval}${intervalCount}`
    );
    return preset ? preset.key : 'custom';
  });

  const allowPriceChanges = isNewProduct || isNewPrice || !subscriberCount;

  return (
    <Fragment>
      {!allowPriceChanges && (
        <p className="text-muted text-sm max-w-500 mb-20">
          <Trans
            message="This price can't modified or deleted, because it has [one 1 subscriber|other :count subscribers]. You can instead add a new price."
            values={{count: subscriberCount}}
          />
        </p>
      )}

      <FormTextField
        required
        disabled={!allowPriceChanges}
        label={<Trans message="Amount" />}
        type="number"
        min={0.1}
        step={0.01}
        name={`prices.${index}.amount`}
        className="mb-20"
      />
      <FormSelect
        required
        disabled={!allowPriceChanges}
        label={<Trans message="Currency" />}
        name={`prices.${index}.currency`}
        items={currencies}
        showSearchField
        searchPlaceholder={trans(message('Search currencies'))}
        selectionMode="single"
        className="mb-20"
      >
        {item => (
          <Item
            value={item.code}
            key={item.code}
          >{`${item.code}: ${item.name}`}</Item>
        )}
      </FormSelect>
      <BillingPeriodSelect
        disabled={!allowPriceChanges}
        index={index}
        value={billingPeriodPreset}
        onValueChange={setBillingPeriodPreset}
      />
      {billingPeriodPreset === 'custom' && (
        <CustomBillingPeriodField disabled={!allowPriceChanges} index={index} />
      )}
      <div className="text-right">
        <Button
          size="xs"
          variant="outline"
          color="danger"
          disabled={!allowPriceChanges}
          onClick={() => {
            onRemovePrice();
          }}
        >
          <Trans message="Delete price" />
        </Button>
      </div>
    </Fragment>
  );
}

interface BillingPeriodSelectProps {
  index: number;
  value: string;
  onValueChange: (value: string) => void;
  disabled: boolean;
}
function BillingPeriodSelect({
  index,
  value,
  onValueChange,
  disabled,
}: BillingPeriodSelectProps) {
  const {setValue: setFormValue} = useFormContext<Product>();

  return (
    <Select
      label={<Trans message="Billing period" />}
      disabled={disabled}
      className="mb-20"
      selectionMode="single"
      selectedValue={value}
      onSelectionChange={value => {
        onValueChange(value as string);
        if (value === 'custom') {
        } else {
          const preset = BillingPeriodPresets.find(p => p.key === value);
          if (preset) {
            setFormValue(
              `prices.${index}.interval`,
              preset.interval as Price['interval']
            );
            setFormValue(
              `prices.${index}.interval_count`,
              preset.interval_count as number
            );
          }
        }
      }}
    >
      {BillingPeriodPresets.map(preset => (
        <Item key={preset.key} value={preset.key}>
          <Trans {...preset.label} />
        </Item>
      ))}
    </Select>
  );
}

interface CustomBillingPeriodFieldProps {
  index: number;
  disabled: boolean;
}
function CustomBillingPeriodField({
  index,
  disabled,
}: CustomBillingPeriodFieldProps) {
  const {watch} = useFormContext<Product>();
  const interval = watch(`prices.${index}.interval`);
  let maxIntervalCount: number;

  if (interval === 'day') {
    maxIntervalCount = 365;
  } else if (interval === 'week') {
    maxIntervalCount = 52;
  } else {
    maxIntervalCount = 12;
  }

  return (
    <div className="flex border rounded w-min">
      <div className="px-18 flex items-center text-sm">
        <Trans message="Every" />
      </div>
      <FormTextField
        inputShadow="shadow-none"
        inputBorder="border-none"
        className="border-l border-r w-80"
        name={`prices.${index}.interval_count`}
        type="number"
        min={1}
        max={maxIntervalCount}
        disabled={disabled}
        required
      />
      <FormSelect
        inputShadow="shadow-none"
        inputBorder="border-none"
        name={`prices.${index}.interval`}
        selectionMode="single"
        disabled={disabled}
      >
        <Item value="day">
          <Trans message="Days" />
        </Item>
        <Item value="week">
          <Trans message="Weeks" />
        </Item>
        <Item value="month">
          <Trans message="Months" />
        </Item>
      </FormSelect>
    </div>
  );
}