DEV Community

Nebula
Nebula

Posted on

frontend2

import { useState, useCallback } from "react";
import { DollarSign, Trash2 } from "lucide-react";
import {
  Container,
  Form,
  InputGroup,
  Label,
  Input,
  Select,
  CreateButton,
  Table,
  StatusBadge,
  Modal,
  ToastComponent,
  containerVariants,
  formVariants
} from './CreateAccountStyles';

function Deposit() {
  const [form, setForm] = useState({
    toAccount: "",
    amount: "",
    description: ""
  });

  const [deposits, setDeposits] = useState([
    {
      srNo: 1,
      transactionId: "TXN123456",
      toAccount: "1234567890",
      amount: 1000.0,
      description: "Initial deposit",
      date: "2022-01-01",
      status: "COMPLETED",
    },
  ]);

  const [isModalOpen, setIsModalOpen] = useState(false);
  const [toasts, setToasts] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [errors, setErrors] = useState({});

  // Available accounts for deposit
  const availableAccounts = [
    { number: "1234567890", name: "Kishan - Savings" },
    { number: "0987654321", name: "Tilak - Current" }
  ];

  // Generate random transaction ID
  const generateTransactionId = () => {
    return "TXN" + Math.floor(100000 + Math.random() * 900000).toString();
  };

  // Validate form
  const validateForm = () => {
    const newErrors = {};

    if (!form.toAccount) {
      newErrors.toAccount = "Please select an account";
    }

    if (!form.amount) {
      newErrors.amount = "Amount is required";
    } else if (parseFloat(form.amount) <= 0) {
      newErrors.amount = "Amount must be greater than 0";
    } else if (parseFloat(form.amount) > 100000) {
      newErrors.amount = "Amount cannot exceed $100,000";
    }

    if (!form.description.trim()) {
      newErrors.description = "Description is required";
    } else if (form.description.trim().length < 3) {
      newErrors.description = "Description must be at least 3 characters";
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  // Handle input changes
  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setForm(prev => ({
      ...prev,
      [name]: value
    }));

    // Clear error when user starts typing
    if (errors[name]) {
      setErrors(prev => ({
        ...prev,
        [name]: ""
      }));
    }
  };

  // Add toast notification
  const addToast = useCallback((type, title, message) => {
    const id = Date.now() + Math.random();
    const newToast = { id, type, title, message };

    setToasts(prev => [...prev, newToast]);

    // Auto remove toast after 5 seconds
    setTimeout(() => {
      removeToast(id);
    }, 5000);
  }, []);

  // Remove toast
  const removeToast = useCallback((id) => {
    setToasts(prev => prev.filter(toast => toast.id !== id));
  }, []);

  // Handle form submission
  const handleSubmit = () => {
    if (!validateForm()) {
      addToast('error', 'Validation Error', 'Please fix the errors and try again');
      return;
    }

    setIsModalOpen(true);
  };

  // Handle deposit confirmation
  const handleConfirmDeposit = async () => {
    setIsModalOpen(false);
    setIsLoading(true);

    try {
      // Simulate API call
      await new Promise(resolve => setTimeout(resolve, 1500));

      const newDeposit = {
        srNo: deposits.length + 1,
        transactionId: generateTransactionId(),
        toAccount: form.toAccount,
        amount: parseFloat(form.amount),
        description: form.description.trim(),
        date: new Date().toISOString().split('T')[0],
        status: "COMPLETED",
      };

      setDeposits(prev => [...prev, newDeposit]);

      // Reset form
      setForm({
        toAccount: "",
        amount: "",
        description: ""
      });

      addToast(
        'success',
        'Deposit Successful!',
        `$${parseFloat(form.amount).toFixed(2)} has been deposited to account ${form.toAccount}`
      );

    } catch (error) {
      addToast('error', 'Deposit Failed', 'Failed to process deposit. Please try again.');
    } finally {
      setIsLoading(false);
    }
  };

  // Clear form
  const clearForm = () => {
    setForm({
      toAccount: "",
      amount: "",
      description: ""
    });
    setErrors({});
  };

  // Format currency
  const formatCurrency = (amount) => {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD'
    }).format(amount);
  };

  // Format date
  const formatDate = (dateString) => {
    return new Date(dateString).toLocaleDateString('en-US', {
      year: 'numeric',
      month: 'short',
      day: 'numeric'
    });
  };

  return (
    <>
      <Container
        variants={containerVariants}
        initial="initial"
        animate="animate"
      >
        <h2>Deposit Funds</h2>

        <Form
          variants={formVariants}
          as="div"
        >
          <InputGroup>
            <Label htmlFor="toAccount">To Account</Label>
            <Select
              id="toAccount"
              name="toAccount"
              value={form.toAccount}
              onChange={handleInputChange}
              required
              style={{
                borderColor: errors.toAccount ? '#ff6b6b' : undefined
              }}
            >
              <option value="">Select Account</option>
              {availableAccounts.map((account) => (
                <option key={account.number} value={account.number}>
                  {account.number} - {account.name}
                </option>
              ))}
            </Select>
            {errors.toAccount && (
              <span style={{ color: '#ff6b6b', fontSize: '14px', marginTop: '4px' }}>
                {errors.toAccount}
              </span>
            )}
          </InputGroup>

          <InputGroup>
            <Label htmlFor="amount">Amount</Label>
            <Input
              id="amount"
              name="amount"
              type="number"
              step="0.01"
              min="0"
              placeholder="Enter amount"
              value={form.amount}
              onChange={handleInputChange}
              required
              style={{
                borderColor: errors.amount ? '#ff6b6b' : undefined
              }}
            />
            {errors.amount && (
              <span style={{ color: '#ff6b6b', fontSize: '14px', marginTop: '4px' }}>
                {errors.amount}
              </span>
            )}
          </InputGroup>

          <InputGroup>
            <Label htmlFor="description">Description</Label>
            <Input
              id="description"
              name="description"
              type="text"
              placeholder="Enter description"
              value={form.description}
              onChange={handleInputChange}
              required
              style={{
                borderColor: errors.description ? '#ff6b6b' : undefined
              }}
            />
            {errors.description && (
              <span style={{ color: '#ff6b6b', fontSize: '14px', marginTop: '4px' }}>
                {errors.description}
              </span>
            )}
          </InputGroup>

          <div style={{ display: 'flex', gap: '12px' }}>
            <CreateButton
              type="button"
              onClick={handleSubmit}
              disabled={isLoading}
              whileHover={{ scale: 1.02 }}
              whileTap={{ scale: 0.98 }}
            >
              <DollarSign size={18} />
              {isLoading ? 'Processing...' : 'Deposit'}
            </CreateButton>

            <CreateButton
              type="button"
              onClick={clearForm}
              disabled={isLoading}
              whileHover={{ scale: 1.02 }}
              whileTap={{ scale: 0.98 }}
              style={{
                background: 'transparent',
                color: '#4a5568',
                border: '2px solid #e2e8f0',
                boxShadow: 'none'
              }}
            >
              <Trash2 size={18} />
              Clear
            </CreateButton>
          </div>
        </Form>

        <h2 style={{ marginTop: '48px', marginBottom: '24px' }}>All Deposits</h2>

        <Table>
          <thead>
            <tr>
              <th>Sr. No</th>
              <th>Transaction ID</th>
              <th>To Account</th>
              <th>Amount</th>
              <th>Description</th>
              <th>Transaction Date</th>
              <th>Status</th>
            </tr>
          </thead>
          <tbody>
            {deposits.map((deposit, index) => (
              <tr key={deposit.transactionId}>
                <td>{deposit.srNo}</td>
                <td>
                  <code style={{ 
                    background: 'rgba(102, 126, 234, 0.1)', 
                    padding: '4px 8px', 
                    borderRadius: '6px',
                    fontSize: '14px',
                    fontWeight: '600'
                  }}>
                    {deposit.transactionId}
                  </code>
                </td>
                <td>
                  <code style={{ 
                    background: 'rgba(102, 126, 234, 0.1)', 
                    padding: '4px 8px', 
                    borderRadius: '6px',
                    fontSize: '14px',
                    fontWeight: '600'
                  }}>
                    {deposit.toAccount}
                  </code>
                </td>
                <td style={{ fontWeight: '600', color: '#38a169' }}>
                  {formatCurrency(deposit.amount)}
                </td>
                <td>{deposit.description}</td>
                <td>{formatDate(deposit.date)}</td>
                <td>
                  <StatusBadge status={deposit.status}>
                    {deposit.status}
                  </StatusBadge>
                </td>
              </tr>
            ))}
          </tbody>
        </Table>
      </Container>

      <Modal
        isOpen={isModalOpen}
        onClose={() => setIsModalOpen(false)}
        title="Confirm Deposit"
        message={`Are you sure you want to deposit ${formatCurrency(parseFloat(form.amount || 0))} to account ${form.toAccount}? This action cannot be undone.`}
        onConfirm={handleConfirmDeposit}
        confirmText="Confirm Deposit"
        cancelText="Cancel"
      />

      <ToastComponent 
        toasts={toasts} 
        removeToast={removeToast} 
      />
    </>
  );
}

export default Deposit;
Enter fullscreen mode Exit fullscreen mode

Top comments (0)