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

File "plans-index-page.tsx"

Full Path: /home/markqprx/iniasli.pro/client/admin/plans/plans-index-page.tsx
File size: 4.86 KB
MIME-type: text/plain
Charset: utf-8

import React, {Fragment} from 'react';
import {DataTablePage} from '../../datatable/page/data-table-page';
import {IconButton} from '../../ui/buttons/icon-button';
import {EditIcon} from '../../icons/material/Edit';
import {FormattedDate} from '../../i18n/formatted-date';
import {ColumnConfig} from '../../datatable/column-config';
import {Trans} from '../../i18n/trans';
import {DataTableEmptyStateMessage} from '../../datatable/page/data-table-emty-state-message';
import softwareEngineerSvg from './../tags/software-engineer.svg';
import {DataTableAddItemButton} from '../../datatable/data-table-add-item-button';
import {Product} from '../../billing/product';
import {NameWithAvatar} from '../../datatable/column-templates/name-with-avatar';
import {Link} from 'react-router-dom';
import {FormattedPrice} from '../../i18n/formatted-price';
import {SyncIcon} from '../../icons/material/Sync';
import {useSyncProducts} from './requests/use-sync-products';
import {Tooltip} from '../../ui/tooltip/tooltip';
import {useDeleteProduct} from './requests/use-delete-product';
import {DeleteIcon} from '../../icons/material/Delete';
import {DialogTrigger} from '../../ui/overlays/dialog/dialog-trigger';
import {ConfirmationDialog} from '../../ui/overlays/dialog/confirmation-dialog';
import {useNavigate} from '../../utils/hooks/use-navigate';
import {PlansIndexPageFilters} from './plans-index-page-filters';

const columnConfig: ColumnConfig<Product>[] = [
  {
    key: 'name',
    allowsSorting: true,
    visibleInMode: 'all',
    header: () => <Trans message="Name" />,
    body: product => {
      const price = product.prices[0];
      return (
        <NameWithAvatar
          label={product.name}
          description={
            product.free ? (
              <Trans message="Free" />
            ) : (
              <FormattedPrice price={price} />
            )
          }
        />
      );
    },
  },
  {
    key: 'created_at',
    allowsSorting: true,
    maxWidth: 'max-w-100',
    header: () => <Trans message="Created" />,
    body: product => <FormattedDate date={product.created_at} />,
  },
  {
    key: 'updated_at',
    allowsSorting: true,
    maxWidth: 'max-w-100',
    header: () => <Trans message="Last updated" />,
    body: product => <FormattedDate date={product.updated_at} />,
  },
  {
    key: 'actions',
    header: () => <Trans message="Actions" />,
    visibleInMode: 'all',
    hideHeader: true,
    align: 'end',
    maxWidth: 'max-w-84',
    body: product => {
      return (
        <Fragment>
          <IconButton
            size="md"
            className="text-muted"
            elementType={Link}
            to={`/admin/plans/${product.id}/edit`}
          >
            <EditIcon />
          </IconButton>
          <DeleteProductButton product={product} />
        </Fragment>
      );
    },
  },
];

export function PlansIndexPage() {
  const navigate = useNavigate();
  return (
    <DataTablePage
      endpoint="billing/products"
      title={<Trans message="Subscription plans" />}
      columns={columnConfig}
      actions={<Actions />}
      enableSelection={false}
      filters={PlansIndexPageFilters}
      onRowAction={item => {
        navigate(`/admin/plans/${item.id}/edit`);
      }}
      emptyStateMessage={
        <DataTableEmptyStateMessage
          image={softwareEngineerSvg}
          title={<Trans message="No plans have been created yet" />}
          filteringTitle={<Trans message="No matching plans" />}
        />
      }
    />
  );
}

interface DeleteProductButtonProps {
  product: Product;
}
function DeleteProductButton({product}: DeleteProductButtonProps) {
  const deleteProduct = useDeleteProduct();
  return (
    <DialogTrigger
      type="modal"
      onClose={confirmed => {
        if (confirmed) {
          deleteProduct.mutate({productId: product.id});
        }
      }}
    >
      <Tooltip label={<Trans message="Delete plan" />}>
        <IconButton
          size="md"
          className="text-muted"
          disabled={deleteProduct.isPending}
        >
          <DeleteIcon />
        </IconButton>
      </Tooltip>
      <ConfirmationDialog
        title={<Trans message="Delete plan" />}
        body={<Trans message="Are you sure you want to delete this plan?" />}
        confirm={<Trans message="Delete" />}
      />
    </DialogTrigger>
  );
}

function Actions() {
  const syncPlans = useSyncProducts();
  return (
    <Fragment>
      <Tooltip label={<Trans message="Sync plans with Stripe & PayPal" />}>
        <IconButton
          color="primary"
          variant="outline"
          size="sm"
          disabled={syncPlans.isPending}
          onClick={() => {
            syncPlans.mutate();
          }}
        >
          <SyncIcon />
        </IconButton>
      </Tooltip>
      <DataTableAddItemButton elementType={Link} to="/admin/plans/new">
        <Trans message="Add new plan" />
      </DataTableAddItemButton>
    </Fragment>
  );
}