<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nebula</title>
    <description>The latest articles on DEV Community by Nebula (@nebula_3108).</description>
    <link>https://dev.to/nebula_3108</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3291826%2Fab66a1c9-2bd1-4dbc-a815-31fa092741be.png</url>
      <title>DEV Community: Nebula</title>
      <link>https://dev.to/nebula_3108</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nebula_3108"/>
    <language>en</language>
    <item>
      <title>commands</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Tue, 15 Jul 2025 18:12:13 +0000</pubDate>
      <link>https://dev.to/nebula_3108/commands-3cl2</link>
      <guid>https://dev.to/nebula_3108/commands-3cl2</guid>
      <description>&lt;p&gt;npm i axios framer-motion lucide-react react-dom react-hook-form react-hot-toast react-icons react-router react-router-dom recharts styled-components unleash-proxy-client&lt;/p&gt;

&lt;p&gt;npm install @eslint/js @types/react @types/react-dom @vitejs/plugin-react eslint eslint-config-prettier eslint-plugin-prettier eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-refresh globals husky lint-staged prettier vite --save-dev&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @unleash/proxy-client-react unleash-proxy-client

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @vitejs/plugin-react --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Delete node_modules and package-lock.json
rm -rf node_modules package-lock.json

# Clear npm cache
npm cache clean --force

# Reinstall dependencies
npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>presentation</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Mon, 07 Jul 2025 10:25:14 +0000</pubDate>
      <link>https://dev.to/nebula_3108/presentation-53ba</link>
      <guid>https://dev.to/nebula_3108/presentation-53ba</guid>
      <description>&lt;p&gt;Slide 1: Title Slide&lt;br&gt;
Title: Implementing Feature Flag Management with Unleash: A Banking Application Case Study&lt;br&gt;
Subtitle: Showcasing Modern Software Development &amp;amp; Release Strategies&lt;br&gt;
Your Name: [Your Name]&lt;br&gt;
Company/Internship: [Company Name]&lt;br&gt;
Date: [Date]&lt;/p&gt;

&lt;p&gt;Slide 2: Introduction - The Challenge of Modern Software Delivery&lt;br&gt;
In today's fast-paced digital world, delivering new software features quickly and reliably is paramount. However, traditional release processes often come with significant hurdles:&lt;br&gt;
High-Risk Deployments: Releasing new features can be a nerve-wracking event, often leading to "big bang" deployments with a high risk of introducing bugs or breaking existing functionality for all users.&lt;br&gt;
Slow Iteration &amp;amp; Feedback: Getting new features into users' hands quickly for feedback and iteration is challenging when every change requires a full deployment cycle.&lt;br&gt;
Limited Experimentation: A/B testing or rolling out features to specific user groups for targeted feedback is complex, if not impossible, without flexible control mechanisms.&lt;br&gt;
Difficulty in Personalization: Tailoring user experiences based on individual preferences or demographics becomes cumbersome when features are hard-coded into the application.&lt;br&gt;
This project, demonstrated through a banking application, addresses these very challenges. We explored how to achieve safer releases, enable testing directly in production environments, and personalize user experiences dynamically – all without the complexities of continuous redeployments.&lt;br&gt;
The core problem: Traditional software release cycles are often slow, inherently risky, and severely limit our ability to experiment and adapt.&lt;/p&gt;

&lt;p&gt;Slide 3: What is Feature Flagging?&lt;br&gt;
At its core, Feature Flagging (also known as Feature Toggling or Feature Flipping) is a powerful software development technique that allows you to turn functionality on and off without deploying new code.&lt;br&gt;
Think of it like the light switches in your house or circuit breakers in an electrical panel. Just as you can control individual lights or sections of your home's power independently, feature flags give you granular control over specific features within your application.&lt;br&gt;
Why is this so transformative? Feature flags provide several high-level benefits that address the challenges we just discussed:&lt;br&gt;
Decoupling Deployment from Release: You can deploy code containing new features at any time, but only release those features to users when you're ready, by simply toggling a flag.&lt;br&gt;
Reducing Risk: If a new feature causes issues, you can instantly turn it off for all or a subset of users, minimizing impact without needing an emergency hotfix deployment.&lt;br&gt;
Enabling A/B Testing &amp;amp; Experimentation: Easily test different versions of a feature with different user groups to gather data and make informed decisions.&lt;br&gt;
Personalization: Deliver tailored experiences to specific user segments based on their attributes or preferences.&lt;br&gt;
Faster Iteration &amp;amp; Feedback: Get new features into production quickly and iterate based on real-world usage and feedback.&lt;br&gt;
Visuals: Imagine a simple diagram showing a user request entering your application. Instead of a direct path to a feature, there's a "decision point" (the feature flag) that directs the request to either the "new feature" path or the "old/disabled" path.&lt;/p&gt;

&lt;p&gt;Slide 4: Introducing Unleash - Your Feature Flag Management Tool&lt;br&gt;
To effectively manage our feature flags, we chose Unleash, a leading open-source and enterprise-ready feature flag management system.&lt;br&gt;
Why Unleash?&lt;br&gt;
We selected Unleash for several compelling reasons:&lt;br&gt;
• Centralized Control: It provides a single, intuitive dashboard to manage all feature flags across different applications and environments.&lt;br&gt;
• Powerful Strategies: Unleash offers a rich set of built-in strategies and the flexibility to create custom ones, allowing for highly granular control over who sees which feature.&lt;br&gt;
• Extensive SDK Support: With Software Development Kits (SDKs) available for numerous programming languages (like React and Java, which we used), integration into existing applications is straightforward.&lt;br&gt;
• User-Friendly Interface: Its intuitive UI makes it easy for developers, product managers, and even non-technical stakeholders to understand and manage feature rollouts.&lt;br&gt;
Key Components of Unleash:&lt;br&gt;
Understanding Unleash involves grasping its core building blocks:&lt;br&gt;
• Feature Flags: These are the fundamental "on/off" toggles for specific functionalities in your application. Each flag represents a decision point in your code.&lt;br&gt;
• Strategies: These are the rules that determine if a feature flag is "on" for a given user or environment. Examples include percentage rollouts, user ID targeting, or IP-based access.&lt;br&gt;
• Context: This is the dynamic data about the user or the environment that Unleash uses to evaluate strategies. Common context fields include userId, sessionId, remoteAddress (IP), and custom fields like region.&lt;br&gt;
Visuals: A compelling screenshot of the Unleash UI, perhaps showing the dashboard with a list of flags, or a detailed view of a single flag's configuration, would be highly effective here.&lt;/p&gt;

&lt;p&gt;Slide 5: Unleash Integration in Our Banking Application&lt;br&gt;
Now, let's look at how Unleash was seamlessly integrated into our banking application to enable dynamic feature management.&lt;br&gt;
Our Integration Architecture:&lt;br&gt;
The setup involved a straightforward connection between our application components and the hosted Unleash instance:&lt;br&gt;
Frontend (React.js): This is where our user interface resides.&lt;br&gt;
Backend (Spring Boot): This handles our business logic, data persistence, and API endpoints.&lt;br&gt;
Unleash Instance: Our centralized server for managing all feature flags.&lt;br&gt;
(Visuals: A simple block diagram showing arrows from Frontend to Backend, and both Frontend and Backend communicating with the Unleash Instance)&lt;br&gt;
SDKs Utilized for Integration:&lt;br&gt;
To facilitate communication with Unleash, we leveraged its official Software Development Kits:&lt;br&gt;
React Client SDK: This SDK was integrated directly into our React frontend. It's ideal for controlling UI elements, enabling or disabling client-side features, and performing A/B tests that are primarily visual.&lt;br&gt;
Java Server SDK: Our Spring Boot backend utilized the Java Server SDK. This allowed us to control backend logic, API access, and more complex business rules based on feature flag states, ensuring robust and secure feature management.&lt;br&gt;
How it Works:&lt;br&gt;
The integration allows our application to dynamically adapt its behavior. When a user interacts with the application, or a specific piece of logic is invoked:&lt;br&gt;
Our application (either frontend or backend, depending on the feature) queries the Unleash instance through the respective SDK.&lt;br&gt;
Unleash evaluates the status of the requested feature flag based on its configured strategies and the provided user/environment context.&lt;br&gt;
Unleash then returns the flag's status (enabled or disabled) to our application.&lt;br&gt;
Based on this status, our application renders the appropriate UI, executes specific backend logic, or displays relevant messages.&lt;br&gt;
This dynamic evaluation ensures that features are delivered precisely when and to whom they are intended, without requiring any code redeployments for simple toggles&lt;/p&gt;

&lt;p&gt;Slide 6: Core Feature Flag Use Cases - Risk Mitigation &amp;amp; UI Control&lt;br&gt;
Now that we understand how Unleash is integrated, let's dive into some fundamental feature flag use cases that directly address common software delivery challenges.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Kill Switch: The Filtering Feature
Concept: This is perhaps the most critical and straightforward use of feature flags. A "kill switch" allows you to instantly disable a problematic or underperforming feature in production without requiring any code redeployment. It's your immediate safety net.
Unleash Implementation: For this, we used a simple on/off toggle for the feature flag, typically with a 100% rollout. When the flag is "off," the feature is disabled for everyone.
Banking App Scenario: In our banking application, the filtering functionality on the transactions page serves as a perfect example. If a bug were discovered in the filtering logic, or if it caused performance issues, we could simply turn off the associated Unleash flag.
User Experience: When the flag is turned off, the filtering options disappear, and a clear message is displayed to the user, indicating that the feature has been temporarily taken down.
Demo Cue: "Let's see how we can instantly disable the transaction filtering feature in our banking application using Unleash." (Prepare to show turning off the flag in Unleash, then refreshing the app to demonstrate the filtering options disappearing and the message appearing.)&lt;/li&gt;
&lt;li&gt;A/B Testing / UI Toggle: The New UI Feature
Concept: Feature flags are invaluable for A/B testing and dynamically controlling user interface (UI) elements. This allows you to roll out new UI experiences or test different visual layouts with specific user segments, gathering feedback and data before a full release.
Unleash Implementation: This also involves a simple on/off toggle. When the flag is "on," the new UI is displayed; when "off," the default UI is shown.
Banking App Scenario: By default, the transactions on our banking application's transactions page are displayed in a traditional tabulated way. We implemented a "New UI Feature" flag.
User Experience: If we toggle this flag "on" from the Unleash instance, the entire UI of those transactions changes from the tabular format to a more modern, card-based layout. Toggling it "off" reverts it to the original tabular view.
Demo Cue: "Now, let's explore how we can switch between different UI experiences for our transaction list, demonstrating a dynamic UI toggle." (Prepare to show toggling the flag in Unleash, then refreshing the app to show the UI changing between tabular and card formats.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Slide 7: Advanced Strategies - Gradual Rollouts &amp;amp; Experimentation&lt;br&gt;
Beyond simple on/off toggles, Unleash truly shines with its advanced strategies, allowing for sophisticated control over feature delivery. These enable controlled experimentation and phased rollouts, minimizing risk while maximizing learning.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Gradual Rollout Simulator
• Concept: This strategy is fundamental for safe and controlled feature releases. Instead of deploying a new feature to all users at once, a gradual rollout allows you to release it to a small percentage of your user base first, and then progressively increase that percentage over time. This approach is ideal for monitoring performance, identifying unforeseen issues early, and gathering targeted feedback before a wider release.
• Unleash Implementation: Unleash provides a built-in "Gradual Rollout" (or "Percentage Rollout") strategy. You simply define the percentage of users who should see the feature, and Unleash handles the distribution based on a consistent hashing mechanism.
• Banking App Scenario: To demonstrate this, I've developed a "Gradual Rollout Simulator" page within the banking application. This simulator generates a specified number of dummy users. For each dummy user, it sends a request to Unleash to check the status of a particular feature flag. Based on the percentage set in Unleash, a corresponding number of dummy users will receive the flag as "enabled," showcasing the rollout in action.
• Demo Cue: "Unleash allows for controlled, gradual rollouts, giving us immense flexibility. I've built a simulator to demonstrate this in real-time." (Prepare to show the simulator, explain how it creates dummy users and queries Unleash, and then demonstrate how changing the rollout percentage in the Unleash UI directly impacts the number of 'enabled' users in the simulator results.)&lt;/li&gt;
&lt;li&gt;A/B / Multivariate Test Simulator
• Concept: When you have multiple variations of a feature or UI element and want to determine which performs best, A/B testing (or Multivariate Testing for more than two variations) is crucial. This strategy allows you to simultaneously expose different user groups to distinct versions of a feature and measure their impact.
• Unleash Implementation: Unleash supports this through its "Variants" feature. You can define multiple variants for a single feature flag (e.g., variantA, variantB, variantC) and assign a distribution percentage to each. Unleash ensures that users are consistently assigned to a specific variant.
• Banking App Scenario: I've created a flag with three distinct variants, each distributed equally (approximately 33.33%). The A/B / Multivariate Test Simulator creates a certain number of dummy users. For each user, it queries Unleash for the flag's status and the assigned variant. The simulator then visually demonstrates that, statistically, roughly one-third of the users receive each particular variant, proving the equitable distribution.
• Demo Cue: "For more complex experiments and data-driven decisions, Unleash supports A/B and multivariate testing with its powerful variant management." (Prepare to show the simulator, explain the concept of variants, and demonstrate the distribution of different variants among the dummy users, highlighting how the percentages align with the Unleash configuration.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Slide 8: Advanced Strategies - Context-Based Targeting&lt;br&gt;
Unleash's power extends to targeting specific user segments based on various contextual data. This allows for highly precise control over who sees which feature, enabling tailored experiences and controlled rollouts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IP-Based Strategy &amp;amp; Simulator
• Concept: This strategy enables features only for users originating from specific IP addresses or defined IP ranges. It's incredibly useful for internal testing, providing early access to beta users, or delivering features relevant to a particular network.
• Unleash Implementation: Unleash provides a dedicated "IP Strategy" where you can specify individual IP addresses or CIDR ranges.
• Banking App Scenario: To illustrate this, I've built an IP Strategy Simulator. This tool allows us to input a range or discrete IP addresses and then test the flag status for each. Only those IP addresses falling within the range configured in Unleash will receive the flag as "enabled."
• Demo Cue: "Beyond percentages, Unleash allows targeting based on specific user attributes, like IP addresses. Let's see how our IP simulator demonstrates this." (Prepare to show the IP strategy configuration in Unleash, then use the simulator to demonstrate how only allowed IPs receive the enabled flag, while others do not.)&lt;/li&gt;
&lt;li&gt;Geo-Targeted Feature Flag (with Custom Context)
• Concept: For features that are relevant to users in specific geographical locations, Unleash allows for geo-targeting. This ensures that a feature is only accessible to users within a defined region, country, or city.
• Unleash Implementation: This is achieved by combining the IP strategy with a custom context field, such as region. We define the region as a context property, and then add a constraint to the flag that checks this region value.
• Banking App Scenario: We've created a flag that is available only to users whose region context matches a specific geographical location. This demonstrates how you can provide region-specific features or comply with local regulations.
• Demo Cue: "Combining strategies with custom contexts, we can even target users by their geographical region. Our flag, for instance, is configured to be available only to users in a specific region." (Explain the region custom context and show the constraint in Unleash. You can verbally explain how the simulator or a live user from that region would experience the enabled flag, while others wouldn't.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Slide 9: Advanced Strategies - User Targeting &amp;amp; Permissions&lt;br&gt;
Unleash excels at managing access to features based on individual users or specific user groups. This is crucial for premium features, internal testing, or controlled rollouts to a select audience.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Permission Flag (User Targeting)
• Concept: This strategy allows you to grant access to specific features, modules, or premium content only to a predefined set of users. It's perfect for enabling premium subscriptions, beta testing with a select group, or providing internal tools.
• Unleash Implementation: We achieve this by adding a constraint based on the userId context field. You can specify a list of user IDs who should have access to the feature.
• Banking App Scenario: In our banking application, the "Analytics &amp;amp; Insights" page is a premium feature. Access to this page is controlled by an Unleash flag with a userId constraint. Only users whose IDs are explicitly listed in Unleash will be able to view this page.
• Demo Cue: "Finally, Unleash is excellent for managing user permissions and premium features. Let's see how it controls access to our Analytics page." (Prepare to log in as a user without the specified User ID and show the Analytics page is hidden or inaccessible. Then, log in as a user with the specified User ID in Unleash and show full access to the Analytics page.)&lt;/li&gt;
&lt;li&gt;Money Transfer Feature (Backend-Driven Kill Switch)
• Concept: While we've seen UI-driven kill switches, it's equally vital to control critical backend functionalities. This demonstrates how a feature flag can disable core business logic directly on the server side, providing a robust safety mechanism.
• Unleash Implementation: This feature is integrated with the Java Server SDK. The backend application queries Unleash for the flag status before processing a money transfer request. It's a simple on/off toggle for critical functionality.
• Banking App Scenario: We've implemented a kill switch for the money transfer feature. If this flag is disabled from Unleash, any attempt by a user to perform a money transfer will result in a response from the backend indicating that the feature is currently disabled.
• Demo Cue: "This isn't just for the UI; backend features can also be controlled. For instance, the money transfer functionality." (Prepare to attempt a money transfer while the flag is disabled, show the backend response indicating it's disabled, and then show the flag's status in the Unleash UI.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Slide 10: Key Takeaways &amp;amp; Impact of Unleash&lt;br&gt;
Having explored Unleash's capabilities, let's summarize the profound impact it has on modern software development and delivery:&lt;br&gt;
Empowered Development Teams: Unleash enables faster iteration cycles, significantly reduces deployment risk, and fosters a culture of continuous experimentation.&lt;br&gt;
Improved User Experience: Through A/B testing and personalized features, Unleash allows for tailored experiences, leading to higher user satisfaction. It also facilitates quick bug fixes and rollbacks, minimizing user disruption.&lt;br&gt;
Enhanced Business Agility: Businesses can respond rapidly to market changes, launch new initiatives with confidence, and instantly roll back features if needed, maintaining competitive edge.&lt;br&gt;
Decoupling Deployment from Release: This is a fundamental shift. Code can be deployed to production at any time, while the actual release of features is controlled independently via feature flags, reducing deployment stress.&lt;br&gt;
Confidence in Production: Unleash allows for safely testing new features with a small subset of users in a live environment, building confidence before a full rollout.&lt;br&gt;
Visuals: Consider using simple, impactful icons representing concepts like speed, safety, and flexibility to visually reinforce these key takeaways.&lt;/p&gt;

&lt;p&gt;Slide 11: Conclusion &amp;amp; Q&amp;amp;A&lt;br&gt;
Goal: Wrap up the presentation and invite questions.&lt;br&gt;
Content:&lt;br&gt;
Recap: Briefly reiterate how Unleash transforms software delivery.&lt;br&gt;
Call to Action (Optional): Encourage adoption of feature flagging practices.&lt;br&gt;
Thank You!&lt;br&gt;
Questions?&lt;br&gt;
Contact Information (Optional): [Your Email/LinkedIn]&lt;/p&gt;

</description>
    </item>
    <item>
      <title>analytics2</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Fri, 04 Jul 2025 06:13:58 +0000</pubDate>
      <link>https://dev.to/nebula_3108/analytics2-1l6e</link>
      <guid>https://dev.to/nebula_3108/analytics2-1l6e</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect, useMemo, useCallback } from 'react';
import styled from 'styled-components';
import { motion, AnimatePresence } from 'framer-motion';
import { Search, Filter, X, RefreshCw, AlertCircle, TrendingUp, TrendingDown, ArrowUpDown } from 'lucide-react';
import {
  ResponsiveContainer,
  BarChart,
  Bar,
  LineChart,
  Line,
  PieChart,
  Pie,
  Cell,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
} from 'recharts';
import { toast } from 'react-hot-toast'; // Assuming you use react-hot-toast

// Assume 'api' is configured and imported from your api setup
// import api from '../api';
// Assume 'user' object is available from a context or props
// const { user } = useAuth();

// Styled Components (as provided in the prompt)
const colors = {
  primary: '#667eea',
  primaryDark: '#5a67d8',
  secondary: '#764ba2',
  success: '#48bb78',
  error: '#ff6b6b',
  warning: '#f6ad55',
  text: '#1a202c',
  textSecondary: '#4a5568',
  textMuted: '#a0aec0',
  background: 'rgba(255, 255, 255, 0.95)',
  border: 'rgba(102, 126, 234, 0.2)',
  borderHover: '#667eea',
  glass: 'rgba(255, 255, 255, 0.95)',
  glassLight: 'rgba(255, 255, 255, 0.8)',
  shadow: 'rgba(0, 0, 0, 0.1)',
  shadowHover: 'rgba(102, 126, 234, 0.1)'
};

const gradients = {
  primary: `linear-gradient(135deg, ${colors.primary}, ${colors.secondary})`,
};

const spacing = {
  sm: '8px',
  md: '12px',
  lg: '16px',
  xl: '20px',
  xxl: '24px',
  xxxl: '32px'
};

const Container = styled(motion.div)`
  padding: ${spacing.xxxl};
  max-width: 1600px;
  margin: 0 auto;
  h2 {
    font-size: 32px;
    font-weight: 800;
    color: ${colors.text};
    margin-bottom: ${spacing.xxxl};
    background: ${gradients.primary};
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    text-align: center;
  }
  @media (max-width: 768px) { padding: ${spacing.xl}; }
`;

const FilterSection = styled(motion.div)`
  background: ${colors.glass};
  backdrop-filter: blur(20px);
  border-radius: 20px;
  padding: ${spacing.xxl};
  margin-bottom: ${spacing.xxxl};
  box-shadow: 0 8px 32px ${colors.shadow};
  border: 1px solid rgba(255, 255, 255, 0.2);
`;

const SearchContainer = styled.div`
  position: relative;
  margin-bottom: ${spacing.xl};
  svg {
    position: absolute;
    left: ${spacing.lg};
    top: 50%;
    transform: translateY(-50%);
    color: ${colors.textMuted};
  }
`;

const SearchInput = styled.input`
  width: 100%;
  padding: ${spacing.lg} ${spacing.lg} ${spacing.lg} 48px;
  border: 2px solid ${colors.border};
  border-radius: 12px;
  font-size: 16px;
  background: ${colors.glassLight};
  &amp;amp;:focus {
    outline: none;
    border-color: ${colors.borderHover};
    box-shadow: 0 0 0 4px ${colors.shadowHover};
  }
`;

const FiltersGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: ${spacing.lg};
  margin-bottom: ${spacing.xl};
`;

const FilterSelect = styled.select`
  padding: ${spacing.lg};
  border: 2px solid ${colors.border};
  border-radius: 12px;
  font-size: 16px;
  background: ${colors.glassLight};
  cursor: pointer;
  &amp;amp;:focus {
    outline: none;
    border-color: ${colors.borderHover};
    box-shadow: 0 0 0 4px ${colors.shadowHover};
  }
`;

const DateInput = styled.input`
    padding: ${spacing.lg};
    border: 2px solid ${colors.border};
    border-radius: 12px;
    font-size: 16px;
    background: ${colors.glassLight};
    color: ${colors.textSecondary};
    cursor: pointer;
    &amp;amp;:focus {
        outline: none;
        border-color: ${colors.borderHover};
        box-shadow: 0 0 0 4px ${colors.shadowHover};
    }
`;

const ButtonGroup = styled.div`
  display: flex;
  gap: ${spacing.md};
  justify-content: flex-end;
  margin-top: ${spacing.xl};
`;

const Button = styled(motion.button)`
  display: flex;
  align-items: center;
  gap: ${spacing.sm};
  padding: ${spacing.md} ${spacing.xl};
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  border: 2px solid transparent;
  transition: all 0.3s ease;

  ${props =&amp;gt; props.variant === 'primary' ? `
    background: ${gradients.primary};
    color: white;
    box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);
    &amp;amp;:hover:not(:disabled) {
      transform: translateY(-2px);
      box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5);
    }
  ` : `
    background: transparent;
    color: ${colors.textSecondary};
    border-color: #e2e8f0;
    &amp;amp;:hover:not(:disabled) {
      background: #f7fafc;
      border-color: #cbd5e0;
    }
  `}

  &amp;amp;:disabled { opacity: 0.6; cursor: not-allowed; }
`;

const AnalyticsGrid = styled(motion.div)`
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
    gap: ${spacing.xxl};
    margin-bottom: ${spacing.xxxl};
`;

const ChartContainer = styled.div`
    background: ${colors.glass};
    backdrop-filter: blur(20px);
    border-radius: 20px;
    padding: ${spacing.xl};
    box-shadow: 0 8px 32px ${colors.shadow};
    border: 1px solid rgba(255, 255, 255, 0.2);
    h3 {
        font-size: 18px;
        font-weight: 600;
        color: ${colors.text};
        margin-bottom: ${spacing.xl};
    }
`;

const TableContainer = styled.div`
  background: ${colors.glass};
  backdrop-filter: blur(20px);
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 8px 32px ${colors.shadow};
`;

const Table = styled.table`
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  th {
    background: ${gradients.primary};
    color: white;
    padding: ${spacing.lg};
    text-align: left;
    font-weight: 600;
    font-size: 14px;
    cursor: pointer;
    white-space: nowrap;
    &amp;amp;:hover { background: ${colors.primaryDark}; }
  }
  td {
    padding: ${spacing.lg};
    color: ${colors.textSecondary};
    border-bottom: 1px solid rgba(226, 232, 240, 0.8);
  }
  tr:last-child td { border-bottom: none; }
  tr:hover { background: ${colors.shadowHover}; }
`;

const StatusBadge = styled.span`
  padding: 6px ${spacing.md};
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  ${({ status }) =&amp;gt; {
    switch (status) {
      case 'SUCCESS': return `background-color: ${colors.success}20; color: ${colors.success};`;
      case 'PENDING': return `background-color: ${colors.warning}20; color: ${colors.warning};`;
      case 'FAILED': return `background-color: ${colors.error}20; color: ${colors.error};`;
      default: return `background-color: ${colors.textMuted}20; color: ${colors.textMuted};`;
    }
  }}
`;

const TypeBadge = styled.span`
  padding: 6px ${spacing.md};
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  ${({ type }) =&amp;gt; {
    switch (type) {
      case 'DEPOSIT': return `background-color: ${colors.success}20; color: ${colors.success};`;
      case 'WITHDRAW': return `background-color: ${colors.error}20; color: ${colors.error};`;
      case 'TRANSFER': return `background-color: ${colors.primary}20; color: ${colors.primary};`;
      default: return `background-color: ${colors.textMuted}20; color: ${colors.textMuted};`;
    }
  }}
`;

const LoadingSpinner = styled(motion.div)`
  display: flex; justify-content: center; padding: 64px;
  svg { animation: spin 1s linear infinite; }
  @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
`;

const ErrorMessage = styled(motion.div)`
  display: flex; flex-direction: column; align-items: center; gap: ${spacing.lg};
  padding: 64px; text-align: center; color: ${colors.error};
`;

const EmptyState = styled(motion.div)`
  display: flex; flex-direction: column; align-items: center; gap: ${spacing.lg};
  padding: 64px; text-align: center; color: ${colors.textMuted};
`;


// Mock user for demonstration. In a real app, this would come from an auth context.
const user = { id: 1, name: 'Kishan' };

// Mock API for demonstration
const api = {
    get: async (url) =&amp;gt; {
        console.log(`Fetching ${url}...`);
        await new Promise(res =&amp;gt; setTimeout(res, 500)); // Simulate network delay
        if (url.startsWith('/accounts/user/')) {
            return { data: { message: "Accounts retrieved successfully", data: [ { id: 1, accountNumber: "98765432155", accountType: "SAVINGS", balance: 1450.01, userDTO: { id: 1, name: "kishan" } }, { id: 52, accountNumber: "98765432188", accountType: "SALARY", balance: 25000.00, userDTO: { id: 1, name: "kishan" } } ] }};
        }
        if (url.startsWith('/transactions/user/')) {
            return { data: { message: "Transactions fetched successfully", data: [ { id: 1, fromAccount: { id: 52, accountNumber: "98765432188" }, toAccount: { id: 1, accountNumber: "98765432155" }, type: "TRANSFER", amount: 500.00, description: "Monthly savings", timestamp: "2025-07-01T10:00:00Z", status: "SUCCESS" }, { id: 2, toAccount: { id: 52, accountNumber: "98765432188" }, type: "DEPOSIT", amount: 25000.00, description: "July Salary", timestamp: "2025-07-01T09:00:00Z", status: "SUCCESS" }, { id: 3, fromAccount: { id: 1, accountNumber: "98765432155" }, type: "WITHDRAW", amount: 150.00, description: "Grocery Shopping", timestamp: "2025-07-02T18:30:00Z", status: "SUCCESS" }, { id: 4, fromAccount: { id: 1, accountNumber: "98765432155" }, type: "WITHDRAW", amount: 80.00, description: "Dinner with friends", timestamp: "2025-06-15T20:00:00Z", status: "SUCCESS" }, { id: 5, toAccount: { id: 1, accountNumber: "98765432155" }, type: "DEPOSIT", amount: 1000.00, description: "Freelance Payment", timestamp: "2025-06-20T14:00:00Z", status: "SUCCESS" } ] }};
        }
        return { data: { data: [] } };
    }
};

const TransactionAnalytics = () =&amp;gt; {
  const [transactions, setTransactions] = useState([]);
  const [userAccounts, setUserAccounts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [accountsLoading, setAccountsLoading] = useState(true);
  const [error, setError] = useState(null);

  const [filters, setFilters] = useState({
    searchTerm: '',
    account: 'all',
    type: 'all',
    startDate: '',
    endDate: '',
  });

  const [sortConfig, setSortConfig] = useState({ key: 'timestamp', direction: 'desc' });

  // --- DATA FETCHING ---
  const fetchUserAccounts = useCallback(async () =&amp;gt; {
    if (!user?.id) return;
    try {
      setAccountsLoading(true);
      const response = await api.get(`/accounts/user/${user.id}`);
      setUserAccounts(response.data.data);
    } catch (err) {
      console.error('Error fetching user accounts:', err);
      toast.error('Failed to load user accounts');
    } finally {
      setAccountsLoading(false);
    }
  }, []); // user.id is static in this example

  const fetchTransactions = useCallback(async () =&amp;gt; {
    if (!user?.id) return;
    try {
      setLoading(true);
      setError(null);
      const response = await api.get(`/transactions/user/${user.id}`);
      setTransactions(response.data.data);
    } catch (err) {
      setError('Failed to load transactions. Please try again.');
      console.error('Error fetching transactions:', err);
    } finally {
      setLoading(false);
    }
  }, []); // user.id is static

  const handleRefresh = () =&amp;gt; {
      toast.success('Refreshing data...');
      fetchUserAccounts();
      fetchTransactions();
  }

  useEffect(() =&amp;gt; {
    handleRefresh();
  }, [fetchUserAccounts, fetchTransactions]);


  // --- FILTERING &amp;amp; SORTING ---
  const filteredAndSortedTransactions = useMemo(() =&amp;gt; {
    let filtered = transactions.filter(t =&amp;gt; {
      const transactionDate = new Date(t.timestamp);
      const startDate = filters.startDate ? new Date(filters.startDate) : null;
      const endDate = filters.endDate ? new Date(filters.endDate) : null;

      if(startDate) startDate.setHours(0,0,0,0);
      if(endDate) endDate.setHours(23,59,59,999);

      const inDateRange = (!startDate || transactionDate &amp;gt;= startDate) &amp;amp;&amp;amp; (!endDate || transactionDate &amp;lt;= endDate);
      const inSearch = t.description.toLowerCase().includes(filters.searchTerm.toLowerCase());
      const inAccount = filters.account === 'all' || t.fromAccount?.accountNumber === filters.account || t.toAccount?.accountNumber === filters.account;
      const inType = filters.type === 'all' || t.type === filters.type;

      return inDateRange &amp;amp;&amp;amp; inSearch &amp;amp;&amp;amp; inAccount &amp;amp;&amp;amp; inType;
    });

    return filtered.sort((a, b) =&amp;gt; {
      if (a[sortConfig.key] &amp;lt; b[sortConfig.key]) {
        return sortConfig.direction === 'asc' ? -1 : 1;
      }
      if (a[sortConfig.key] &amp;gt; b[sortConfig.key]) {
        return sortConfig.direction === 'asc' ? 1 : -1;
      }
      return 0;
    });
  }, [transactions, filters, sortConfig]);

  const handleSort = (key) =&amp;gt; {
    setSortConfig(prev =&amp;gt; ({
      key,
      direction: prev.key === key &amp;amp;&amp;amp; prev.direction === 'asc' ? 'desc' : 'asc'
    }));
  };

  const handleFilterChange = (e) =&amp;gt; {
    const { name, value } = e.target;
    setFilters(prev =&amp;gt; ({ ...prev, [name]: value }));
  };

  const resetFilters = () =&amp;gt; {
    setFilters({ searchTerm: '', account: 'all', type: 'all', startDate: '', endDate: '' });
    setSortConfig({ key: 'timestamp', direction: 'desc' });
    toast.success("Filters Reset");
  };


  // --- CHART DATA PROCESSING ---
  const analyticsData = useMemo(() =&amp;gt; {
    const incomeVsExpense = [
        { name: 'Income', amount: filteredAndSortedTransactions.filter(t =&amp;gt; t.type === 'DEPOSIT').reduce((sum, t) =&amp;gt; sum + t.amount, 0) },
        { name: 'Expenses', amount: filteredAndSortedTransactions.filter(t =&amp;gt; ['WITHDRAW', 'TRANSFER'].includes(t.type)).reduce((sum, t) =&amp;gt; sum + t.amount, 0) }
    ];

    const typeDistribution = Object.entries(
      filteredAndSortedTransactions.reduce((acc, t) =&amp;gt; {
        acc[t.type] = (acc[t.type] || 0) + 1;
        return acc;
      }, {})
    ).map(([name, value]) =&amp;gt; ({ name, value }));

    const trendData = filteredAndSortedTransactions
      .map(t =&amp;gt; ({ ...t, date: new Date(t.timestamp).toISOString().split('T')[0] }))
      .reduce((acc, t) =&amp;gt; {
        if (!acc[t.date]) acc[t.date] = { date: t.date, amount: 0 };
        acc[t.date].amount += t.amount;
        return acc;
      }, {});

    const sortedTrendData = Object.values(trendData).sort((a,b) =&amp;gt; new Date(a.date) - new Date(b.date));

    return { incomeVsExpense, typeDistribution, trendData: sortedTrendData };
  }, [filteredAndSortedTransactions]);

  const PIE_COLORS = {
      DEPOSIT: colors.success,
      WITHDRAW: colors.error,
      TRANSFER: colors.primary
  };

  const CustomTooltip = ({ active, payload, label }) =&amp;gt; {
    if (active &amp;amp;&amp;amp; payload &amp;amp;&amp;amp; payload.length) {
      return (
        &amp;lt;div style={{ background: 'white', padding: '10px', border: `1px solid ${colors.border}`, borderRadius: '10px' }}&amp;gt;
          &amp;lt;p style={{ fontWeight: 600, color: colors.text }}&amp;gt;{`Date: ${label}`}&amp;lt;/p&amp;gt;
          &amp;lt;p style={{ color: colors.primary }}&amp;gt;{`Amount: $${payload[0].value.toFixed(2)}`}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      );
    }
    return null;
  };

  // --- RENDER LOGIC ---
  if (error) {
    return (
      &amp;lt;Container&amp;gt;
        &amp;lt;ErrorMessage initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }}&amp;gt;
          &amp;lt;AlertCircle size={48} /&amp;gt;
          &amp;lt;h3&amp;gt;Oops! Something went wrong.&amp;lt;/h3&amp;gt;
          &amp;lt;p&amp;gt;{error}&amp;lt;/p&amp;gt;
          &amp;lt;Button variant="primary" onClick={handleRefresh}&amp;gt;&amp;lt;RefreshCw size={16} /&amp;gt; Try Again&amp;lt;/Button&amp;gt;
        &amp;lt;/ErrorMessage&amp;gt;
      &amp;lt;/Container&amp;gt;
    );
  }

  return (
    &amp;lt;Container initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.5 }}&amp;gt;
      &amp;lt;h2&amp;gt;Transaction Analytics&amp;lt;/h2&amp;gt;

      &amp;lt;FilterSection initial={{ opacity: 0, y: -20 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.2 }}&amp;gt;
        &amp;lt;SearchContainer&amp;gt;
          &amp;lt;Search size={20} /&amp;gt;
          &amp;lt;SearchInput
            type="text"
            name="searchTerm"
            placeholder="Search by description..."
            value={filters.searchTerm}
            onChange={handleFilterChange}
          /&amp;gt;
        &amp;lt;/SearchContainer&amp;gt;
        &amp;lt;FiltersGrid&amp;gt;
          &amp;lt;FilterSelect name="account" value={filters.account} onChange={handleFilterChange} disabled={accountsLoading}&amp;gt;
            &amp;lt;option value="all"&amp;gt;All Accounts&amp;lt;/option&amp;gt;
            {userAccounts.map(acc =&amp;gt; (
              &amp;lt;option key={acc.id} value={acc.accountNumber}&amp;gt;
                {acc.accountType} - {acc.accountNumber}
              &amp;lt;/option&amp;gt;
            ))}
          &amp;lt;/FilterSelect&amp;gt;
          &amp;lt;FilterSelect name="type" value={filters.type} onChange={handleFilterChange}&amp;gt;
            &amp;lt;option value="all"&amp;gt;All Types&amp;lt;/option&amp;gt;
            &amp;lt;option value="DEPOSIT"&amp;gt;Deposit&amp;lt;/option&amp;gt;
            &amp;lt;option value="WITHDRAW"&amp;gt;Withdraw&amp;lt;/option&amp;gt;
            &amp;lt;option value="TRANSFER"&amp;gt;Transfer&amp;lt;/option&amp;gt;
          &amp;lt;/FilterSelect&amp;gt;
          &amp;lt;DateInput type="date" name="startDate" value={filters.startDate} onChange={handleFilterChange} /&amp;gt;
          &amp;lt;DateInput type="date" name="endDate" value={filters.endDate} onChange={handleFilterChange} /&amp;gt;
        &amp;lt;/FiltersGrid&amp;gt;
        &amp;lt;ButtonGroup&amp;gt;
            &amp;lt;Button onClick={resetFilters} whileTap={{ scale: 0.95 }}&amp;gt;
                &amp;lt;X size={16} /&amp;gt; Reset
            &amp;lt;/Button&amp;gt;
            &amp;lt;Button variant="primary" onClick={handleRefresh} disabled={loading || accountsLoading} whileTap={{ scale: 0.95 }}&amp;gt;
                &amp;lt;RefreshCw size={16} /&amp;gt; Refresh Data
            &amp;lt;/Button&amp;gt;
        &amp;lt;/ButtonGroup&amp;gt;
      &amp;lt;/FilterSection&amp;gt;

      {loading ? (
        &amp;lt;LoadingSpinner&amp;gt;&amp;lt;RefreshCw size={48} /&amp;gt;&amp;lt;/LoadingSpinner&amp;gt;
      ) : (
        &amp;lt;&amp;gt;
            &amp;lt;AnalyticsGrid initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.4 }}&amp;gt;
                &amp;lt;ChartContainer&amp;gt;
                    &amp;lt;h3&amp;gt;Income vs. Expense&amp;lt;/h3&amp;gt;
                    &amp;lt;ResponsiveContainer width="100%" height={300}&amp;gt;
                        &amp;lt;BarChart data={analyticsData.incomeVsExpense} margin={{ top: 5, right: 20, left: -10, bottom: 5 }}&amp;gt;
                            &amp;lt;CartesianGrid strokeDasharray="3 3" stroke={colors.border}/&amp;gt;
                            &amp;lt;XAxis dataKey="name" stroke={colors.textSecondary} /&amp;gt;
                            &amp;lt;YAxis stroke={colors.textSecondary}/&amp;gt;
                            &amp;lt;Tooltip cursor={{fill: 'rgba(102, 126, 234, 0.1)'}}/&amp;gt;
                            &amp;lt;Legend /&amp;gt;
                            &amp;lt;Bar dataKey="amount" name="Amount"&amp;gt;
                                {analyticsData.incomeVsExpense.map((entry, index) =&amp;gt; (
                                    &amp;lt;Cell key={`cell-${index}`} fill={entry.name === 'Income' ? colors.success : colors.error} /&amp;gt;
                                ))}
                            &amp;lt;/Bar&amp;gt;
                        &amp;lt;/BarChart&amp;gt;
                    &amp;lt;/ResponsiveContainer&amp;gt;
                &amp;lt;/ChartContainer&amp;gt;
                 &amp;lt;ChartContainer&amp;gt;
                    &amp;lt;h3&amp;gt;Transaction Trend&amp;lt;/h3&amp;gt;
                    &amp;lt;ResponsiveContainer width="100%" height={300}&amp;gt;
                        &amp;lt;LineChart data={analyticsData.trendData} margin={{ top: 5, right: 20, left: -10, bottom: 5 }}&amp;gt;
                            &amp;lt;CartesianGrid strokeDasharray="3 3" stroke={colors.border} /&amp;gt;
                            &amp;lt;XAxis dataKey="date" stroke={colors.textSecondary} tickFormatter={(str) =&amp;gt; new Date(str).toLocaleDateString('en-US', {month: 'short', day: 'numeric'})} /&amp;gt;
                            &amp;lt;YAxis stroke={colors.textSecondary}/&amp;gt;
                            &amp;lt;Tooltip content={&amp;lt;CustomTooltip /&amp;gt;}/&amp;gt;
                            &amp;lt;Legend /&amp;gt;
                            &amp;lt;Line type="monotone" dataKey="amount" stroke={colors.primary} strokeWidth={2} dot={{ r: 4 }} activeDot={{ r: 8 }} name="Total Amount"/&amp;gt;
                        &amp;lt;/LineChart&amp;gt;
                    &amp;lt;/ResponsiveContainer&amp;gt;
                &amp;lt;/ChartContainer&amp;gt;
                &amp;lt;ChartContainer&amp;gt;
                    &amp;lt;h3&amp;gt;Transaction by Type&amp;lt;/h3&amp;gt;
                    &amp;lt;ResponsiveContainer width="100%" height={300}&amp;gt;
                        &amp;lt;PieChart&amp;gt;
                            &amp;lt;Pie data={analyticsData.typeDistribution} dataKey="value" nameKey="name" cx="50%" cy="50%" outerRadius={100} label&amp;gt;
                                {analyticsData.typeDistribution.map((entry, index) =&amp;gt; (
                                    &amp;lt;Cell key={`cell-${index}`} fill={PIE_COLORS[entry.name]} /&amp;gt;
                                ))}
                            &amp;lt;/Pie&amp;gt;
                            &amp;lt;Tooltip /&amp;gt;
                            &amp;lt;Legend /&amp;gt;
                        &amp;lt;/PieChart&amp;gt;
                    &amp;lt;/ResponsiveContainer&amp;gt;
                &amp;lt;/ChartContainer&amp;gt;
            &amp;lt;/AnalyticsGrid&amp;gt;

            &amp;lt;AnimatePresence&amp;gt;
                {filteredAndSortedTransactions.length &amp;gt; 0 ? (
                &amp;lt;TableContainer initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.6 }}&amp;gt;
                    &amp;lt;Table&amp;gt;
                    &amp;lt;thead&amp;gt;
                        &amp;lt;tr&amp;gt;
                            &amp;lt;th onClick={() =&amp;gt; handleSort('timestamp')}&amp;gt;Date &amp;lt;ArrowUpDown size={14} /&amp;gt;&amp;lt;/th&amp;gt;
                            &amp;lt;th onClick={() =&amp;gt; handleSort('description')}&amp;gt;Description &amp;lt;ArrowUpDown size={14} /&amp;gt;&amp;lt;/th&amp;gt;
                            &amp;lt;th&amp;gt;From&amp;lt;/th&amp;gt;
                            &amp;lt;th&amp;gt;To&amp;lt;/th&amp;gt;
                            &amp;lt;th onClick={() =&amp;gt; handleSort('type')}&amp;gt;Type &amp;lt;ArrowUpDown size={14} /&amp;gt;&amp;lt;/th&amp;gt;
                            &amp;lt;th onClick={() =&amp;gt; handleSort('amount')}&amp;gt;Amount &amp;lt;ArrowUpDown size={14} /&amp;gt;&amp;lt;/th&amp;gt;
                            &amp;lt;th onClick={() =&amp;gt; handleSort('status')}&amp;gt;Status &amp;lt;ArrowUpDown size={14} /&amp;gt;&amp;lt;/th&amp;gt;
                        &amp;lt;/tr&amp;gt;
                    &amp;lt;/thead&amp;gt;
                    &amp;lt;tbody&amp;gt;
                        {filteredAndSortedTransactions.map(t =&amp;gt; (
                        &amp;lt;motion.tr key={t.id} initial={{ opacity: 0 }} animate={{ opacity: 1 }}&amp;gt;
                            &amp;lt;td&amp;gt;{new Date(t.timestamp).toLocaleDateString()}&amp;lt;/td&amp;gt;
                            &amp;lt;td&amp;gt;{t.description}&amp;lt;/td&amp;gt;
                            &amp;lt;td&amp;gt;{t.fromAccount?.accountNumber || 'N/A'}&amp;lt;/td&amp;gt;
                            &amp;lt;td&amp;gt;{t.toAccount?.accountNumber || 'N/A'}&amp;lt;/td&amp;gt;
                            &amp;lt;td&amp;gt;&amp;lt;TypeBadge type={t.type}&amp;gt;{t.type}&amp;lt;/TypeBadge&amp;gt;&amp;lt;/td&amp;gt;
                            &amp;lt;td style={{ color: ['DEPOSIT'].includes(t.type) ? colors.success : colors.error, fontWeight: '600' }}&amp;gt;
                               {['DEPOSIT'].includes(t.type) ? '+' : '-'} ${t.amount.toFixed(2)}
                            &amp;lt;/td&amp;gt;
                            &amp;lt;td&amp;gt;&amp;lt;StatusBadge status={t.status}&amp;gt;{t.status}&amp;lt;/StatusBadge&amp;gt;&amp;lt;/td&amp;gt;
                        &amp;lt;/motion.tr&amp;gt;
                        ))}
                    &amp;lt;/tbody&amp;gt;
                    &amp;lt;/Table&amp;gt;
                &amp;lt;/TableContainer&amp;gt;
                ) : (
                &amp;lt;EmptyState initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ delay: 0.6 }}&amp;gt;
                    &amp;lt;Filter size={48} /&amp;gt;
                    &amp;lt;h3&amp;gt;No Transactions Found&amp;lt;/h3&amp;gt;
                    &amp;lt;p&amp;gt;Try adjusting your filters or click Refresh to fetch the latest data.&amp;lt;/p&amp;gt;
                &amp;lt;/EmptyState&amp;gt;
                )}
            &amp;lt;/AnimatePresence&amp;gt;
        &amp;lt;/&amp;gt;
      )}
    &amp;lt;/Container&amp;gt;
  );
};

export default TransactionAnalytics;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>apikey</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Wed, 02 Jul 2025 19:45:00 +0000</pubDate>
      <link>https://dev.to/nebula_3108/apikey-1399</link>
      <guid>https://dev.to/nebula_3108/apikey-1399</guid>
      <description>&lt;p&gt;ira_T7H78xibLqmLD7LyC1Z7VCyfNP8fha1wBL63&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Subject: Feedback on Internship Buddy Program - Rasika [Last Name]&lt;br&gt;
Dear [Manager's Name/HR Team],&lt;br&gt;
I am writing to provide feedback on my internship experience with the Morpheus team, specifically regarding the buddy program.&lt;br&gt;
I would like to commend Rasika for her exceptional support throughout my internship tenure. As my assigned buddy, she has been consistently helpful and considerate, always making time in her busy schedule to assist me whenever I encountered challenges or needed guidance.&lt;br&gt;
Rasika's willingness to share her knowledge and provide direction has significantly contributed to my smooth integration into the team and overall positive internship experience. Her mentorship has been invaluable in helping me navigate both technical and organizational aspects of my role.&lt;br&gt;
I believe the buddy program is highly effective, and Rasika exemplifies the qualities that make this initiative successful. I wanted to ensure her contributions are recognized and appreciated.&lt;br&gt;
Thank you for providing such a supportive learning environment.&lt;br&gt;
Best regards,&lt;br&gt;
[Your Name]&lt;br&gt;
[Your Position - Intern, Morpheus Team]&lt;br&gt;
[Your Contact Information]&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>security</category>
      <category>api</category>
    </item>
    <item>
      <title>analytics</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Wed, 02 Jul 2025 05:44:48 +0000</pubDate>
      <link>https://dev.to/nebula_3108/analytics-35p8</link>
      <guid>https://dev.to/nebula_3108/analytics-35p8</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect, useCallback, useMemo } from "react";
import { Search, Filter, X, RefreshCw, AlertCircle, TrendingUp, TrendingDown, Calendar, DollarSign, PieChart, BarChart3, Download, Eye, EyeOff } from "lucide-react";
import styled from 'styled-components';
import { motion, AnimatePresence } from 'framer-motion';
import { LineChart, Line, AreaChart, Area, BarChart, Bar, PieChart as RechartsPieChart, Cell, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';

// Design tokens (from your original file)
const colors = {
  primary: '#667eea',
  primaryDark: '#5a67d8',
  secondary: '#764ba2',
  success: '#48bb78',
  error: '#ff6b6b',
  warning: '#f6ad55',
  text: '#1a202c',
  textSecondary: '#4a5568',
  textMuted: '#a0aec0',
  background: 'rgba(255, 255, 255, 0.95)',
  border: 'rgba(102, 126, 234, 0.2)',
  borderHover: '#667eea',
  glass: 'rgba(255, 255, 255, 0.95)',
  glassLight: 'rgba(255, 255, 255, 0.8)',
  shadow: 'rgba(0, 0, 0, 0.1)',
  shadowHover: 'rgba(102, 126, 234, 0.1)'
};

const gradients = {
  primary: `linear-gradient(135deg, ${colors.primary}, ${colors.secondary})`,
  success: `linear-gradient(135deg, ${colors.success}, #38b2ac)`,
  error: `linear-gradient(135deg, ${colors.error}, #ee5a52)`,
  warning: `linear-gradient(135deg, ${colors.warning}, #ff8c00)`
};

const spacing = {
  xs: '4px',
  sm: '8px',
  md: '12px',
  lg: '16px',
  xl: '20px',
  xxl: '24px',
  xxxl: '32px'
};

// Styled Components
const Container = styled(motion.div)`
  padding: ${spacing.xxxl};
  max-width: 1400px;
  margin: 0 auto;
  min-height: calc(100vh - 120px);

  h1 {
    font-size: 36px;
    font-weight: 800;
    color: ${colors.text};
    margin-bottom: ${spacing.sm};
    background: ${gradients.primary};
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    text-align: center;
  }

  .subtitle {
    text-align: center;
    color: ${colors.textMuted};
    margin-bottom: ${spacing.xxxl};
    font-size: 16px;
  }

  @media (max-width: 768px) {
    padding: ${spacing.xl};

    h1 {
      font-size: 28px;
      margin-bottom: ${spacing.xs};
    }
  }
`;

const StatsGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: ${spacing.xl};
  margin-bottom: ${spacing.xxxl};

  @media (max-width: 768px) {
    grid-template-columns: 1fr;
    gap: ${spacing.lg};
  }
`;

const StatCard = styled(motion.div)`
  background: ${colors.glass};
  backdrop-filter: blur(20px);
  border-radius: 20px;
  padding: ${spacing.xxl};
  box-shadow: 0 8px 32px ${colors.shadow};
  border: 1px solid rgba(255, 255, 255, 0.2);
  position: relative;
  overflow: hidden;

  &amp;amp;::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: ${props =&amp;gt; props.color || gradients.primary};
  }

  .stat-header {
    display: flex;
    align-items: center;
    gap: ${spacing.md};
    margin-bottom: ${spacing.lg};

    svg {
      color: ${props =&amp;gt; props.iconColor || colors.primary};
    }

    h3 {
      margin: 0;
      font-size: 14px;
      font-weight: 600;
      color: ${colors.textSecondary};
      text-transform: uppercase;
      letter-spacing: 0.5px;
    }
  }

  .stat-value {
    font-size: 32px;
    font-weight: 800;
    color: ${colors.text};
    margin-bottom: ${spacing.sm};
  }

  .stat-change {
    display: flex;
    align-items: center;
    gap: ${spacing.xs};
    font-size: 14px;
    font-weight: 600;

    &amp;amp;.positive {
      color: ${colors.success};
    }

    &amp;amp;.negative {
      color: ${colors.error};
    }
  }
`;

const FilterSection = styled(motion.div)`
  background: ${colors.glass};
  backdrop-filter: blur(20px);
  border-radius: 20px;
  padding: ${spacing.xxl};
  margin-bottom: ${spacing.xxxl};
  box-shadow: 0 8px 32px ${colors.shadow};
  border: 1px solid rgba(255, 255, 255, 0.2);
  position: relative;
  overflow: hidden;

  &amp;amp;::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: ${gradients.primary};
  }

  .filter-header {
    display: flex;
    align-items: center;
    gap: ${spacing.md};
    margin-bottom: ${spacing.xl};

    h3 {
      margin: 0;
      font-size: 18px;
      font-weight: 600;
      color: ${colors.text};
    }
  }
`;

const FiltersGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: ${spacing.lg};
  margin-bottom: ${spacing.xl};

  @media (max-width: 768px) {
    grid-template-columns: 1fr;
  }
`;

const FilterSelect = styled.select`
  padding: ${spacing.lg} ${spacing.xl};
  border: 2px solid ${colors.border};
  border-radius: 12px;
  font-size: 16px;
  font-weight: 500;
  color: ${colors.text};
  background: ${colors.glassLight};
  backdrop-filter: blur(10px);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;

  &amp;amp;:focus {
    outline: none;
    border-color: ${colors.borderHover};
    box-shadow: 0 0 0 4px ${colors.shadowHover};
    background: ${colors.background};
  }
`;

const DateInput = styled.input`
  padding: ${spacing.lg} ${spacing.xl};
  border: 2px solid ${colors.border};
  border-radius: 12px;
  font-size: 16px;
  font-weight: 500;
  color: ${colors.text};
  background: ${colors.glassLight};
  backdrop-filter: blur(10px);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

  &amp;amp;:focus {
    outline: none;
    border-color: ${colors.borderHover};
    box-shadow: 0 0 0 4px ${colors.shadowHover};
    background: ${colors.background};
  }
`;

const AmountRangeContainer = styled.div`
  display: flex;
  gap: ${spacing.md};
  align-items: center;

  input {
    flex: 1;
    padding: ${spacing.lg};
    border: 2px solid ${colors.border};
    border-radius: 12px;
    font-size: 16px;
    font-weight: 500;
    color: ${colors.text};
    background: ${colors.glassLight};
    backdrop-filter: blur(10px);
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

    &amp;amp;:focus {
      outline: none;
      border-color: ${colors.borderHover};
      box-shadow: 0 0 0 4px ${colors.shadowHover};
      background: ${colors.background};
    }
  }

  span {
    color: ${colors.textMuted};
    font-weight: 600;
  }
`;

const ButtonGroup = styled.div`
  display: flex;
  gap: ${spacing.md};
  justify-content: flex-end;

  @media (max-width: 768px) {
    justify-content: stretch;
  }
`;

const Button = styled(motion.button)`
  display: flex;
  align-items: center;
  gap: ${spacing.sm};
  padding: ${spacing.md} ${spacing.xl};
  border-radius: 12px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border: 2px solid transparent;

  ${props =&amp;gt; props.variant === 'primary' ? `
    background: ${gradients.primary};
    color: white;
    box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);

    &amp;amp;:hover:not(:disabled) {
      transform: translateY(-2px);
      box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5);
    }
  ` : `
    background: transparent;
    color: ${colors.textSecondary};
    border-color: #e2e8f0;

    &amp;amp;:hover:not(:disabled) {
      background: #f7fafc;
      border-color: #cbd5e0;
    }
  `}

  &amp;amp;:active {
    transform: translateY(0);
  }

  &amp;amp;:disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }

  @media (max-width: 768px) {
    flex: 1;
    justify-content: center;
  }
`;

const ChartsGrid = styled.div`
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: ${spacing.xl};
  margin-bottom: ${spacing.xxxl};

  @media (max-width: 1024px) {
    grid-template-columns: 1fr;
  }
`;

const ChartContainer = styled(motion.div)`
  background: ${colors.glass};
  backdrop-filter: blur(20px);
  border-radius: 20px;
  padding: ${spacing.xxl};
  box-shadow: 0 8px 32px ${colors.shadow};
  border: 1px solid rgba(255, 255, 255, 0.2);
  position: relative;
  overflow: hidden;
  grid-column: ${props =&amp;gt; props.fullWidth ? 'span 2' : 'span 1'};

  @media (max-width: 1024px) {
    grid-column: span 1;
  }

  &amp;amp;::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: ${gradients.primary};
  }

  .chart-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: ${spacing.xl};

    h3 {
      margin: 0;
      font-size: 18px;
      font-weight: 600;
      color: ${colors.text};
    }

    .chart-controls {
      display: flex;
      gap: ${spacing.sm};
    }
  }

  .chart-wrapper {
    height: 300px;
  }
`;

const ToggleButton = styled(motion.button)`
  padding: ${spacing.sm} ${spacing.md};
  border: 2px solid ${colors.border};
  border-radius: 8px;
  background: ${props =&amp;gt; props.active ? gradients.primary : 'transparent'};
  color: ${props =&amp;gt; props.active ? 'white' : colors.textSecondary};
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;

  &amp;amp;:hover {
    border-color: ${colors.borderHover};
  }
`;

const LoadingSpinner = styled(motion.div)`
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 64px;
  color: ${colors.primary};

  svg {
    animation: spin 1s linear infinite;
  }

  @keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
`;

// Mock data generator
const generateMockTransactions = (count = 100) =&amp;gt; {
  const types = ['DEPOSIT', 'WITHDRAW', 'TRANSFER', 'LOAN'];
  const statuses = ['SUCCESS', 'PENDING', 'FAILED'];
  const merchants = ['Amazon', 'Starbucks', 'Uber', 'Netflix', 'Spotify', 'Apple', 'Google', 'Microsoft', 'Target', 'Walmart'];
  const categories = ['Food &amp;amp; Dining', 'Shopping', 'Transportation', 'Entertainment', 'Bills &amp;amp; Utilities', 'Healthcare', 'Travel', 'Education'];

  return Array.from({ length: count }, (_, index) =&amp;gt; {
    const type = types[Math.floor(Math.random() * types.length)];
    const amount = type === 'DEPOSIT' 
      ? Math.floor(Math.random() * 5000) + 100
      : -(Math.floor(Math.random() * 1000) + 10);

    return {
      id: `txn_${index + 1}`,
      type,
      amount,
      status: statuses[Math.floor(Math.random() * statuses.length)],
      date: new Date(Date.now() - Math.floor(Math.random() * 90) * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
      merchant: merchants[Math.floor(Math.random() * merchants.length)],
      category: categories[Math.floor(Math.random() * categories.length)],
      description: `Transaction with ${merchants[Math.floor(Math.random() * merchants.length)]}`
    };
  });
};

// Custom tooltip component
const CustomTooltip = ({ active, payload, label }) =&amp;gt; {
  if (active &amp;amp;&amp;amp; payload &amp;amp;&amp;amp; payload.length) {
    return (
      &amp;lt;div style={{
        background: colors.glass,
        backdropFilter: 'blur(20px)',
        border: `1px solid ${colors.border}`,
        borderRadius: '12px',
        padding: spacing.md,
        boxShadow: `0 8px 32px ${colors.shadow}`
      }}&amp;gt;
        &amp;lt;p style={{ margin: 0, color: colors.text, fontWeight: '600' }}&amp;gt;{label}&amp;lt;/p&amp;gt;
        {payload.map((entry, index) =&amp;gt; (
          &amp;lt;p key={index} style={{ margin: '4px 0', color: entry.color, fontSize: '14px' }}&amp;gt;
            {`${entry.name}: $${Math.abs(entry.value).toLocaleString()}`}
          &amp;lt;/p&amp;gt;
        ))}
      &amp;lt;/div&amp;gt;
    );
  }
  return null;
};

const BankingAnalyticsDashboard = () =&amp;gt; {
  const [transactions, setTransactions] = useState([]);
  const [loading, setLoading] = useState(true);
  const [filters, setFilters] = useState({
    type: 'ALL',
    status: 'ALL',
    category: 'ALL',
    dateFrom: '',
    dateTo: '',
    amountMin: '',
    amountMax: ''
  });
  const [chartView, setChartView] = useState({
    timeChart: 'line',
    showBalance: true
  });

  // Simulate API call
  useEffect(() =&amp;gt; {
    const fetchTransactions = async () =&amp;gt; {
      setLoading(true);
      // Simulate API delay
      await new Promise(resolve =&amp;gt; setTimeout(resolve, 1000));
      setTransactions(generateMockTransactions(150));
      setLoading(false);
    };

    fetchTransactions();
  }, []);

  // Filter transactions
  const filteredTransactions = useMemo(() =&amp;gt; {
    return transactions.filter(transaction =&amp;gt; {
      if (filters.type !== 'ALL' &amp;amp;&amp;amp; transaction.type !== filters.type) return false;
      if (filters.status !== 'ALL' &amp;amp;&amp;amp; transaction.status !== filters.status) return false;
      if (filters.category !== 'ALL' &amp;amp;&amp;amp; transaction.category !== filters.category) return false;
      if (filters.dateFrom &amp;amp;&amp;amp; transaction.date &amp;lt; filters.dateFrom) return false;
      if (filters.dateTo &amp;amp;&amp;amp; transaction.date &amp;gt; filters.dateTo) return false;
      if (filters.amountMin &amp;amp;&amp;amp; Math.abs(transaction.amount) &amp;lt; parseFloat(filters.amountMin)) return false;
      if (filters.amountMax &amp;amp;&amp;amp; Math.abs(transaction.amount) &amp;gt; parseFloat(filters.amountMax)) return false;
      return true;
    });
  }, [transactions, filters]);

  // Calculate statistics
  const stats = useMemo(() =&amp;gt; {
    const totalIncome = filteredTransactions
      .filter(t =&amp;gt; t.amount &amp;gt; 0)
      .reduce((sum, t) =&amp;gt; sum + t.amount, 0);

    const totalExpenses = filteredTransactions
      .filter(t =&amp;gt; t.amount &amp;lt; 0)
      .reduce((sum, t) =&amp;gt; sum + Math.abs(t.amount), 0);

    const netBalance = totalIncome - totalExpenses;
    const avgTransaction = filteredTransactions.length &amp;gt; 0 
      ? filteredTransactions.reduce((sum, t) =&amp;gt; sum + Math.abs(t.amount), 0) / filteredTransactions.length 
      : 0;

    // Calculate month-over-month changes (mock data)
    const incomeChange = Math.random() * 20 - 10; // -10% to +10%
    const expenseChange = Math.random() * 20 - 10;
    const balanceChange = Math.random() * 30 - 15;

    return {
      totalIncome,
      totalExpenses,
      netBalance,
      avgTransaction,
      transactionCount: filteredTransactions.length,
      incomeChange,
      expenseChange,
      balanceChange
    };
  }, [filteredTransactions]);

  // Prepare chart data
  const timeSeriesData = useMemo(() =&amp;gt; {
    const dataMap = {};
    let runningBalance = 0;

    filteredTransactions
      .sort((a, b) =&amp;gt; new Date(a.date) - new Date(b.date))
      .forEach(transaction =&amp;gt; {
        const date = transaction.date;
        if (!dataMap[date]) {
          dataMap[date] = { date, income: 0, expenses: 0, balance: runningBalance };
        }

        if (transaction.amount &amp;gt; 0) {
          dataMap[date].income += transaction.amount;
        } else {
          dataMap[date].expenses += Math.abs(transaction.amount);
        }

        runningBalance += transaction.amount;
        dataMap[date].balance = runningBalance;
      });

    return Object.values(dataMap);
  }, [filteredTransactions]);

  const categoryData = useMemo(() =&amp;gt; {
    const categoryMap = {};
    filteredTransactions.forEach(transaction =&amp;gt; {
      if (transaction.amount &amp;lt; 0) { // Only expenses
        const category = transaction.category;
        categoryMap[category] = (categoryMap[category] || 0) + Math.abs(transaction.amount);
      }
    });

    return Object.entries(categoryMap).map(([name, value]) =&amp;gt; ({ name, value }));
  }, [filteredTransactions]);

  const typeData = useMemo(() =&amp;gt; {
    const typeMap = {};
    filteredTransactions.forEach(transaction =&amp;gt; {
      const type = transaction.type;
      typeMap[type] = (typeMap[type] || 0) + Math.abs(transaction.amount);
    });

    return Object.entries(typeMap).map(([name, value]) =&amp;gt; ({ name, value }));
  }, [filteredTransactions]);

  const handleFilterChange = (key, value) =&amp;gt; {
    setFilters(prev =&amp;gt; ({ ...prev, [key]: value }));
  };

  const resetFilters = () =&amp;gt; {
    setFilters({
      type: 'ALL',
      status: 'ALL',
      category: 'ALL',
      dateFrom: '',
      dateTo: '',
      amountMin: '',
      amountMax: ''
    });
  };

  const refreshData = () =&amp;gt; {
    setTransactions(generateMockTransactions(150));
  };

  const exportData = () =&amp;gt; {
    // Mock export functionality
    const dataStr = JSON.stringify(filteredTransactions, null, 2);
    const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);

    const exportFileDefaultName = 'transaction-analytics.json';

    const linkElement = document.createElement('a');
    linkElement.setAttribute('href', dataUri);
    linkElement.setAttribute('download', exportFileDefaultName);
    linkElement.click();
  };

  const pieColors = [colors.primary, colors.secondary, colors.success, colors.warning, colors.error, '#9f7aea', '#38b2ac', '#ed8936'];

  if (loading) {
    return (
      &amp;lt;Container&amp;gt;
        &amp;lt;LoadingSpinner
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
        &amp;gt;
          &amp;lt;RefreshCw size={32} /&amp;gt;
          &amp;lt;span style={{ marginLeft: spacing.md, fontSize: '18px', fontWeight: '600' }}&amp;gt;
            Loading Analytics...
          &amp;lt;/span&amp;gt;
        &amp;lt;/LoadingSpinner&amp;gt;
      &amp;lt;/Container&amp;gt;
    );
  }

  return (
    &amp;lt;Container
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.6 }}
    &amp;gt;
      &amp;lt;h1&amp;gt;Transaction Analytics&amp;lt;/h1&amp;gt;
      &amp;lt;p className="subtitle"&amp;gt;Comprehensive insights into your financial activities&amp;lt;/p&amp;gt;

      {/* Statistics Cards */}
      &amp;lt;StatsGrid&amp;gt;
        &amp;lt;StatCard
          color={gradients.success}
          iconColor={colors.success}
          initial={{ opacity: 0, y: 30 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.1 }}
        &amp;gt;
          &amp;lt;div className="stat-header"&amp;gt;
            &amp;lt;TrendingUp size={20} /&amp;gt;
            &amp;lt;h3&amp;gt;Total Income&amp;lt;/h3&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="stat-value"&amp;gt;${stats.totalIncome.toLocaleString()}&amp;lt;/div&amp;gt;
          &amp;lt;div className={`stat-change ${stats.incomeChange &amp;gt;= 0 ? 'positive' : 'negative'}`}&amp;gt;
            {stats.incomeChange &amp;gt;= 0 ? &amp;lt;TrendingUp size={16} /&amp;gt; : &amp;lt;TrendingDown size={16} /&amp;gt;}
            {Math.abs(stats.incomeChange).toFixed(1)}% from last month
          &amp;lt;/div&amp;gt;
        &amp;lt;/StatCard&amp;gt;

        &amp;lt;StatCard
          color={gradients.error}
          iconColor={colors.error}
          initial={{ opacity: 0, y: 30 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.2 }}
        &amp;gt;
          &amp;lt;div className="stat-header"&amp;gt;
            &amp;lt;TrendingDown size={20} /&amp;gt;
            &amp;lt;h3&amp;gt;Total Expenses&amp;lt;/h3&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="stat-value"&amp;gt;${stats.totalExpenses.toLocaleString()}&amp;lt;/div&amp;gt;
          &amp;lt;div className={`stat-change ${stats.expenseChange &amp;lt;= 0 ? 'positive' : 'negative'}`}&amp;gt;
            {stats.expenseChange &amp;lt;= 0 ? &amp;lt;TrendingDown size={16} /&amp;gt; : &amp;lt;TrendingUp size={16} /&amp;gt;}
            {Math.abs(stats.expenseChange).toFixed(1)}% from last month
          &amp;lt;/div&amp;gt;
        &amp;lt;/StatCard&amp;gt;

        &amp;lt;StatCard
          color={stats.netBalance &amp;gt;= 0 ? gradients.success : gradients.error}
          iconColor={stats.netBalance &amp;gt;= 0 ? colors.success : colors.error}
          initial={{ opacity: 0, y: 30 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.3 }}
        &amp;gt;
          &amp;lt;div className="stat-header"&amp;gt;
            &amp;lt;DollarSign size={20} /&amp;gt;
            &amp;lt;h3&amp;gt;Net Balance&amp;lt;/h3&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="stat-value"&amp;gt;${stats.netBalance.toLocaleString()}&amp;lt;/div&amp;gt;
          &amp;lt;div className={`stat-change ${stats.balanceChange &amp;gt;= 0 ? 'positive' : 'negative'}`}&amp;gt;
            {stats.balanceChange &amp;gt;= 0 ? &amp;lt;TrendingUp size={16} /&amp;gt; : &amp;lt;TrendingDown size={16} /&amp;gt;}
            {Math.abs(stats.balanceChange).toFixed(1)}% from last month
          &amp;lt;/div&amp;gt;
        &amp;lt;/StatCard&amp;gt;

        &amp;lt;StatCard
          color={gradients.primary}
          iconColor={colors.primary}
          initial={{ opacity: 0, y: 30 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.4 }}
        &amp;gt;
          &amp;lt;div className="stat-header"&amp;gt;
            &amp;lt;BarChart3 size={20} /&amp;gt;
            &amp;lt;h3&amp;gt;Avg Transaction&amp;lt;/h3&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="stat-value"&amp;gt;${stats.avgTransaction.toLocaleString()}&amp;lt;/div&amp;gt;
          &amp;lt;div className="stat-change positive"&amp;gt;
            &amp;lt;Calendar size={16} /&amp;gt;
            {stats.transactionCount} transactions
          &amp;lt;/div&amp;gt;
        &amp;lt;/StatCard&amp;gt;
      &amp;lt;/StatsGrid&amp;gt;

      {/* Filters */}
      &amp;lt;FilterSection
        initial={{ opacity: 0, y: 30 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ delay: 0.5 }}
      &amp;gt;
        &amp;lt;div className="filter-header"&amp;gt;
          &amp;lt;Filter size={20} /&amp;gt;
          &amp;lt;h3&amp;gt;Filters &amp;amp; Controls&amp;lt;/h3&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;FiltersGrid&amp;gt;
          &amp;lt;FilterSelect 
            value={filters.type} 
            onChange={(e) =&amp;gt; handleFilterChange('type', e.target.value)}
          &amp;gt;
            &amp;lt;option value="ALL"&amp;gt;All Types&amp;lt;/option&amp;gt;
            &amp;lt;option value="DEPOSIT"&amp;gt;Deposits&amp;lt;/option&amp;gt;
            &amp;lt;option value="WITHDRAW"&amp;gt;Withdrawals&amp;lt;/option&amp;gt;
            &amp;lt;option value="TRANSFER"&amp;gt;Transfers&amp;lt;/option&amp;gt;
            &amp;lt;option value="LOAN"&amp;gt;Loans&amp;lt;/option&amp;gt;
          &amp;lt;/FilterSelect&amp;gt;

          &amp;lt;FilterSelect 
            value={filters.status} 
            onChange={(e) =&amp;gt; handleFilterChange('status', e.target.value)}
          &amp;gt;
            &amp;lt;option value="ALL"&amp;gt;All Status&amp;lt;/option&amp;gt;
            &amp;lt;option value="SUCCESS"&amp;gt;Success&amp;lt;/option&amp;gt;
            &amp;lt;option value="PENDING"&amp;gt;Pending&amp;lt;/option&amp;gt;
            &amp;lt;option value="FAILED"&amp;gt;Failed&amp;lt;/option&amp;gt;
          &amp;lt;/FilterSelect&amp;gt;

          &amp;lt;FilterSelect 
            value={filters.category} 
            onChange={(e) =&amp;gt; handleFilterChange('category', e.target.value)}
          &amp;gt;
            &amp;lt;option value="ALL"&amp;gt;All Categories&amp;lt;/option&amp;gt;
            &amp;lt;option value="Food &amp;amp; Dining"&amp;gt;Food &amp;amp; Dining&amp;lt;/option&amp;gt;
            &amp;lt;option value="Shopping"&amp;gt;Shopping&amp;lt;/option&amp;gt;
            &amp;lt;option value="Transportation"&amp;gt;Transportation&amp;lt;/option&amp;gt;
            &amp;lt;option value="Entertainment"&amp;gt;Entertainment&amp;lt;/option&amp;gt;
            &amp;lt;option value="Bills &amp;amp; Utilities"&amp;gt;Bills &amp;amp; Utilities&amp;lt;/option&amp;gt;
            &amp;lt;option value="Healthcare"&amp;gt;Healthcare&amp;lt;/option&amp;gt;
            &amp;lt;option value="Travel"&amp;gt;Travel&amp;lt;/option&amp;gt;
            &amp;lt;option value="Education"&amp;gt;Education&amp;lt;/option&amp;gt;
          &amp;lt;/FilterSelect&amp;gt;

          &amp;lt;DateInput
            type="date"
            placeholder="From Date"
            value={filters.dateFrom}
            onChange={(e) =&amp;gt; handleFilterChange('dateFrom', e.target.value)}
          /&amp;gt;

          &amp;lt;DateInput
            type="date"
            placeholder="To Date"
            value={filters.dateTo}
            onChange={(e) =&amp;gt; handleFilterChange('dateTo', e.target.value)}
          /&amp;gt;

          &amp;lt;AmountRangeContainer&amp;gt;
            &amp;lt;input
              type="number"
              placeholder="Min Amount"
              value={filters.amountMin}
              onChange={(e) =&amp;gt; handleFilterChange('amountMin', e.target.value)}
            /&amp;gt;
            &amp;lt;span&amp;gt;-&amp;lt;/span&amp;gt;
            &amp;lt;input
              type="number"
              placeholder="Max Amount"
              value={filters.amountMax}
              onChange={(e) =&amp;gt; handleFilterChange('amountMax', e.target.value)}
            /&amp;gt;
          &amp;lt;/AmountRangeContainer&amp;gt;
        &amp;lt;/FiltersGrid&amp;gt;

        &amp;lt;ButtonGroup&amp;gt;
          &amp;lt;Button onClick={resetFilters}&amp;gt;
            &amp;lt;X size={16} /&amp;gt;
            Clear Filters
          &amp;lt;/Button&amp;gt;
          &amp;lt;Button onClick={refreshData}&amp;gt;
            &amp;lt;RefreshCw size={16} /&amp;gt;
            Refresh Data
          &amp;lt;/Button&amp;gt;
          &amp;lt;Button variant="primary" onClick={exportData}&amp;gt;
            &amp;lt;Download size={16} /&amp;gt;
            Export Data
          &amp;lt;/Button&amp;gt;
        &amp;lt;/ButtonGroup&amp;gt;
      &amp;lt;/FilterSection&amp;gt;

      {/* Charts */}
      &amp;lt;ChartsGrid&amp;gt;
        {/* Time Series Chart */}
        &amp;lt;ChartContainer
          fullWidth
          initial={{ opacity: 0, y: 30 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.6 }}
        &amp;gt;
          &amp;lt;div className="chart-header"&amp;gt;
            &amp;lt;h3&amp;gt;Financial Flow Over Time&amp;lt;/h3&amp;gt;
            &amp;lt;div className="chart-controls"&amp;gt;
              &amp;lt;ToggleButton
                active={chartView.timeChart === 'line'}
                onClick={() =&amp;gt; setChartView(prev =&amp;gt; ({...prev, timeChart: 'line'}))}
              &amp;gt;
                Line
              &amp;lt;/ToggleButton&amp;gt;
              &amp;lt;ToggleButton
                active={chartView.timeChart === 'area'}
                onClick={() =&amp;gt; setChartView(prev =&amp;gt; ({...prev, timeChart: 'area'}))}
              &amp;gt;
                Area
              &amp;lt;/ToggleButton&amp;gt;
              &amp;lt;ToggleButton
                active={chartView.showBalance}
                onClick={() =&amp;gt; setChartView(prev =&amp;gt; ({...prev, showBalance: !prev.showBalance}))}
              &amp;gt;
                {chartView.showBalance ? &amp;lt;Eye size={14} /&amp;gt; : &amp;lt;EyeOff size={14} /&amp;gt;}
                Balance
              &amp;lt;/ToggleButton&amp;gt;
            &amp;lt;/div&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="chart-wrapper"&amp;gt;
            &amp;lt;ResponsiveContainer width="100%" height="100%"&amp;gt;
              {chartView.timeChart === 'line' ? (
                &amp;lt;LineChart data={timeSeriesData}&amp;gt;
                  &amp;lt;CartesianGrid strokeDasharray="3 3" stroke={colors.border} /&amp;gt;
                  &amp;lt;XAxis dataKey="date" stroke={colors.textMuted} /&amp;gt;
                  &amp;lt;YAxis stroke={colors.textMuted} /&amp;gt;
                  &amp;lt;Tooltip content={&amp;lt;CustomTooltip /&amp;gt;} /&amp;gt;
                  &amp;lt;Legend /&amp;gt;
                  &amp;lt;Line 
                    type="monotone" 
                    dataKey="income" 
                    stroke={colors.success} 
                    strokeWidth={3}
                    dot={{ fill: colors.success, strokeWidth: 2, r: 4 }}
                    name="Income"
                  /&amp;gt;
                  &amp;lt;Line 
                    type="monotone" 
                    dataKey="expenses" 
                    stroke={colors.error} 
                    strokeWidth={3}
                    dot={{ fill: colors.error, strokeWidth: 2, r: 4 }}
                    name="Expenses"
                  /&amp;gt;
                  {chartView.showBalance &amp;amp;&amp;amp; (
                    &amp;lt;Line 
                      type="monotone" 
                      dataKey="balance" 
                      stroke={colors.primary} 
                      strokeWidth={3}
                      dot={{ fill: colors.primary, strokeWidth: 2, r: 4 }}
                      name="Running Balance"
                    /&amp;gt;
                  )}
                &amp;lt;/LineChart&amp;gt;
              ) : (
                &amp;lt;AreaChart data={timeSeriesData}&amp;gt;
                  &amp;lt;CartesianGrid strokeDasharray="3 3" stroke={colors.border} /&amp;gt;
                  &amp;lt;XAxis dataKey="date" stroke={colors.textMuted} /&amp;gt;
                  &amp;lt;YAxis stroke={colors.textMuted} /&amp;gt;
                  &amp;lt;Tooltip content={&amp;lt;CustomTooltip /&amp;gt;} /&amp;gt;
                  &amp;lt;Legend /&amp;gt;
                  &amp;lt;Area 
                    type="monotone" 
                    dataKey="income" 
                    stackId="1"
                    stroke={colors.success} 
                    fill={colors.success}
                    fillOpacity={0.6}
                    name="Income"
                  /&amp;gt;
                  &amp;lt;Area 
                    type="monotone" 
                    dataKey="expenses" 
                    stackId="2"
                    stroke={colors.error} 
                    fill={colors.error}
                    fillOpacity={0.6}
                    name="Expenses"
                  /&amp;gt;
                  {chartView.showBalance &amp;amp;&amp;amp; (
                    &amp;lt;Area 
                      type="monotone" 
                      dataKey="balance" 
                      stroke={colors.primary} 
                      fill={colors.primary}
                      fillOpacity={0.3}
                      name="Running Balance"
                    /&amp;gt;
                  )}
                &amp;lt;/AreaChart&amp;gt;
              )}
            &amp;lt;/ResponsiveContainer&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/ChartContainer&amp;gt;

        {/* Category Breakdown */}
        &amp;lt;ChartContainer
          initial={{ opacity: 0, y: 30 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.7 }}
        &amp;gt;
          &amp;lt;div className="chart-header"&amp;gt;
            &amp;lt;h3&amp;gt;Expenses by Category&amp;lt;/h3&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="chart-wrapper"&amp;gt;
            &amp;lt;ResponsiveContainer width="100%" height="100%"&amp;gt;
              &amp;lt;RechartsPieChart&amp;gt;
                &amp;lt;Pie
                  data={categoryData}
                  cx="50%"
                  cy="50%"
                  innerRadius={60}
                  outerRadius={100}
                  paddingAngle={5}
                  dataKey="value"
                &amp;gt;
                  {categoryData.map((entry, index) =&amp;gt; (
                    &amp;lt;Cell key={`cell-${index}`} fill={pieColors[index % pieColors.length]} /&amp;gt;
                  ))}
                &amp;lt;/Pie&amp;gt;
                &amp;lt;Tooltip content={&amp;lt;CustomTooltip /&amp;gt;} /&amp;gt;
                &amp;lt;Legend /&amp;gt;
              &amp;lt;/RechartsPieChart&amp;gt;
            &amp;lt;/ResponsiveContainer&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/ChartContainer&amp;gt;

        {/* Transaction Types */}
        &amp;lt;ChartContainer
          initial={{ opacity: 0, y: 30 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.8 }}
        &amp;gt;
          &amp;lt;div className="chart-header"&amp;gt;
            &amp;lt;h3&amp;gt;Transaction Types&amp;lt;/h3&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;div className="chart-wrapper"&amp;gt;
            &amp;lt;ResponsiveContainer width="100%" height="100%"&amp;gt;
              &amp;lt;BarChart data={typeData}&amp;gt;
                &amp;lt;CartesianGrid strokeDasharray="3 3" stroke={colors.border} /&amp;gt;
                &amp;lt;XAxis dataKey="name" stroke={colors.textMuted} /&amp;gt;
                &amp;lt;YAxis stroke={colors.textMuted} /&amp;gt;
                &amp;lt;Tooltip content={&amp;lt;CustomTooltip /&amp;gt;} /&amp;gt;
                &amp;lt;Bar dataKey="value" fill={colors.primary} radius={[8, 8, 0, 0]} /&amp;gt;
              &amp;lt;/BarChart&amp;gt;
            &amp;lt;/ResponsiveContainer&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/ChartContainer&amp;gt;
      &amp;lt;/ChartsGrid&amp;gt;

      {/* Recent Transactions Table */}
      &amp;lt;ChartContainer
        initial={{ opacity: 0, y: 30 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ delay: 0.9 }}
      &amp;gt;
        &amp;lt;div className="chart-header"&amp;gt;
          &amp;lt;h3&amp;gt;Recent Transactions&amp;lt;/h3&amp;gt;
          &amp;lt;div className="chart-controls"&amp;gt;
            &amp;lt;span style={{ fontSize: '14px', color: colors.textMuted }}&amp;gt;
              Showing {Math.min(10, filteredTransactions.length)} of {filteredTransactions.length} transactions
            &amp;lt;/span&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;div style={{ overflowX: 'auto' }}&amp;gt;
          &amp;lt;table style={{ width: '100%', borderCollapse: 'separate', borderSpacing: 0 }}&amp;gt;
            &amp;lt;thead&amp;gt;
              &amp;lt;tr style={{ background: gradients.primary }}&amp;gt;
                &amp;lt;th style={{ padding: spacing.lg, color: 'white', fontWeight: '600', fontSize: '14px', textAlign: 'left' }}&amp;gt;Date&amp;lt;/th&amp;gt;
                &amp;lt;th style={{ padding: spacing.lg, color: 'white', fontWeight: '600', fontSize: '14px', textAlign: 'left' }}&amp;gt;Description&amp;lt;/th&amp;gt;
                &amp;lt;th style={{ padding: spacing.lg, color: 'white', fontWeight: '600', fontSize: '14px', textAlign: 'left' }}&amp;gt;Category&amp;lt;/th&amp;gt;
                &amp;lt;th style={{ padding: spacing.lg, color: 'white', fontWeight: '600', fontSize: '14px', textAlign: 'left' }}&amp;gt;Type&amp;lt;/th&amp;gt;
                &amp;lt;th style={{ padding: spacing.lg, color: 'white', fontWeight: '600', fontSize: '14px', textAlign: 'left' }}&amp;gt;Status&amp;lt;/th&amp;gt;
                &amp;lt;th style={{ padding: spacing.lg, color: 'white', fontWeight: '600', fontSize: '14px', textAlign: 'right' }}&amp;gt;Amount&amp;lt;/th&amp;gt;
              &amp;lt;/tr&amp;gt;
            &amp;lt;/thead&amp;gt;
            &amp;lt;tbody&amp;gt;
              {filteredTransactions.slice(0, 10).map((transaction, index) =&amp;gt; (
                &amp;lt;tr 
                  key={transaction.id}
                  style={{ 
                    background: index % 2 === 0 ? 'rgba(248, 250, 252, 0.5)' : 'transparent',
                    borderBottom: '1px solid rgba(226, 232, 240, 0.5)'
                  }}
                &amp;gt;
                  &amp;lt;td style={{ padding: spacing.lg, color: colors.textSecondary, fontWeight: '500' }}&amp;gt;
                    {new Date(transaction.date).toLocaleDateString()}
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td style={{ padding: spacing.lg, color: colors.text, fontWeight: '600' }}&amp;gt;
                    {transaction.description}
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td style={{ padding: spacing.lg, color: colors.textSecondary }}&amp;gt;
                    {transaction.category}
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td style={{ padding: spacing.lg }}&amp;gt;
                    &amp;lt;TypeBadge type={transaction.type}&amp;gt;
                      {transaction.type}
                    &amp;lt;/TypeBadge&amp;gt;
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td style={{ padding: spacing.lg }}&amp;gt;
                    &amp;lt;StatusBadge status={transaction.status}&amp;gt;
                      {transaction.status}
                    &amp;lt;/StatusBadge&amp;gt;
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td style={{ 
                    padding: spacing.lg, 
                    textAlign: 'right', 
                    fontWeight: '700',
                    color: transaction.amount &amp;gt; 0 ? colors.success : colors.error
                  }}&amp;gt;
                    {transaction.amount &amp;gt; 0 ? '+' : ''}${transaction.amount.toLocaleString()}
                  &amp;lt;/td&amp;gt;
                &amp;lt;/tr&amp;gt;
              ))}
            &amp;lt;/tbody&amp;gt;
          &amp;lt;/table&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/ChartContainer&amp;gt;
    &amp;lt;/Container&amp;gt;
  );
};

// Styled badge components
const StatusBadge = styled.span`
  padding: 6px ${spacing.md};
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;

  ${props =&amp;gt; props.status === 'SUCCESS' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(72, 187, 120, 0.2), rgba(56, 178, 172, 0.2));
    color: ${colors.success};
    border: 1px solid rgba(72, 187, 120, 0.3);
  `}

  ${props =&amp;gt; props.status === 'PENDING' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(255, 193, 7, 0.2), rgba(255, 152, 0, 0.2));
    color: ${colors.warning};
    border: 1px solid rgba(255, 193, 7, 0.3);
  `}

  ${props =&amp;gt; props.status === 'FAILED' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(255, 107, 107, 0.2), rgba(238, 90, 82, 0.2));
    color: ${colors.error};
    border: 1px solid rgba(255, 107, 107, 0.3);
  `}
`;

const TypeBadge = styled.span`
  padding: 6px ${spacing.md};
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;

  ${props =&amp;gt; props.type === 'DEPOSIT' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(72, 187, 120, 0.2), rgba(56, 178, 172, 0.2));
    color: ${colors.success};
    border: 1px solid rgba(72, 187, 120, 0.3);
  `}

  ${props =&amp;gt; props.type === 'WITHDRAW' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(255, 107, 107, 0.2), rgba(238, 90, 82, 0.2));
    color: ${colors.error};
    border: 1px solid rgba(255, 107, 107, 0.3);
  `}

  ${props =&amp;gt; props.type === 'TRANSFER' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(102, 126, 234, 0.2), rgba(118, 75, 162, 0.2));
    color: ${colors.primary};
    border: 1px solid rgba(102, 126, 234, 0.3);
  `}

  ${props =&amp;gt; props.type === 'LOAN' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(255, 193, 7, 0.2), rgba(255, 152, 0, 0.2));
    color: ${colors.warning};
    border: 1px solid rgba(255, 193, 7, 0.3);
  `}
`;

export default BankingAnalyticsDashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>mvt-redesigned</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Mon, 30 Jun 2025 11:55:34 +0000</pubDate>
      <link>https://dev.to/nebula_3108/mvt-redesigned-4dj2</link>
      <guid>https://dev.to/nebula_3108/mvt-redesigned-4dj2</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect, useCallback } from 'react';
import { useUnleashContext, useUnleashClient } from '@unleash/proxy-client-react';
import styled, { keyframes } from 'styled-components';

// --- Simple Animations ---
const fadeIn = keyframes`
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
`;

const spin = keyframes`
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
`;

// --- Layout Components ---
const Container = styled.div`
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  min-height: 100vh;
  padding: 2rem 1rem;
`;

const MainContent = styled.div`
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 2rem;
`;

const Card = styled.div`
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  border-radius: 20px;
  padding: 2rem;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  animation: ${fadeIn} 0.6s ease-out;
`;

// --- Header Components ---
const Header = styled.div`
  text-align: center;
  margin-bottom: 1rem;
`;

const Title = styled.h1`
  font-size: 2.5rem;
  font-weight: 700;
  background: linear-gradient(135deg, #667eea, #764ba2);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin-bottom: 0.5rem;
`;

const Subtitle = styled.p`
  font-size: 1.1rem;
  color: #64748b;
  font-weight: 400;
`;

// --- Form Components ---
const ConfigSection = styled.div`
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.5rem;
  align-items: end;

  @media (max-width: 768px) {
    grid-template-columns: 1fr;
  }
`;

const InputGroup = styled.div`
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
`;

const Label = styled.label`
  font-size: 0.9rem;
  font-weight: 600;
  color: #374151;
`;

const Input = styled.input`
  padding: 0.875rem 1rem;
  border: 2px solid #e5e7eb;
  border-radius: 12px;
  font-size: 1rem;
  transition: all 0.2s ease;
  background: white;

  &amp;amp;:focus {
    outline: none;
    border-color: #667eea;
    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
  }
`;

const Button = styled.button`
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.875rem 1.5rem;
  background: linear-gradient(135deg, #667eea, #764ba2);
  color: white;
  border: none;
  border-radius: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);

  &amp;amp;:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
  }

  &amp;amp;:disabled {
    opacity: 0.7;
    cursor: not-allowed;
    transform: none;
  }
`;

const Spinner = styled.div`
  width: 18px;
  height: 18px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top: 2px solid white;
  border-radius: 50%;
  animation: ${spin} 1s linear infinite;
`;

// --- Status Components ---
const StatusBanner = styled.div`
  background: linear-gradient(135deg, #3b82f6, #1d4ed8);
  color: white;
  padding: 1rem 1.5rem;
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  animation: ${fadeIn} 0.3s ease-out;
`;

const StatusSpinner = styled(Spinner)`
  border-color: rgba(255, 255, 255, 0.3);
  border-top-color: white;
`;

// --- Stats Components ---
const StatsGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.5rem;
`;

const StatCard = styled(Card)`
  text-align: center;
  padding: 1.5rem;
  background: linear-gradient(135deg, #f8fafc, #e2e8f0);
`;

const StatValue = styled.div`
  font-size: 2.5rem;
  font-weight: 800;
  color: ${props =&amp;gt; props.color || '#1e293b'};
  margin-bottom: 0.5rem;
`;

const StatLabel = styled.div`
  font-size: 0.9rem;
  color: #64748b;
  font-weight: 500;
`;

// --- Variant Display Components ---
const VariantGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.5rem;
  margin-top: 1.5rem;
`;

const VariantCard = styled.div`
  background: linear-gradient(135deg, #f1f5f9, #e2e8f0);
  border-radius: 16px;
  padding: 1.5rem;
  text-align: center;
  border: 2px solid rgba(255, 255, 255, 0.5);
`;

const VariantName = styled.h4`
  font-size: 1.1rem;
  font-weight: 600;
  color: #334155;
  margin-bottom: 1rem;
`;

const SimulatedButton = styled.button`
  padding: 0.75rem 1.5rem;
  border-radius: 10px;
  font-weight: 600;
  color: white;
  background: ${props =&amp;gt; props.color || '#3b82f6'};
  border: none;
  cursor: pointer;
  transition: transform 0.2s ease;

  &amp;amp;:hover {
    transform: scale(1.05);
  }
`;

const VariantDescription = styled.p`
  font-size: 0.85rem;
  color: #64748b;
  margin-top: 0.75rem;
`;

// --- Progress Components ---
const ProgressContainer = styled.div`
  margin: 1.5rem 0;
`;

const ProgressBar = styled.div`
  width: 100%;
  height: 8px;
  background: #e2e8f0;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
`;

const ProgressSegment = styled.div`
  height: 100%;
  background: ${props =&amp;gt; props.color || '#3b82f6'};
  width: ${props =&amp;gt; props.percentage}%;
  transition: width 0.5s ease;
`;

const ProgressLabels = styled.div`
  display: flex;
  justify-content: space-between;
  margin-top: 0.75rem;
  font-size: 0.85rem;
  color: #64748b;
`;

// --- Table Components ---
const TableContainer = styled.div`
  overflow-x: auto;
  border-radius: 12px;
  border: 1px solid #e5e7eb;
`;

const Table = styled.table`
  width: 100%;
  border-collapse: collapse;
  background: white;
`;

const TableHeader = styled.th`
  padding: 1rem 1.5rem;
  text-align: left;
  background: #f8fafc;
  font-weight: 600;
  color: #374151;
  font-size: 0.875rem;
  border-bottom: 1px solid #e5e7eb;
`;

const TableRow = styled.tr`
  &amp;amp;:nth-child(even) {
    background: #f9fafb;
  }

  &amp;amp;:hover {
    background: #f3f4f6;
  }
`;

const TableCell = styled.td`
  padding: 1rem 1.5rem;
  border-bottom: 1px solid #e5e7eb;
  font-size: 0.9rem;
  color: #374151;
`;

// --- User Display Components ---
const UserInfo = styled.div`
  display: flex;
  align-items: center;
  gap: 0.75rem;
`;

const UserAvatar = styled.div`
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: linear-gradient(135deg, #667eea, #764ba2);
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: 600;
  font-size: 0.85rem;
`;

const UserDetails = styled.div``;

const UserName = styled.div`
  font-weight: 500;
  color: #1f2937;
`;

const UserEmail = styled.div`
  font-size: 0.8rem;
  color: #6b7280;
`;

// --- Badge Components ---
const Badge = styled.span`
  padding: 0.25rem 0.75rem;
  border-radius: 20px;
  font-size: 0.75rem;
  font-weight: 600;
  background: ${props =&amp;gt; {
    switch (props.type) {
      case 'Premium': return 'linear-gradient(135deg, #fbbf24, #f59e0b)';
      case 'Gold': return 'linear-gradient(135deg, #3b82f6, #1d4ed8)';
      case 'Standard': return 'linear-gradient(135deg, #8b5cf6, #7c3aed)';
      default: return '#e5e7eb';
    }
  }};
  color: ${props =&amp;gt; props.type ? 'white' : '#374151'};
`;

const StatusBadge = styled.span`
  padding: 0.25rem 0.75rem;
  border-radius: 20px;
  font-size: 0.75rem;
  font-weight: 600;
  background: ${props =&amp;gt; {
    switch (props.type) {
      case 'enabled': return 'linear-gradient(135deg, #10b981, #059669)';
      case 'disabled': return 'linear-gradient(135deg, #ef4444, #dc2626)';
      case 'error': return 'linear-gradient(135deg, #ef4444, #dc2626)';
      default: return '#e5e7eb';
    }
  }};
  color: ${props =&amp;gt; props.type ? 'white' : '#374151'};
`;

// --- Empty State Components ---
const EmptyState = styled(Card)`
  text-align: center;
  padding: 3rem 2rem;
`;

const EmptyIcon = styled.div`
  font-size: 4rem;
  margin-bottom: 1rem;
`;

const EmptyTitle = styled.h3`
  font-size: 1.5rem;
  font-weight: 600;
  color: #1f2937;
  margin-bottom: 0.5rem;
`;

const EmptyText = styled.p`
  color: #6b7280;
  margin-bottom: 1rem;
`;

const EmptyNote = styled.p`
  font-size: 0.85rem;
  color: #9ca3af;
  font-style: italic;
`;

const SectionTitle = styled.h2`
  font-size: 1.5rem;
  font-weight: 600;
  color: #1f2937;
  margin-bottom: 1rem;
`;

// --- Helper Functions ---
const generateRandomId = () =&amp;gt; {
  return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
};

const generateDummyUsers = (count = 100) =&amp;gt; {
  return Array.from({ length: count }, (_, i) =&amp;gt; ({
    id: generateRandomId(),
    name: `Test User ${i + 1}`,
    email: `user${i + 1}@example.com`,
    accountType: i % 3 === 0 ? 'Premium' : i % 2 === 0 ? 'Gold' : 'Standard',
  }));
};

// --- Main Component ---
const ABTestSimulator = () =&amp;gt; {
  const [testResults, setTestResults] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [currentTestingUser, setCurrentTestingUser] = useState('');
  const [featureFlagName, setFeatureFlagName] = useState('ab-test-variant-feature');
  const updateContext = useUnleashContext();
  const unleashClient = useUnleashClient();

  const expectedVariants = [
    { name: 'control-cta', buttonText: 'Learn More', buttonColor: '#3b82f6', description: 'Standard blue button' },
    { name: 'variant-a-cta', buttonText: 'Discover Now', buttonColor: '#10b981', description: 'Green button for discovery' },
    { name: 'variant-b-cta', buttonText: 'Explore Features', buttonColor: '#ef4444', description: 'Red button to explore' },
  ];

  const dummyUsers = generateDummyUsers(100);

  const runABCTest = useCallback(async () =&amp;gt; {
    setIsLoading(true);
    setTestResults([]);
    const results = [];

    for (let i = 0; i &amp;lt; dummyUsers.length; i++) {
      const user = dummyUsers[i];
      setCurrentTestingUser(user.name);

      try {
        await updateContext({
          userId: user.id,
        });

        await new Promise((resolve) =&amp;gt; setTimeout(resolve, 100));

        const variant = unleashClient.getVariant(featureFlagName);

        results.push({
          ...user,
          variantName: variant.name,
          variantPayload: variant.payload ? JSON.parse(variant.payload.value) : null,
          testTimestamp: new Date().toLocaleTimeString(),
          flagEnabled: variant.enabled,
        });
      } catch (error) {
        console.error(`Error testing user ${user.id}:`, error);
        results.push({
          ...user,
          variantName: 'error',
          variantPayload: null,
          testTimestamp: new Date().toLocaleTimeString(),
          flagEnabled: false,
          error: true,
        });
      }
    }

    setTestResults(results);
    setCurrentTestingUser('');
    setIsLoading(false);
  }, [dummyUsers, featureFlagName, updateContext, unleashClient]);

  const calculateStats = useCallback(() =&amp;gt; {
    if (testResults.length === 0) {
      return {
        total: 0,
        variants: expectedVariants.map(v =&amp;gt; ({
          name: v.name,
          count: 0,
          percentage: 0,
          color: v.buttonColor,
          buttonText: v.buttonText,
        })),
        totalEnabled: 0,
        totalEnabledPercentage: 0,
      };
    }

    const variantCounts = {};
    let totalEnabled = 0;

    testResults.forEach((result) =&amp;gt; {
      if (result.flagEnabled) {
        totalEnabled++;
        variantCounts[result.variantName] = (variantCounts[result.variantName] || 0) + 1;
      }
    });

    const stats = expectedVariants.map(v =&amp;gt; {
      const count = variantCounts[v.name] || 0;
      const percentage = totalEnabled &amp;gt; 0 ? Math.round((count / totalEnabled) * 100) : 0;
      return {
        name: v.name,
        count,
        percentage,
        color: v.buttonColor,
        buttonText: v.buttonText,
      };
    });

    return {
      total: testResults.length,
      variants: stats,
      totalEnabled: totalEnabled,
      totalEnabledPercentage: testResults.length &amp;gt; 0 ? Math.round((totalEnabled / testResults.length) * 100) : 0,
    };
  }, [testResults, expectedVariants]);

  const stats = calculateStats();

  return (
    &amp;lt;Container&amp;gt;
      &amp;lt;MainContent&amp;gt;
        {/* Header */}
        &amp;lt;Card&amp;gt;
          &amp;lt;Header&amp;gt;
            &amp;lt;Title&amp;gt;✨ Unleash A/B/C Test Simulator&amp;lt;/Title&amp;gt;
            &amp;lt;Subtitle&amp;gt;
              Simulate multivariate testing with real Unleash flag variants and observe distribution.
            &amp;lt;/Subtitle&amp;gt;
          &amp;lt;/Header&amp;gt;
        &amp;lt;/Card&amp;gt;

        {/* Configuration */}
        &amp;lt;Card&amp;gt;
          &amp;lt;SectionTitle&amp;gt;Configuration&amp;lt;/SectionTitle&amp;gt;
          &amp;lt;ConfigSection&amp;gt;
            &amp;lt;InputGroup&amp;gt;
              &amp;lt;Label htmlFor="flagName"&amp;gt;Feature Flag Name&amp;lt;/Label&amp;gt;
              &amp;lt;Input
                id="flagName"
                type="text"
                value={featureFlagName}
                onChange={(e) =&amp;gt; setFeatureFlagName(e.target.value)}
                placeholder="e.g., ab-test-variant-feature"
              /&amp;gt;
            &amp;lt;/InputGroup&amp;gt;
            &amp;lt;Button onClick={runABCTest} disabled={isLoading}&amp;gt;
              {isLoading ? (
                &amp;lt;&amp;gt;
                  &amp;lt;Spinner /&amp;gt;
                  Testing...
                &amp;lt;/&amp;gt;
              ) : (
                &amp;lt;&amp;gt;🚀 Start A/B/C Test ({dummyUsers.length} Users)&amp;lt;/&amp;gt;
              )}
            &amp;lt;/Button&amp;gt;
          &amp;lt;/ConfigSection&amp;gt;
        &amp;lt;/Card&amp;gt;

        {/* Status */}
        {isLoading &amp;amp;&amp;amp; (
          &amp;lt;StatusBanner&amp;gt;
            &amp;lt;StatusSpinner /&amp;gt;
            &amp;lt;span&amp;gt;Currently testing: {currentTestingUser}&amp;lt;/span&amp;gt;
          &amp;lt;/StatusBanner&amp;gt;
        )}

        {/* Variant Preview */}
        &amp;lt;Card&amp;gt;
          &amp;lt;SectionTitle&amp;gt;Simulated Variant Preview&amp;lt;/SectionTitle&amp;gt;
          &amp;lt;p style={{ color: '#64748b', fontSize: '0.9rem', marginBottom: '1rem' }}&amp;gt;
            These are the expected UI variations based on the payload configured in Unleash.
          &amp;lt;/p&amp;gt;
          &amp;lt;VariantGrid&amp;gt;
            {expectedVariants.map((variant) =&amp;gt; (
              &amp;lt;VariantCard key={variant.name}&amp;gt;
                &amp;lt;VariantName&amp;gt;{variant.name}&amp;lt;/VariantName&amp;gt;
                &amp;lt;SimulatedButton color={variant.buttonColor}&amp;gt;
                  {variant.buttonText}
                &amp;lt;/SimulatedButton&amp;gt;
                &amp;lt;VariantDescription&amp;gt;{variant.description}&amp;lt;/VariantDescription&amp;gt;
              &amp;lt;/VariantCard&amp;gt;
            ))}
          &amp;lt;/VariantGrid&amp;gt;
        &amp;lt;/Card&amp;gt;

        {/* Statistics */}
        {testResults.length &amp;gt; 0 &amp;amp;&amp;amp; (
          &amp;lt;&amp;gt;
            &amp;lt;StatsGrid&amp;gt;
              &amp;lt;StatCard&amp;gt;
                &amp;lt;StatValue color="#3b82f6"&amp;gt;{stats.total}&amp;lt;/StatValue&amp;gt;
                &amp;lt;StatLabel&amp;gt;Total Users Tested&amp;lt;/StatLabel&amp;gt;
              &amp;lt;/StatCard&amp;gt;
              &amp;lt;StatCard&amp;gt;
                &amp;lt;StatValue color="#10b981"&amp;gt;{stats.totalEnabled}&amp;lt;/StatValue&amp;gt;
                &amp;lt;StatLabel&amp;gt;Flag Enabled Users&amp;lt;/StatLabel&amp;gt;
              &amp;lt;/StatCard&amp;gt;
              &amp;lt;StatCard&amp;gt;
                &amp;lt;StatValue color="#8b5cf6"&amp;gt;{stats.totalEnabledPercentage}%&amp;lt;/StatValue&amp;gt;
                &amp;lt;StatLabel&amp;gt;Total Rollout Percentage&amp;lt;/StatLabel&amp;gt;
              &amp;lt;/StatCard&amp;gt;
            &amp;lt;/StatsGrid&amp;gt;

            &amp;lt;Card&amp;gt;
              &amp;lt;SectionTitle&amp;gt;Variant Distribution&amp;lt;/SectionTitle&amp;gt;
              &amp;lt;ProgressContainer&amp;gt;
                &amp;lt;ProgressBar&amp;gt;
                  {stats.variants.map((variantStat) =&amp;gt; (
                    &amp;lt;ProgressSegment
                      key={variantStat.name}
                      percentage={variantStat.percentage}
                      color={variantStat.color}
                    /&amp;gt;
                  ))}
                &amp;lt;/ProgressBar&amp;gt;
                &amp;lt;ProgressLabels&amp;gt;
                  {stats.variants.map((variantStat) =&amp;gt; (
                    &amp;lt;span key={`label-${variantStat.name}`} style={{ color: variantStat.color }}&amp;gt;
                      {variantStat.name} ({variantStat.count})
                    &amp;lt;/span&amp;gt;
                  ))}
                &amp;lt;/ProgressLabels&amp;gt;
              &amp;lt;/ProgressContainer&amp;gt;
            &amp;lt;/Card&amp;gt;
          &amp;lt;/&amp;gt;
        )}

        {/* Results Table */}
        {testResults.length &amp;gt; 0 &amp;amp;&amp;amp; (
          &amp;lt;Card style={{ padding: 0 }}&amp;gt;
            &amp;lt;div style={{ padding: '2rem 2rem 1rem' }}&amp;gt;
              &amp;lt;SectionTitle style={{ margin: 0 }}&amp;gt;Detailed Test Results&amp;lt;/SectionTitle&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;TableContainer&amp;gt;
              &amp;lt;Table&amp;gt;
                &amp;lt;thead&amp;gt;
                  &amp;lt;tr&amp;gt;
                    &amp;lt;TableHeader&amp;gt;User&amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableHeader&amp;gt;Account Type&amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableHeader&amp;gt;Assigned Variant&amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableHeader&amp;gt;Flag Enabled&amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableHeader&amp;gt;Test Time&amp;lt;/TableHeader&amp;gt;
                  &amp;lt;/tr&amp;gt;
                &amp;lt;/thead&amp;gt;
                &amp;lt;tbody&amp;gt;
                  {testResults.map((result) =&amp;gt; (
                    &amp;lt;TableRow key={result.id}&amp;gt;
                      &amp;lt;TableCell&amp;gt;
                        &amp;lt;UserInfo&amp;gt;
                          &amp;lt;UserAvatar&amp;gt;
                            {result.name
                              .split(' ')
                              .map((n) =&amp;gt; n[0])
                              .join('')
                              .slice(0, 2)}
                          &amp;lt;/UserAvatar&amp;gt;
                          &amp;lt;UserDetails&amp;gt;
                            &amp;lt;UserName&amp;gt;{result.name}&amp;lt;/UserName&amp;gt;
                            &amp;lt;UserEmail&amp;gt;{result.email}&amp;lt;/UserEmail&amp;gt;
                          &amp;lt;/UserDetails&amp;gt;
                        &amp;lt;/UserInfo&amp;gt;
                      &amp;lt;/TableCell&amp;gt;
                      &amp;lt;TableCell&amp;gt;
                        &amp;lt;Badge type={result.accountType}&amp;gt;
                          {result.accountType}
                        &amp;lt;/Badge&amp;gt;
                      &amp;lt;/TableCell&amp;gt;
                      &amp;lt;TableCell&amp;gt;
                        {result.error ? (
                          &amp;lt;StatusBadge type="error"&amp;gt;❌ Error&amp;lt;/StatusBadge&amp;gt;
                        ) : result.flagEnabled ? (
                          &amp;lt;StatusBadge type="enabled"&amp;gt;{result.variantName}&amp;lt;/StatusBadge&amp;gt;
                        ) : (
                          &amp;lt;StatusBadge type="disabled"&amp;gt;N/A (Disabled)&amp;lt;/StatusBadge&amp;gt;
                        )}
                      &amp;lt;/TableCell&amp;gt;
                      &amp;lt;TableCell&amp;gt;
                        {result.error ? (
                          &amp;lt;StatusBadge type="error"&amp;gt;❌ No&amp;lt;/StatusBadge&amp;gt;
                        ) : result.flagEnabled ? (
                          &amp;lt;StatusBadge type="enabled"&amp;gt;✅ Yes&amp;lt;/StatusBadge&amp;gt;
                        ) : (
                          &amp;lt;StatusBadge type="disabled"&amp;gt;❌ No&amp;lt;/StatusBadge&amp;gt;
                        )}
                      &amp;lt;/TableCell&amp;gt;
                      &amp;lt;TableCell&amp;gt;{result.testTimestamp}&amp;lt;/TableCell&amp;gt;
                    &amp;lt;/TableRow&amp;gt;
                  ))}
                &amp;lt;/tbody&amp;gt;
              &amp;lt;/Table&amp;gt;
            &amp;lt;/TableContainer&amp;gt;
          &amp;lt;/Card&amp;gt;
        )}

        {/* Empty State */}
        {testResults.length === 0 &amp;amp;&amp;amp; !isLoading &amp;amp;&amp;amp; (
          &amp;lt;EmptyState&amp;gt;
            &amp;lt;EmptyIcon&amp;gt;📊&amp;lt;/EmptyIcon&amp;gt;
            &amp;lt;EmptyTitle&amp;gt;Ready to Simulate A/B/C Tests&amp;lt;/EmptyTitle&amp;gt;
            &amp;lt;EmptyText&amp;gt;
              Enter your feature flag name and click "Start Test" to see how Unleash distributes users across variants.
            &amp;lt;/EmptyText&amp;gt;
            &amp;lt;EmptyNote&amp;gt;
              Ensure your flag "{featureFlagName}" is configured in Unleash with at least three variants and a gradual rollout strategy.
            &amp;lt;/EmptyNote&amp;gt;
          &amp;lt;/EmptyState&amp;gt;
        )}
      &amp;lt;/MainContent&amp;gt;
    &amp;lt;/Container&amp;gt;
  );
};

export default ABTestSimulator;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>mvt-testing</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Sun, 29 Jun 2025 15:13:39 +0000</pubDate>
      <link>https://dev.to/nebula_3108/mvt-testing-195p</link>
      <guid>https://dev.to/nebula_3108/mvt-testing-195p</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect, useCallback } from 'react';
import { useUnleashContext, useUnleashClient } from '@unleash/proxy-client-react';
import styled, { keyframes, css } from 'styled-components';

// --- Styled Components ---

const fadeIn = keyframes`
  from { opacity: 0; transform: translateY(-10px); }
  to { opacity: 1; transform: translateY(0); }
`;

const spin = keyframes`
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
`;

const Container = styled.div`
  font-family: 'Inter', sans-serif;
  background-color: #f8fafc; /* Tailwind gray-50 */
  min-height: 100vh;
  padding: 2rem;
  display: flex;
  justify-content: center;
  align-items: flex-start;
`;

const MaxWidthWrapper = styled.div`
  max-width: 960px;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
`;

const Card = styled.div`
  background-color: white;
  border-radius: 0.75rem; /* rounded-xl */
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); /* shadow-xl */
  padding: 1.5rem;
  border: 1px solid #e2e8f0; /* border-gray-200 */
`;

const Header = styled.div`
  text-align: center;
  margin-bottom: 1rem;
`;

const Title = styled.h1`
  font-size: 2.25rem; /* text-4xl */
  font-weight: 700; /* font-bold */
  color: #1a202c; /* gray-900 */
  margin-bottom: 0.5rem;
`;

const Subtitle = styled.p`
  font-size: 1.125rem; /* text-lg */
  color: #4a5568; /* gray-600 */
`;

const SectionTitle = styled.h2`
  font-size: 1.5rem; /* text-2xl */
  font-weight: 600; /* font-semibold */
  color: #2d3748; /* gray-800 */
  margin-bottom: 1rem;
`;

const ConfigPanel = styled.div`
  display: flex;
  flex-direction: column;
  gap: 1rem;
  @media (min-width: 640px) { /* sm */
    flex-direction: row;
    align-items: flex-end;
    justify-content: space-between;
  }
`;

const InputGroup = styled.div`
  flex-grow: 1;
`;

const Label = styled.label`
  display: block;
  font-size: 0.875rem; /* text-sm */
  font-weight: 500; /* font-medium */
  color: #2d3748; /* gray-700 */
  margin-bottom: 0.5rem;
`;

const Input = styled.input`
  width: 100%;
  padding: 0.75rem 1rem;
  border: 1px solid #cbd5e0; /* border-gray-300 */
  border-radius: 0.5rem; /* rounded-lg */
  font-size: 1rem;
  color: #2d3748;
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.05);
  &amp;amp;:focus {
    outline: none;
    border-color: #3b82f6; /* blue-500 */
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); /* ring-blue-300 */
  }
`;

const Button = styled.button`
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.5rem;
  background-color: #3b82f6; /* blue-500 */
  color: white;
  font-weight: 600; /* font-semibold */
  border-radius: 0.5rem; /* rounded-lg */
  border: none;
  cursor: pointer;
  transition: background-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); /* shadow-md */

  &amp;amp;:hover {
    background-color: #2563eb; /* blue-600 */
    box-shadow: 0 6px 8px -1px rgba(0, 0, 0, 0.15), 0 4px 6px -2px rgba(0, 0, 0, 0.08);
  }

  &amp;amp;:disabled {
    background-color: #9ca3af; /* gray-400 */
    cursor: not-allowed;
    box-shadow: none;
  }
`;

const Spinner = styled.div`
  border: 4px solid rgba(255, 255, 255, 0.3);
  border-top: 4px solid white;
  border-radius: 50%;
  width: 1.5rem;
  height: 1.5rem;
  animation: ${spin} 1s linear infinite;
`;

const StatusBanner = styled.div`
  background-color: #eff6ff; /* blue-50 */
  border: 1px solid #bfdbfe; /* blue-200 */
  color: #1e40af; /* blue-800 */
  padding: 0.75rem 1.5rem;
  border-radius: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: ${fadeIn} 0.5s ease-out;
`;

const StatusContent = styled.div`
  display: flex;
  align-items: center;
  gap: 0.75rem;
`;

const StatusSpinner = styled(Spinner)`
  border-color: rgba(30, 64, 175, 0.3);
  border-top-color: #1e40af;
  width: 1.25rem;
  height: 1.25rem;
`;

const StatusText = styled.p`
  font-size: 1rem;
  font-weight: 500;
`;

const StatsGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1rem;
`;

const StatCard = styled(Card)`
  padding: 1rem;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: #f0f9ff; /* blue-50 */
`;

const StatValue = styled.p`
  font-size: 2.5rem; /* text-5xl */
  font-weight: 700; /* font-bold */
  color: ${(props) =&amp;gt; props.color || '#1a202c'};
  line-height: 1;
  margin-bottom: 0.5rem;
`;

const StatLabel = styled.p`
  font-size: 0.875rem; /* text-sm */
  color: #4a5568; /* gray-600 */
  font-weight: 500;
`;

const ProgressSection = styled(Card)`
  padding: 1.5rem;
`;

const ProgressTitle = styled(SectionTitle)`
  margin-bottom: 1.5rem;
  text-align: center;
`;

const ProgressBarContainer = styled.div`
  width: 100%;
  background-color: #e2e8f0; /* gray-200 */
  border-radius: 9999px; /* rounded-full */
  height: 1.5rem;
  overflow: hidden;
  display: flex; /* To allow multiple bars */
`;

const ProgressBarSegment = styled.div`
  height: 100%;
  background-color: ${(props) =&amp;gt; props.color || '#3b82f6'};
  width: ${(props) =&amp;gt; props.percentage}%;
  transition: width 0.5s ease-out;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: 600;
  font-size: 0.875rem;
  text-shadow: 1px 1px 2px rgba(0,0,0,0.2);
`;

const ProgressLabels = styled.div`
  display: flex;
  justify-content: space-between;
  font-size: 0.875rem;
  color: #4a5568;
  margin-top: 0.5rem;
`;

const ProgressCenter = styled.span`
  text-align: center;
  flex-grow: 1;
`;

const ResultsCard = styled(Card)`
  padding: 0; /* Remove padding from card, table will handle it */
  overflow: hidden; /* For rounded corners on table */
`;

const ResultsHeader = styled.div`
  padding: 1.5rem;
  border-bottom: 1px solid #e2e8f0;
`;

const ResultsTitle = styled(SectionTitle)`
  margin-bottom: 0;
`;

const TableContainer = styled.div`
  overflow-x: auto;
  -webkit-overflow-scrolling: touch; /* For smooth scrolling on iOS */
`;

const Table = styled.table`
  width: 100%;
  border-collapse: collapse;
`;

const TableHead = styled.thead`
  background-color: #f8fafc; /* gray-50 */
`;

const TableHeader = styled.th`
  padding: 1rem 1.5rem;
  text-align: left;
  font-size: 0.875rem;
  font-weight: 600;
  color: #4a5568;
  text-transform: uppercase;
  letter-spacing: 0.05em;
`;

const TableRow = styled.tr`
  &amp;amp;:nth-child(even) {
    background-color: #f8fafc; /* gray-50 */
  }
  &amp;amp;:hover {
    background-color: #f0f4f8; /* slightly darker on hover */
  }
`;

const TableCell = styled.td`
  padding: 1rem 1.5rem;
  font-size: 0.9375rem;
  color: #2d3748;
  vertical-align: middle;
`;

const UserInfo = styled.div`
  display: flex;
  align-items: center;
  gap: 0.75rem;
`;

const UserAvatar = styled.div`
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background-color: #60a5fa; /* blue-400 */
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: 600;
  font-size: 0.875rem;
`;

const UserInitials = styled.span``;

const UserDetails = styled.div`
  display: flex;
  flex-direction: column;
`;

const UserName = styled.p`
  font-weight: 500;
`;

const UserEmail = styled.p`
  font-size: 0.8125rem; /* text-xs */
  color: #718096; /* gray-500 */
`;

const Badge = styled.span`
  display: inline-flex;
  padding: 0.25rem 0.75rem;
  border-radius: 9999px; /* rounded-full */
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: capitalize;
  ${(props) =&amp;gt; {
    switch (props.type) {
      case 'Premium':
        return css`
          background-color: #fef3c7; /* yellow-100 */
          color: #b45309; /* yellow-800 */
        `;
      case 'Gold':
        return css`
          background-color: #dbeafe; /* blue-100 */
          color: #1e40af; /* blue-800 */
        `;
      case 'Standard':
        return css`
          background-color: #e0e7ff; /* indigo-100 */
          color: #4338ca; /* indigo-800 */
        `;
      default:
        return css`
          background-color: #e2e8f0;
          color: #4a5568;
        `;
    }
  }}
`;

const StatusBadge = styled.span`
  display: inline-flex;
  padding: 0.25rem 0.75rem;
  border-radius: 9999px;
  font-size: 0.75rem;
  font-weight: 600;
  ${(props) =&amp;gt; {
    switch (props.type) {
      case 'enabled':
        return css`
          background-color: #dcfce7; /* green-100 */
          color: #16a34a; /* green-700 */
        `;
      case 'disabled':
        return css`
          background-color: #fee2e2; /* red-100 */
          color: #dc2626; /* red-700 */
        `;
      case 'error':
        return css`
          background-color: #fee2e2; /* red-100 */
          color: #dc2626; /* red-700 */
        `;
      default:
        return css`
          background-color: #e2e8f0;
          color: #4a5568;
        `;
    }
  }}
`;

const EmptyState = styled.div`
  text-align: center;
  padding: 3rem 1.5rem;
  background-color: white;
  border-radius: 0.75rem;
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
  border: 1px solid #e2e8f0;
  animation: ${fadeIn} 0.5s ease-out;
`;

const EmptyStateIcon = styled.span`
  font-size: 3rem;
  margin-bottom: 1rem;
  display: block;
`;

const EmptyStateTitle = styled.h3`
  font-size: 1.5rem;
  font-weight: 600;
  color: #2d3748;
  margin-bottom: 0.5rem;
`;

const EmptyStateText = styled.p`
  font-size: 1rem;
  color: #4a5568;
  margin-bottom: 1rem;
`;

const EmptyStateNote = styled.p`
  font-size: 0.875rem;
  color: #718096;
  font-style: italic;
`;

const VariantDisplaySection = styled(Card)`
  padding: 1.5rem;
`;

const VariantDisplayGrid = styled.div`
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1.5rem;
  margin-top: 1.5rem;
`;

const VariantCard = styled.div`
  background-color: #f0f9ff; /* blue-50 */
  border: 1px solid #bfdbfe; /* blue-200 */
  border-radius: 0.75rem;
  padding: 1.25rem;
  text-align: center;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
`;

const VariantName = styled.h4`
  font-size: 1.125rem;
  font-weight: 600;
  color: #1e40af; /* blue-800 */
  margin-bottom: 0.75rem;
`;

const SimulatedButton = styled.button`
  padding: 0.75rem 1.5rem;
  border-radius: 0.5rem;
  font-weight: 600;
  color: white;
  background-color: ${(props) =&amp;gt; props.color || '#3b82f6'};
  border: none;
  cursor: pointer;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
  transition: transform 0.1s ease-in-out, box-shadow 0.1s ease-in-out;

  &amp;amp;:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0,0,0,0.25);
  }
`;

const VariantDescription = styled.p`
  font-size: 0.875rem;
  color: #4a5568;
  margin-top: 0.75rem;
`;

// --- Helper Functions ---

const generateRandomId = () =&amp;gt; {
  return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
};

const generateDummyUsers = (count = 100) =&amp;gt; { // Increased default count for better stats
  return Array.from({ length: count }, (_, i) =&amp;gt; ({
    id: generateRandomId(),
    name: `Test User ${i + 1}`,
    email: `user${i + 1}@example.com`,
    accountType: i % 3 === 0 ? 'Premium' : i % 2 === 0 ? 'Gold' : 'Standard',
  }));
};

// --- Main Component ---

const ABTestSimulator = () =&amp;gt; {
  const [testResults, setTestResults] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [currentTestingUser, setCurrentTestingUser] = useState('');
  const [featureFlagName, setFeatureFlagName] = useState('ab-test-variant-feature'); // Default flag name
  const updateContext = useUnleashContext();
  const unleashClient = useUnleashClient();

  // Define expected variants for display purposes (these should match Unleash config)
  // In a real app, you might fetch these or have them configured.
  const expectedVariants = [
    { name: 'control-cta', buttonText: 'Learn More', buttonColor: '#2563eb', description: 'Standard blue button' },
    { name: 'variant-a-cta', buttonText: 'Discover Now', buttonColor: '#16a34a', description: 'Green button for discovery' },
    { name: 'variant-b-cta', buttonText: 'Explore Features', buttonColor: '#dc2626', description: 'Red button to explore' },
  ];

  const dummyUsers = generateDummyUsers(100); // Generate 100 dummy users for better distribution

  const runABCTest = useCallback(async () =&amp;gt; {
    setIsLoading(true);
    setTestResults([]);
    const results = [];

    for (let i = 0; i &amp;lt; dummyUsers.length; i++) {
      const user = dummyUsers[i];
      setCurrentTestingUser(user.name);

      try {
        // Update context for this user
        await updateContext({
          userId: user.id,
          // You can add other context properties if your Unleash strategies use them
          // e.g., accountType: user.accountType,
        });

        // Small delay to allow context to fully propagate and client to potentially re-evaluate
        // This is more for visual effect in a rapid loop, less for functional necessity with useUnleashClient
        await new Promise((resolve) =&amp;gt; setTimeout(resolve, 100));

        // Get the variant for the current user and feature flag
        const variant = unleashClient.getVariant(featureFlagName);

        results.push({
          ...user,
          variantName: variant.name,
          variantPayload: variant.payload ? JSON.parse(variant.payload.value) : null, // Parse payload if it exists
          testTimestamp: new Date().toLocaleTimeString(),
          flagEnabled: variant.enabled, // Track if the flag was enabled for this user
        });
      } catch (error) {
        console.error(`Error testing user ${user.id}:`, error);
        results.push({
          ...user,
          variantName: 'error',
          variantPayload: null,
          testTimestamp: new Date().toLocaleTimeString(),
          flagEnabled: false,
          error: true,
        });
      }
    }

    setTestResults(results);
    setCurrentTestingUser('');
    setIsLoading(false);
  }, [dummyUsers, featureFlagName, updateContext, unleashClient]);

  // Calculate rollout statistics for each variant
  const calculateStats = useCallback(() =&amp;gt; {
    if (testResults.length === 0) {
      return {
        total: 0,
        variants: expectedVariants.map(v =&amp;gt; ({
          name: v.name,
          count: 0,
          percentage: 0,
          color: v.buttonColor,
          buttonText: v.buttonText,
        })),
        totalEnabled: 0,
        totalEnabledPercentage: 0,
      };
    }

    const variantCounts = {};
    let totalEnabled = 0;

    testResults.forEach((result) =&amp;gt; {
      if (result.flagEnabled) { // Only count if the flag was actually enabled for the user
        totalEnabled++;
        variantCounts[result.variantName] = (variantCounts[result.variantName] || 0) + 1;
      }
    });

    const stats = expectedVariants.map(v =&amp;gt; {
      const count = variantCounts[v.name] || 0;
      const percentage = totalEnabled &amp;gt; 0 ? Math.round((count / totalEnabled) * 100) : 0;
      return {
        name: v.name,
        count,
        percentage,
        color: v.buttonColor,
        buttonText: v.buttonText,
      };
    });

    return {
      total: testResults.length,
      variants: stats,
      totalEnabled: totalEnabled,
      totalEnabledPercentage: testResults.length &amp;gt; 0 ? Math.round((totalEnabled / testResults.length) * 100) : 0,
    };
  }, [testResults, expectedVariants]);

  const stats = calculateStats();

  return (
    &amp;lt;Container&amp;gt;
      &amp;lt;MaxWidthWrapper&amp;gt;
        {/* Header */}
        &amp;lt;Card&amp;gt;
          &amp;lt;Header&amp;gt;
            &amp;lt;Title&amp;gt;✨ Unleash A/B/C Test Simulator&amp;lt;/Title&amp;gt;
            &amp;lt;Subtitle&amp;gt;
              Simulate multivariate testing with real Unleash flag variants and observe distribution.
            &amp;lt;/Subtitle&amp;gt;
          &amp;lt;/Header&amp;gt;
        &amp;lt;/Card&amp;gt;

        {/* Configuration Panel */}
        &amp;lt;Card&amp;gt;
          &amp;lt;SectionTitle&amp;gt;Configuration&amp;lt;/SectionTitle&amp;gt;
          &amp;lt;ConfigPanel&amp;gt;
            &amp;lt;InputGroup&amp;gt;
              &amp;lt;Label htmlFor="flagName"&amp;gt;Feature Flag Name&amp;lt;/Label&amp;gt;
              &amp;lt;Input
                id="flagName"
                type="text"
                value={featureFlagName}
                onChange={(e) =&amp;gt; setFeatureFlagName(e.target.value)}
                placeholder="e.g., ab-test-variant-feature"
              /&amp;gt;
            &amp;lt;/InputGroup&amp;gt;
            &amp;lt;Button onClick={runABCTest} disabled={isLoading}&amp;gt;
              {isLoading ? (
                &amp;lt;&amp;gt;
                  &amp;lt;Spinner /&amp;gt;
                  Testing...
                &amp;lt;/&amp;gt;
              ) : (
                &amp;lt;&amp;gt;🚀 Start A/B/C Test ({dummyUsers.length} Users)&amp;lt;/&amp;gt;
              )}
            &amp;lt;/Button&amp;gt;
          &amp;lt;/ConfigPanel&amp;gt;
        &amp;lt;/Card&amp;gt;

        {/* Current Status */}
        {isLoading &amp;amp;&amp;amp; (
          &amp;lt;StatusBanner&amp;gt;
            &amp;lt;StatusContent&amp;gt;
              &amp;lt;StatusSpinner /&amp;gt;
              &amp;lt;StatusText&amp;gt;Currently testing: {currentTestingUser}&amp;lt;/StatusText&amp;gt;
            &amp;lt;/StatusContent&amp;gt;
          &amp;lt;/StatusBanner&amp;gt;
        )}

        {/* Visual Representation of Variants */}
        &amp;lt;VariantDisplaySection&amp;gt;
          &amp;lt;SectionTitle&amp;gt;Simulated Variant Preview&amp;lt;/SectionTitle&amp;gt;
          &amp;lt;p style={{ color: '#4a5568', fontSize: '0.9rem', marginBottom: '1rem' }}&amp;gt;
            These are the expected UI variations based on the payload configured in Unleash.
            Your application would render one of these for each user.
          &amp;lt;/p&amp;gt;
          &amp;lt;VariantDisplayGrid&amp;gt;
            {expectedVariants.map((variant) =&amp;gt; (
              &amp;lt;VariantCard key={variant.name}&amp;gt;
                &amp;lt;VariantName&amp;gt;{variant.name}&amp;lt;/VariantName&amp;gt;
                &amp;lt;SimulatedButton color={variant.buttonColor}&amp;gt;
                  {variant.buttonText}
                &amp;lt;/SimulatedButton&amp;gt;
                &amp;lt;VariantDescription&amp;gt;{variant.description}&amp;lt;/VariantDescription&amp;gt;
              &amp;lt;/VariantCard&amp;gt;
            ))}
          &amp;lt;/VariantDisplayGrid&amp;gt;
        &amp;lt;/VariantDisplaySection&amp;gt;

        {/* Statistics Dashboard */}
        {testResults.length &amp;gt; 0 &amp;amp;&amp;amp; (
          &amp;lt;&amp;gt;
            &amp;lt;StatsGrid&amp;gt;
              &amp;lt;StatCard&amp;gt;
                &amp;lt;StatValue color="#2563eb"&amp;gt;{stats.total}&amp;lt;/StatValue&amp;gt;
                &amp;lt;StatLabel&amp;gt;Total Users Tested&amp;lt;/StatLabel&amp;gt;
              &amp;lt;/StatCard&amp;gt;
              &amp;lt;StatCard&amp;gt;
                &amp;lt;StatValue color="#16a34a"&amp;gt;{stats.totalEnabled}&amp;lt;/StatValue&amp;gt;
                &amp;lt;StatLabel&amp;gt;Flag Enabled Users&amp;lt;/StatLabel&amp;gt;
              &amp;lt;/StatCard&amp;gt;
              &amp;lt;StatCard&amp;gt;
                &amp;lt;StatValue color="#7c3aed"&amp;gt;{stats.totalEnabledPercentage}%&amp;lt;/StatValue&amp;gt;
                &amp;lt;StatLabel&amp;gt;Total Rollout Percentage&amp;lt;/StatLabel&amp;gt;
              &amp;lt;/StatCard&amp;gt;
            &amp;lt;/StatsGrid&amp;gt;

            &amp;lt;ProgressSection&amp;gt;
              &amp;lt;ProgressTitle&amp;gt;Variant Distribution&amp;lt;/ProgressTitle&amp;gt;
              &amp;lt;ProgressBarContainer&amp;gt;
                {stats.variants.map((variantStat) =&amp;gt; (
                  &amp;lt;ProgressBarSegment key={variantStat.name} percentage={variantStat.percentage} color={variantStat.color}&amp;gt;
                    {variantStat.percentage &amp;gt; 0 &amp;amp;&amp;amp; `${variantStat.percentage}%`}
                  &amp;lt;/ProgressBarSegment&amp;gt;
                ))}
              &amp;lt;/ProgressBarContainer&amp;gt;
              &amp;lt;ProgressLabels&amp;gt;
                {stats.variants.map((variantStat) =&amp;gt; (
                  &amp;lt;span key={`label-${variantStat.name}`} style={{ flex: 1, textAlign: 'center', color: variantStat.color }}&amp;gt;
                    {variantStat.name} ({variantStat.count})
                  &amp;lt;/span&amp;gt;
                ))}
              &amp;lt;/ProgressLabels&amp;gt;
            &amp;lt;/ProgressSection&amp;gt;
          &amp;lt;/&amp;gt;
        )}

        {/* Results Table */}
        {testResults.length &amp;gt; 0 &amp;amp;&amp;amp; (
          &amp;lt;ResultsCard&amp;gt;
            &amp;lt;ResultsHeader&amp;gt;
              &amp;lt;ResultsTitle&amp;gt;Detailed Test Results&amp;lt;/ResultsTitle&amp;gt;
            &amp;lt;/ResultsHeader&amp;gt;
            &amp;lt;TableContainer&amp;gt;
              &amp;lt;Table&amp;gt;
                &amp;lt;TableHead&amp;gt;
                  &amp;lt;tr&amp;gt;
                    &amp;lt;TableHeader&amp;gt;User&amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableHeader&amp;gt;Account Type&amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableHeader&amp;gt;Assigned Variant&amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableHeader&amp;gt;Flag Enabled&amp;lt;/TableHeader&amp;gt;
                    &amp;lt;TableHeader&amp;gt;Test Time&amp;lt;/TableHeader&amp;gt;
                  &amp;lt;/tr&amp;gt;
                &amp;lt;/TableHead&amp;gt;
                &amp;lt;tbody&amp;gt;
                  {testResults.map((result, index) =&amp;gt; (
                    &amp;lt;TableRow key={result.id}&amp;gt;
                      &amp;lt;TableCell&amp;gt;
                        &amp;lt;UserInfo&amp;gt;
                          &amp;lt;UserAvatar&amp;gt;
                            &amp;lt;UserInitials&amp;gt;
                              {result.name
                                .split(' ')
                                .map((n) =&amp;gt; n[0])
                                .join('')
                                .slice(0, 2)}
                            &amp;lt;/UserInitials&amp;gt;
                          &amp;lt;/UserAvatar&amp;gt;
                          &amp;lt;UserDetails&amp;gt;
                            &amp;lt;UserName&amp;gt;{result.name}&amp;lt;/UserName&amp;gt;
                            &amp;lt;UserEmail&amp;gt;{result.email}&amp;lt;/UserEmail&amp;gt;
                          &amp;lt;/UserDetails&amp;gt;
                        &amp;lt;/UserInfo&amp;gt;
                      &amp;lt;/TableCell&amp;gt;
                      &amp;lt;TableCell&amp;gt;
                        &amp;lt;Badge type={result.accountType}&amp;gt;
                          {result.accountType}
                        &amp;lt;/Badge&amp;gt;
                      &amp;lt;/TableCell&amp;gt;
                      &amp;lt;TableCell&amp;gt;
                        {result.error ? (
                          &amp;lt;StatusBadge type="error"&amp;gt;❌ Error&amp;lt;/StatusBadge&amp;gt;
                        ) : result.flagEnabled ? (
                          &amp;lt;StatusBadge type="enabled"&amp;gt;{result.variantName}&amp;lt;/StatusBadge&amp;gt;
                        ) : (
                          &amp;lt;StatusBadge type="disabled"&amp;gt;N/A (Disabled)&amp;lt;/StatusBadge&amp;gt;
                        )}
                      &amp;lt;/TableCell&amp;gt;
                      &amp;lt;TableCell&amp;gt;
                        {result.error ? (
                          &amp;lt;StatusBadge type="error"&amp;gt;❌ No&amp;lt;/StatusBadge&amp;gt;
                        ) : result.flagEnabled ? (
                          &amp;lt;StatusBadge type="enabled"&amp;gt;✅ Yes&amp;lt;/StatusBadge&amp;gt;
                        ) : (
                          &amp;lt;StatusBadge type="disabled"&amp;gt;❌ No&amp;lt;/StatusBadge&amp;gt;
                        )}
                      &amp;lt;/TableCell&amp;gt;
                      &amp;lt;TableCell&amp;gt;{result.testTimestamp}&amp;lt;/TableCell&amp;gt;
                    &amp;lt;/TableRow&amp;gt;
                  ))}
                &amp;lt;/tbody&amp;gt;
              &amp;lt;/Table&amp;gt;
            &amp;lt;/TableContainer&amp;gt;
          &amp;lt;/ResultsCard&amp;gt;
        )}

        {/* Initial State */}
        {testResults.length === 0 &amp;amp;&amp;amp; !isLoading &amp;amp;&amp;amp; (
          &amp;lt;EmptyState&amp;gt;
            &amp;lt;EmptyStateIcon&amp;gt;📊&amp;lt;/EmptyStateIcon&amp;gt;
            &amp;lt;EmptyStateTitle&amp;gt;Ready to Simulate A/B/C Tests&amp;lt;/EmptyStateTitle&amp;gt;
            &amp;lt;EmptyStateText&amp;gt;
              Enter your feature flag name and click "Start Test" to see how Unleash distributes users across variants.
            &amp;lt;/EmptyStateText&amp;gt;
            &amp;lt;EmptyStateNote&amp;gt;
              Ensure your flag "{featureFlagName}" is configured in Unleash with at least three variants and a gradual rollout strategy.
            &amp;lt;/EmptyStateNote&amp;gt;
          &amp;lt;/EmptyState&amp;gt;
        )}
      &amp;lt;/MaxWidthWrapper&amp;gt;
    &amp;lt;/Container&amp;gt;
  );
};

export default ABTestSimulator;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>gradual-rollout</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Sun, 29 Jun 2025 10:44:58 +0000</pubDate>
      <link>https://dev.to/nebula_3108/gradual-rollout-1458</link>
      <guid>https://dev.to/nebula_3108/gradual-rollout-1458</guid>
      <description>&lt;p&gt;Import useUnleashClient:&lt;br&gt;
You need to import the useUnleashClient hook from @unleash/proxy-client-react.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect } from 'react';
import { useFlag, useUnleashContext, useUnleashClient } from '@unleash/proxy-client-react'; // ADD useUnleashClient here
import styled, { keyframes, css } from 'styled-components';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get the Unleash Client Instance:&lt;br&gt;
Inside your UnleashRolloutTester component, get the client instance using useUnleashClient().&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const UnleashRolloutTester = () =&amp;gt; {
  const [testResults, setTestResults] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [currentTestingUser , setCurrentTestingUser ] = useState('');
  const [featureFlagName, setFeatureFlagName] = useState('filtering-feature');
  const updateContext = useUnleashContext();
  const unleashClient = useUnleashClient(); // ADD this line
  const currentFlag = useFlag(featureFlagName); // You can keep this for the initial display/setup, but won't use it in the loop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify testMultipleUsers function:&lt;br&gt;
Inside the for loop in testMultipleUsers, you'll use unleashClient.isEnabled() with the dynamically updated context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const testMultipleUsers = async () =&amp;gt; {
  setIsLoading(true);
  setTestResults([]);
  const results = [];

  for (let i = 0; i &amp;lt; dummyUsers.length; i++) {
    const user = dummyUsers[i];
    setCurrentTestingUser(user.name);

    try {
      // Update context for this user
      await updateContext({
        userId: user.id,
        // You can also add custom context properties if your strategies use them:
        // accountType: user.accountType, // Uncomment if you have a strategy based on accountType
      });

      // Small delay to ensure context updates (might not be strictly necessary with await updateContext,
      // but good for ensuring the Unleash client has time to process the context change and fetch flags if needed)
      await new Promise((resolve) =&amp;gt; setTimeout(resolve, 300));

      // **THIS IS THE KEY CHANGE:** Use unleashClient.isEnabled() with the current context
      const flagEnabled = unleashClient.isEnabled(featureFlagName); // REAL FLAG CHECK

      results.push({
        ...user,
        flagEnabled: flagEnabled, // Use the actual flagEnabled status
        testTimestamp: new Date().toLocaleTimeString(),
      });
    } catch (error) {
      console.error(`Error testing user ${user.id}:`, error);
      results.push({
        ...user,
        flagEnabled: false,
        error: true,
        testTimestamp: new Date().toLocaleTimeString(),
      });
    }
  }

  setTestResults(results);
  setCurrentTestingUser('');
  setIsLoading(false);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>profilePage</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Fri, 27 Jun 2025 05:32:44 +0000</pubDate>
      <link>https://dev.to/nebula_3108/profilepage-95n</link>
      <guid>https://dev.to/nebula_3108/profilepage-95n</guid>
      <description>&lt;ol&gt;
&lt;li&gt;Additional Imports (at the top with other imports)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';
import { FaTimes } from 'react-icons/fa';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;New Styled Components (add after the existing styled components)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const ModalOverlay = styled(motion.div)`
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(8px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
`;

const ModalContent = styled(motion.div)`
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(20px);
  border-radius: 20px;
  padding: 32px;
  width: 90%;
  max-width: 1000px;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(255, 255, 255, 0.3);
  position: relative;
`;

const ModalHeader = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 2px solid rgba(102, 126, 234, 0.1);

  h3 {
    font-size: 24px;
    font-weight: 700;
    background: linear-gradient(135deg, #667eea, #764ba2);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    margin: 0;
  }
`;

const CloseButton = styled(motion.button)`
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1));
  border: 1px solid rgba(102, 126, 234, 0.2);
  border-radius: 50%;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #667eea;
  transition: all 0.3s ease;

  &amp;amp;:hover {
    background: linear-gradient(135deg, #667eea, #764ba2);
    color: white;
    transform: rotate(90deg);
  }
`;

const TransactionTable = styled(motion.table)`
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
`;

const StatusBadge = styled.span`
  padding: 6px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;

  ${props =&amp;gt; {
    switch (props.status) {
      case 'SUCCESS':
        return `
          background: rgba(34, 197, 94, 0.1);
          color: #059669;
          border: 1px solid rgba(34, 197, 94, 0.2);
        `;
      case 'FAILURE':
        return `
          background: rgba(239, 68, 68, 0.1);
          color: #dc2626;
          border: 1px solid rgba(239, 68, 68, 0.2);
        `;
      case 'PENDING':
        return `
          background: rgba(245, 158, 11, 0.1);
          color: #d97706;
          border: 1px solid rgba(245, 158, 11, 0.2);
        `;
      default:
        return `
          background: rgba(156, 163, 175, 0.1);
          color: #6b7280;
          border: 1px solid rgba(156, 163, 175, 0.2);
        `;
    }
  }}
`;

const TypeBadge = styled.span`
  padding: 6px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;

  ${props =&amp;gt; {
    switch (props.type) {
      case 'DEPOSIT':
        return `
          background: rgba(34, 197, 94, 0.1);
          color: #059669;
          border: 1px solid rgba(34, 197, 94, 0.2);
        `;
      case 'WITHDRAWAL':
        return `
          background: rgba(239, 68, 68, 0.1);
          color: #dc2626;
          border: 1px solid rgba(239, 68, 68, 0.2);
        `;
      case 'TRANSFER':
        return `
          background: rgba(59, 130, 246, 0.1);
          color: #2563eb;
          border: 1px solid rgba(59, 130, 246, 0.2);
        `;
      case 'LOAN':
        return `
          background: rgba(168, 85, 247, 0.1);
          color: #7c3aed;
          border: 1px solid rgba(168, 85, 247, 0.2);
        `;
      default:
        return `
          background: rgba(156, 163, 175, 0.1);
          color: #6b7280;
          border: 1px solid rgba(156, 163, 175, 0.2);
        `;
    }
  }}
`;

const EmptyState = styled(motion.div)`
  text-align: center;
  padding: 60px 20px;
  color: #6b7280;

  h4 {
    font-size: 20px;
    font-weight: 600;
    margin-bottom: 8px;
    color: #374151;
  }

  p {
    font-size: 16px;
    margin: 0;
  }
`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;State Management (add inside the Profile component, after the existing useQuery)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [selectedAccount, setSelectedAccount] = useState(null);
const [isModalOpen, setIsModalOpen] = useState(false);

const { data: transactions, isLoading: isTransactionsLoading } = useQuery({
  queryKey: ['transactions', selectedAccount],
  queryFn: async () =&amp;gt; {
    if (!selectedAccount) return [];
    try {
      const response = await api.get(`/transactions/${selectedAccount}`);
      return response.data.data;
    } catch (error) {
      console.error('Error fetching transactions', error);
      toast.error("Error fetching transactions");
      return [];
    }
  },
  enabled: !!selectedAccount
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Helper Functions (add inside the Profile component)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const openTransactionModal = (accountNumber) =&amp;gt; {
  setSelectedAccount(accountNumber);
  setIsModalOpen(true);
};

const closeTransactionModal = () =&amp;gt; {
  setIsModalOpen(false);
  setSelectedAccount(null);
};

const formatTransactionAmount = (amount, type) =&amp;gt; {
  const formattedAmount = formatCurrency(amount);
  if (type === 'DEPOSIT') return `+${formattedAmount}`;
  if (type === 'WITHDRAWAL') return `-${formattedAmount}`;
  return formattedAmount;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Update the View Transactions Button (replace the existing ActionLink for transactions)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;ActionLink 
  variants={actionLinkVariants} 
  onClick={() =&amp;gt; openTransactionModal(account.accountNumber)}
&amp;gt;
  &amp;lt;FaEye /&amp;gt; View Transactions
&amp;lt;/ActionLink&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add the Modal (add this right before the closing  tag)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{isModalOpen &amp;amp;&amp;amp; (
  &amp;lt;ModalOverlay
    initial={{ opacity: 0 }}
    animate={{ opacity: 1 }}
    exit={{ opacity: 0 }}
    onClick={closeTransactionModal}
  &amp;gt;
    &amp;lt;ModalContent
      initial={{ opacity: 0, scale: 0.8, y: 50 }}
      animate={{ opacity: 1, scale: 1, y: 0 }}
      exit={{ opacity: 0, scale: 0.8, y: 50 }}
      onClick={(e) =&amp;gt; e.stopPropagation()}
    &amp;gt;
      &amp;lt;ModalHeader&amp;gt;
        &amp;lt;h3&amp;gt;Transaction History - {selectedAccount}&amp;lt;/h3&amp;gt;
        &amp;lt;CloseButton
          whileHover={{ scale: 1.1 }}
          whileTap={{ scale: 0.9 }}
          onClick={closeTransactionModal}
        &amp;gt;
          &amp;lt;FaTimes /&amp;gt;
        &amp;lt;/CloseButton&amp;gt;
      &amp;lt;/ModalHeader&amp;gt;

      {isTransactionsLoading ? (
        &amp;lt;div style={{ textAlign: 'center', padding: '40px' }}&amp;gt;
          Loading transactions...
        &amp;lt;/div&amp;gt;
      ) : transactions?.length === 0 ? (
        &amp;lt;EmptyState
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
        &amp;gt;
          &amp;lt;h4&amp;gt;No Transactions Found&amp;lt;/h4&amp;gt;
          &amp;lt;p&amp;gt;This account has no transaction history yet.&amp;lt;/p&amp;gt;
        &amp;lt;/EmptyState&amp;gt;
      ) : (
        &amp;lt;TransactionTable
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
        &amp;gt;
          &amp;lt;thead&amp;gt;
            &amp;lt;tr&amp;gt;
              &amp;lt;TableHeader&amp;gt;Date&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Type&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;From Account&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;To Account&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Amount&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Description&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Status&amp;lt;/TableHeader&amp;gt;
            &amp;lt;/tr&amp;gt;
          &amp;lt;/thead&amp;gt;
          &amp;lt;tbody&amp;gt;
            {transactions?.map((transaction) =&amp;gt; (
              &amp;lt;TableRow key={transaction.id}&amp;gt;
                &amp;lt;TableCell&amp;gt;{formatDate(transaction.timestamp)}&amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;
                  &amp;lt;TypeBadge type={transaction.type}&amp;gt;
                    {transaction.type}
                  &amp;lt;/TypeBadge&amp;gt;
                &amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;
                  {transaction.fromAccount ? (
                    &amp;lt;code style={{
                      background: 'rgba(102,126,234,0.1)',
                      padding: '4px 8px',
                      borderRadius: '6px',
                      fontSize: '12px'
                    }}&amp;gt;
                      {transaction.fromAccount.accountNumber}
                    &amp;lt;/code&amp;gt;
                  ) : (
                    &amp;lt;span style={{ color: '#9ca3af', fontStyle: 'italic' }}&amp;gt;
                      External
                    &amp;lt;/span&amp;gt;
                  )}
                &amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;
                  {transaction.toAccount ? (
                    &amp;lt;code style={{
                      background: 'rgba(102,126,234,0.1)',
                      padding: '4px 8px',
                      borderRadius: '6px',
                      fontSize: '12px'
                    }}&amp;gt;
                      {transaction.toAccount.accountNumber}
                    &amp;lt;/code&amp;gt;
                  ) : (
                    &amp;lt;span style={{ color: '#9ca3af', fontStyle: 'italic' }}&amp;gt;
                      External
                    &amp;lt;/span&amp;gt;
                  )}
                &amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;
                  &amp;lt;span style={{ 
                    fontWeight: 'bold',
                    color: transaction.type === 'DEPOSIT' ? '#059669' : 
                           transaction.type === 'WITHDRAWAL' ? '#dc2626' : '#374151'
                  }}&amp;gt;
                    {formatTransactionAmount(transaction.amount, transaction.type)}
                  &amp;lt;/span&amp;gt;
                &amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;{transaction.description || 'No description'}&amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;
                  &amp;lt;StatusBadge status={transaction.status}&amp;gt;
                    {transaction.status}
                  &amp;lt;/StatusBadge&amp;gt;
                &amp;lt;/TableCell&amp;gt;
              &amp;lt;/TableRow&amp;gt;
            ))}
          &amp;lt;/tbody&amp;gt;
        &amp;lt;/TransactionTable&amp;gt;
      )}
    &amp;lt;/ModalContent&amp;gt;
  &amp;lt;/ModalOverlay&amp;gt;
)}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;








&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;h3&amp;gt;Accounts&amp;lt;/h3&amp;gt;
      {
        isLoading ? ( &amp;lt;div&amp;gt;fetching accounts...&amp;lt;/div&amp;gt;) : isError ? (&amp;lt;div&amp;gt;
          Error fetching accounts!
        &amp;lt;/div&amp;gt; ) : accounts.length === 0 ? &amp;lt;div&amp;gt;
          &amp;lt;p&amp;gt;You dont have any accounts yet. Create your first account&amp;lt;/p&amp;gt;
          &amp;lt;CreateButton onClick={() =&amp;gt; {
            navigate("/dashboard/open-account")
          }}&amp;gt;Create Account&amp;lt;/CreateButton&amp;gt;
        &amp;lt;/div&amp;gt; : 

        &amp;lt;Table initial={{opacity: 0, y:30}}
        animate={{
          opacity: 1,
          y:0,
          transition: {
            duration: 0.6,
            ease: 'easeOut',
            staggerChildren: 0.05
          }   
        }}&amp;gt;
          &amp;lt;thead&amp;gt;
            &amp;lt;tr&amp;gt;
              &amp;lt;TableHeader&amp;gt;Sr. No&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Account Number&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Account Holder Name&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Date of Creation&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Account Balance&amp;lt;/TableHeader&amp;gt;
              &amp;lt;TableHeader&amp;gt;Actions&amp;lt;/TableHeader&amp;gt;
            &amp;lt;/tr&amp;gt;
          &amp;lt;/thead&amp;gt;
          &amp;lt;tbody&amp;gt;
            {accounts?.map((account,idx) =&amp;gt; (
              &amp;lt;TableRow key={idx} whileHover="hover" &amp;gt;
                &amp;lt;TableCell&amp;gt;{idx + 1}&amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;
                &amp;lt;code style={{
                    background: 'rgba(102,126,234,0.1)',
                    padding: '4px 8px',
                    borderRadius: '6px',
                    fontSize: '14px',
                    fontWeight: '600'
                  }}&amp;gt;{account.accountNumber}&amp;lt;/code&amp;gt;
                &amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;{user?.name}&amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;{formatDate(account.createdAt)}&amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;
                  &amp;lt;ActionLink href="#view-balance" onClick={() =&amp;gt; {
                    toast(`Balance ${formatCurrency(account.balance)}`)
                  }}&amp;gt;View Balance&amp;lt;/ActionLink&amp;gt;
                &amp;lt;/TableCell&amp;gt;
                &amp;lt;TableCell&amp;gt;
                  &amp;lt;ActionLink variants={actionLinkVariants} href="#view-transactions"&amp;gt;&amp;lt;FaEye /&amp;gt; View Transactions&amp;lt;/ActionLink&amp;gt;
                &amp;lt;/TableCell&amp;gt;
              &amp;lt;/TableRow&amp;gt;
            ))}
          &amp;lt;/tbody&amp;gt;
        &amp;lt;/Table&amp;gt;
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>frontend4</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Fri, 27 Jun 2025 05:28:30 +0000</pubDate>
      <link>https://dev.to/nebula_3108/frontend4-g07</link>
      <guid>https://dev.to/nebula_3108/frontend4-g07</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* eslint-disable react-refresh/only-export-components */
import React, { createContext, useContext, useState, useEffect } from 'react'
import { authService } from '@/services/authService'
import PropTypes from 'prop-types'
import { useMutation } from '@tanstack/react-query'

const AuthContext = createContext(undefined)

export const AuthProvider = ({ children }) =&amp;gt; {
  const [user, setUser] = useState(authService.getUser())
  const [isLoading, setIsLoading] = useState(true)

  // On first load, restore user if present
  useEffect(() =&amp;gt; {
    const storedUser = authService.getUser()

    setUser(storedUser)
    setIsLoading(false)
  }, [])

  const loginMutation = useMutation({
    mutationFn: async (credentials) =&amp;gt; {
      const userData = await authService.login(credentials)
      setUser(userData)
      return userData
    },
  })

  const logoutMutation = useMutation({
    mutationFn: async () =&amp;gt; {
      await authService.logout()
      setUser(null)
    },
  })

  const signupMutation = useMutation({
    mutationFn: async (credentials) =&amp;gt; {
      const userData = await authService.signup(credentials)
      setUser(userData)
      return userData
    },
  })

  const changePasswordMutation = useMutation({
    mutationFn: async (data) =&amp;gt; {
      return await authService.changePassword(data)
    },
  })

  return (
    &amp;lt;AuthContext.Provider
      value={{
        user: user,
        isAuthenticated: !!user,
        isLoading,
        login: loginMutation.mutateAsync,
        logout: logoutMutation.mutateAsync,
        signup: signupMutation.mutateAsync,
        changePassword: changePasswordMutation.mutateAsync,
        setUser,
      }}
    &amp;gt;
      {children}
    &amp;lt;/AuthContext.Provider&amp;gt;
  )
}

AuthProvider.propTypes = {
  children: PropTypes.node.isRequired,
}

export const useAuth = () =&amp;gt; {
  const context = useContext(AuthContext)
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider')
  }
  return context
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;------------------- AUTH SERVICE-------------------------&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import api from './api'
import Cookies from 'js-cookie'

const USER_KEY = 'user' // localStorage key for storing user data

export const authService = {
  // Login with email &amp;amp; password
  async login(credentials) {
    try {
      const response = await api.post('/auth/login', credentials, {
        withCredentials: true, // important: to include cookies
      })
      // console.log('Data from backend', response.data.user)
      this.setUser(response.data.user)
      return response.data.user
    } catch (error) {
      const message = error.response?.data?.message || 'Login failed!'
      console.error('Login error:', error)
      throw new Error(message)
    }
  },

  // Signup
  async signup(data) {
    try {
      const response = await api.post('/auth/signup', data, {
        withCredentials: true,
      })
      this.setUser(response.data.user)
      return response.data.user
    } catch (error) {
      const message = error.response?.data?.message || 'Signup failed!'
      console.error('Signup error:', message)
      throw new Error(message)
    }
  },

  // Logout
  async logout() {
    try {
      await api.post('/auth/logout', {}, { withCredentials: true })
      this.clearUser()
    } catch (error) {
      console.error('Logout error:', error.message)
    }
  },

  // Forgot Password
  async forgotPassword(email) {
    try {
      const res = await api.post('/auth/forgot-password', { email })
      return res.data
    } catch (error) {
      const message = error.response?.data?.message || 'Request failed'
      throw new Error(message)
    }
  },

  // Reset Password
  async resetPassword(token, data) {
    try {
      const res = await api.post(`/auth/reset-password/${token}`, data)
      return res.data
    } catch (error) {
      const message = error.response?.data?.message || 'Reset failed'
      throw new Error(message)
    }
  },

  // Change Password (authenticated)
  async changePassword(data) {
    try {
      const res = await api.put('/auth/change-password', data, {
        withCredentials: true,
      })
      return res.data
    } catch (error) {
      const message = error.response?.data?.message || 'Password change failed'
      throw new Error(message)
    }
  },

  // Set user in localStorage
  setUser(userData) {
    localStorage.setItem(USER_KEY, JSON.stringify(userData))
  },

  getUser() {
    const userStr = localStorage.getItem(USER_KEY)
    try {
      return userStr ? JSON.parse(userStr) : null
    } catch (err) {
      console.error('Error parsing user data', err)
      return null
    }
  },

  clearUser() {
    localStorage.removeItem(USER_KEY)
  },

  isAuthenticated() {
    return !!Cookies.get('token') // JWT cookie present?
  },
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;------------------------ API.JS---------------------------&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import axios from 'axios'
import Cookies from 'js-cookie'

// const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:4000/api'
const API_URL = import.meta.env.VITE_API_URL || 'https://customerapi.mendt.in/api'

if (!import.meta.env.VITE_API_URL) {
  console.warn('VITE_API_URL is not set, using default API URL.')
}

const api = axios.create({
  baseURL: API_URL,
  withCredentials: true,
  // headers: {
  //   "Content-Type": "application/json",
  // },
})

// Request interceptor for API calls
api.interceptors.request.use(
  (config) =&amp;gt; {
    const token = Cookies.get('token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) =&amp;gt; {
    return Promise.reject(error)
  }
)

// Response interceptor for API calls
api.interceptors.response.use(
  (response) =&amp;gt; {
    return response
  },
  async (error) =&amp;gt; {
    const originalRequest = error.config

    // Handle token expiration and refresh logic here if needed
    if (error.response?.status === 401 &amp;amp;&amp;amp; !originalRequest._retry) {
      originalRequest._retry = true
      // A  dd logic to refresh the token or redirect to login
    }

    return Promise.reject(error)
  }
)

export default api

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;---------------------- jsconfig.json-----------------------&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;-------------------------QueryProvider.jsx---------------------&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import PropTypes from "prop-types";

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      refetchOnWindowFocus: false,
      retry: 1,
      staleTime: 1000 * 60 * 5, // 5 minutes
    },
  },
});

export const QueryProvider = ({ children }) =&amp;gt; {
  return (
    &amp;lt;QueryClientProvider client={queryClient}&amp;gt;
      {children}
      &amp;lt;ReactQueryDevtools initialIsOpen={false} /&amp;gt;
    &amp;lt;/QueryClientProvider&amp;gt;
  );
};

QueryProvider.propTypes = {
  children: PropTypes.node.isRequired,
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;--------------------------SIGNUP--------------------------------&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import styled from 'styled-components';
import { motion } from 'framer-motion';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '@/contexts/AuthContext';
import { useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
import { InputGroup } from './Dashboard/CreateAccountStyles';
import { FaSpinner } from 'react-icons/fa';

// Design tokens
const colors = {
  primary: '#667eea',
  primaryDark: '#5a67d8',
  secondary: '#764ba2',
  success: '#48bb78',
  error: '#ff6b6b',
  warning: '#f6ad55',
  text: '#1a202c',
  textSecondary: '#4a5568',
  textMuted: '#a0aec0',
  background: 'rgba(255, 255, 255, 0.95)',
  border: 'rgba(102, 126, 234, 0.2)',
  borderHover: '#667eea',
  glass: 'rgba(255, 255, 255, 0.95)',
  glassLight: 'rgba(255, 255, 255, 0.8)',
  shadow: 'rgba(0, 0, 0, 0.1)',
  shadowHover: 'rgba(102, 126, 234, 0.1)'
};

const gradients = {
  primary: `linear-gradient(135deg, ${colors.primary}, ${colors.secondary})`,
  success: `linear-gradient(135deg, ${colors.success}, #38b2ac)`,
  error: `linear-gradient(135deg, ${colors.error}, #ee5a52)`,
  warning: `linear-gradient(135deg, ${colors.warning}, #ff8c00)`
};

const spacing = {
  xs: '4px',
  sm: '8px',
  md: '12px',
  lg: '16px',
  xl: '20px',
  xxl: '24px',
  xxxl: '32px'
};

// Styled Components
const Container = styled.div`
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: ${spacing.xl};
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  position: relative;

  &amp;amp;::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: 
      radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
      radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
      radial-gradient(circle at 40% 40%, rgba(120, 119, 198, 0.2) 0%, transparent 50%);
  }
`;

const FormWrapper = styled(motion.div)`
  background: ${colors.glass};
  backdrop-filter: blur(20px);
  border-radius: 20px;
  padding: ${spacing.xxxl};
  box-shadow: 0 8px 32px ${colors.shadow};
  border: 1px solid rgba(255, 255, 255, 0.2);
  position: relative;
  overflow: hidden;
  width: 100%;
  max-width: 450px;
  z-index: 1;

  &amp;amp;::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: ${gradients.primary};
  }

  @media (max-width: 768px) {
    padding: ${spacing.xxl};
    max-width: 100%;
  }
`;

const Title = styled.h1`
  font-size: 32px;
  font-weight: 800;
  color: ${colors.text};
  margin-bottom: ${spacing.sm};
  background: ${gradients.primary};
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  text-align: center;
  line-height: 1.2;

  @media (max-width: 768px) {
    font-size: 28px;
  }
`;

const Subtitle = styled.p`
  font-size: 16px;
  color: ${colors.textSecondary};
  text-align: center;
  margin-bottom: ${spacing.xxxl};
  font-weight: 500;
  line-height: 1.4;
`;

const Form = styled.form`
  display: flex;
  flex-direction: column;
  gap: ${spacing.lg};
`;

const StyledInputGroup = styled.div`
  display: flex;
  flex-direction: column;
  gap: ${spacing.xs};
`;

const Input = styled.input`
  width: 100%;
  padding: ${spacing.lg} ${spacing.xl};
  border: 2px solid ${props =&amp;gt; props.errors ? colors.error : colors.border};
  border-radius: 12px;
  font-size: 16px;
  font-weight: 500;
  color: ${colors.text};
  background: ${colors.glassLight};
  backdrop-filter: blur(10px);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-sizing: border-box;

  &amp;amp;:focus {
    outline: none;
    border-color: ${props =&amp;gt; props.errors ? colors.error : colors.borderHover};
    box-shadow: 0 0 0 4px ${props =&amp;gt; props.errors ? 'rgba(255, 107, 107, 0.1)' : colors.shadowHover};
    background: ${colors.background};
  }

  &amp;amp;::placeholder {
    color: ${colors.textMuted};
  }

  &amp;amp;:-webkit-autofill {
    -webkit-box-shadow: 0 0 0 30px ${colors.background} inset;
    -webkit-text-fill-color: ${colors.text};
  }
`;

const ErrorMessage = styled.p`
  color: ${colors.error};
  font-size: 14px;
  margin: 0;
  font-weight: 500;
  margin-top: ${spacing.xs};
`;

const Button = styled(motion.button)`
  width: 100%;
  padding: ${spacing.lg} ${spacing.xl};
  border-radius: 12px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  border: none;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  background: ${gradients.primary};
  color: white;
  box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: ${spacing.sm};
  margin-top: ${spacing.md};

  &amp;amp;:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5);
  }

  &amp;amp;:active {
    transform: translateY(0);
  }

  &amp;amp;:disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }

  svg {
    animation: spin 1s linear infinite;
  }

  @keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
`;

const LoginText = styled.p`
  text-align: center;
  margin-top: ${spacing.xxxl};
  color: ${colors.textSecondary};
  font-size: 14px;
  font-weight: 500;
`;

const LoginLink = styled.a`
  color: ${colors.primary};
  text-decoration: none;
  font-weight: 600;
  margin-left: ${spacing.xs};
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

  &amp;amp;:hover {
    color: ${colors.primaryDark};
    text-decoration: underline;
  }
`;

function Signup() {
  const navigate = useNavigate();
  const { signup } = useAuth();
  const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm();

  const onSubmit = async (data) =&amp;gt; {
    try {
      const userData = await signup({
        name: data.name,
        email: data.email,
        password: data.password,
        confirmPassword: data.confirmPassword
      });
      toast.success("Signed up successfully");
      setTimeout(() =&amp;gt; {
        navigate("/dashboard/profile");
      }, 1000);
    } catch (error) {
      console.error("Signup error", error);
      toast.error(error.response?.data?.message || error.message || "Signup failed. Please try again!");
    }
  }

  return (
    &amp;lt;Container&amp;gt;
      &amp;lt;FormWrapper
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.5, ease: 'easeOut' }}
        aria-label="Signup form"
      &amp;gt;
        &amp;lt;Title&amp;gt;Banking Application&amp;lt;/Title&amp;gt;
        &amp;lt;Subtitle&amp;gt;Create Your Account&amp;lt;/Subtitle&amp;gt;
        &amp;lt;Form onSubmit={handleSubmit(onSubmit)}&amp;gt;
          &amp;lt;StyledInputGroup&amp;gt;
            &amp;lt;Input
              id="name"
              type="text"
              placeholder="Full Name"
              errors={errors.name}
              {...register('name')}
            /&amp;gt;
            {errors.name &amp;amp;&amp;amp; (
              &amp;lt;ErrorMessage&amp;gt;
                {errors.name.message}
              &amp;lt;/ErrorMessage&amp;gt;
            )}
          &amp;lt;/StyledInputGroup&amp;gt;

          &amp;lt;StyledInputGroup&amp;gt;
            &amp;lt;Input
              id="email"
              type="text"
              placeholder="Email"
              errors={errors.email}
              {...register('email')}
            /&amp;gt;
            {errors.email &amp;amp;&amp;amp; (
              &amp;lt;ErrorMessage&amp;gt;
                {errors.email.message}
              &amp;lt;/ErrorMessage&amp;gt;
            )}
          &amp;lt;/StyledInputGroup&amp;gt;

          &amp;lt;StyledInputGroup&amp;gt;
            &amp;lt;Input
              type="password"
              id="password"
              placeholder="Password"
              errors={errors.password}
              {...register('password')}
            /&amp;gt;
            {errors.password &amp;amp;&amp;amp; (
              &amp;lt;ErrorMessage&amp;gt;
                {errors.password.message}
              &amp;lt;/ErrorMessage&amp;gt;
            )}
          &amp;lt;/StyledInputGroup&amp;gt;

          &amp;lt;StyledInputGroup&amp;gt;
            &amp;lt;Input
              type="password"
              id="confirmPassword"
              placeholder="Confirm Password"
              errors={errors.confirmPassword}
              {...register('confirmPassword')}
            /&amp;gt;
            {errors.confirmPassword &amp;amp;&amp;amp; (
              &amp;lt;ErrorMessage&amp;gt;
                {errors.confirmPassword.message}
              &amp;lt;/ErrorMessage&amp;gt;
            )}
          &amp;lt;/StyledInputGroup&amp;gt;

          &amp;lt;Button
            whileHover={{ scale: 1.02 }}
            whileTap={{ scale: 0.98 }}
            type="submit"
            disabled={isSubmitting}
          &amp;gt;
            {isSubmitting ? &amp;lt;FaSpinner /&amp;gt; : "Sign Up"}
          &amp;lt;/Button&amp;gt;
        &amp;lt;/Form&amp;gt;

        &amp;lt;LoginText&amp;gt;
          Already have an account?
          &amp;lt;LoginLink href="/login"&amp;gt; Log in&amp;lt;/LoginLink&amp;gt;
        &amp;lt;/LoginText&amp;gt;
      &amp;lt;/FormWrapper&amp;gt;
    &amp;lt;/Container&amp;gt;
  );
}

export default Signup;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>transfer page</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Wed, 25 Jun 2025 19:21:11 +0000</pubDate>
      <link>https://dev.to/nebula_3108/transfer-page-4o57</link>
      <guid>https://dev.to/nebula_3108/transfer-page-4o57</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect, useCallback } from "react";
import { Send, RefreshCw, AlertCircle, Filter } from "lucide-react";
import styled from 'styled-components';
import { motion, AnimatePresence } from 'framer-motion';
import toast from 'react-hot-toast';
import ConfirmModal from '@/utils/ConfirmModal';

// Design tokens
const colors = {
  primary: '#667eea',
  primaryDark: '#5a67d8',
  secondary: '#764ba2',
  success: '#48bb78',
  error: '#ff6b6b',
  warning: '#f6ad55',
  text: '#1a202c',
  textSecondary: '#4a5568',
  textMuted: '#a0aec0',
  background: 'rgba(255, 255, 255, 0.95)',
  border: 'rgba(102, 126, 234, 0.2)',
  borderHover: '#667eea',
  glass: 'rgba(255, 255, 255, 0.95)',
  glassLight: 'rgba(255, 255, 255, 0.8)',
  shadow: 'rgba(0, 0, 0, 0.1)',
  shadowHover: 'rgba(102, 126, 234, 0.1)'
};

const gradients = {
  primary: `linear-gradient(135deg, ${colors.primary}, ${colors.secondary})`,
  success: `linear-gradient(135deg, ${colors.success}, #38b2ac)`,
  error: `linear-gradient(135deg, ${colors.error}, #ee5a52)`,
  warning: `linear-gradient(135deg, ${colors.warning}, #ff8c00)`
};

const spacing = {
  xs: '4px',
  sm: '8px',
  md: '12px',
  lg: '16px',
  xl: '20px',
  xxl: '24px',
  xxxl: '32px'
};

// Styled Components
const Container = styled(motion.div)`
  padding: ${spacing.xxxl};
  max-width: 1400px;
  margin: 0 auto;
  min-height: calc(100vh - 120px);

  h2 {
    font-size: 32px;
    font-weight: 800;
    color: ${colors.text};
    margin-bottom: ${spacing.xxxl};
    background: ${gradients.primary};
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    text-align: center;
  }

  @media (max-width: 768px) {
    padding: ${spacing.xl};

    h2 {
      font-size: 28px;
      margin-bottom: ${spacing.xxl};
    }
  }
`;

const FormContainer = styled(motion.div)`
  background: ${colors.glass};
  backdrop-filter: blur(20px);
  border-radius: 20px;
  padding: ${spacing.xxxl};
  margin-bottom: ${spacing.xxxl};
  box-shadow: 0 8px 32px ${colors.shadow};
  border: 1px solid rgba(255, 255, 255, 0.2);
  position: relative;
  overflow: hidden;

  &amp;amp;::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: ${gradients.primary};
  }

  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: ${spacing.xl};

  @media (max-width: 768px) {
    grid-template-columns: 1fr;
    padding: ${spacing.xxl};
  }
`;

const Input = styled.input`
  width: 100%;
  padding: ${spacing.lg} ${spacing.xl};
  border: 2px solid ${colors.border};
  border-radius: 12px;
  font-size: 16px;
  font-weight: 500;
  color: ${colors.text};
  background: ${colors.glassLight};
  backdrop-filter: blur(10px);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

  &amp;amp;:focus {
    outline: none;
    border-color: ${colors.borderHover};
    box-shadow: 0 0 0 4px ${colors.shadowHover};
    background: ${colors.background};
  }

  &amp;amp;::placeholder {
    color: ${colors.textMuted};
  }
`;

const Select = styled.select`
  width: 100%;
  padding: ${spacing.lg} ${spacing.xl};
  border: 2px solid ${colors.border};
  border-radius: 12px;
  font-size: 16px;
  font-weight: 500;
  color: ${colors.text};
  background: ${colors.glassLight};
  backdrop-filter: blur(10px);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;

  &amp;amp;:focus {
    outline: none;
    border-color: ${colors.borderHover};
    box-shadow: 0 0 0 4px ${colors.shadowHover};
    background: ${colors.background};
  }

  option {
    background: white;
    color: ${colors.text};
    padding: ${spacing.md};
  }
`;

const TransferButton = styled(motion.button)`
  display: flex;
  align-items: center;
  justify-content: center;
  gap: ${spacing.sm};
  padding: ${spacing.lg} ${spacing.xxxl};
  border-radius: 12px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border: none;
  background: ${gradients.primary};
  color: white;
  box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);
  grid-column: 1 / -1;
  max-width: 300px;
  justify-self: center;

  &amp;amp;:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5);
  }

  &amp;amp;:active {
    transform: translateY(0);
  }

  &amp;amp;:disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }

  @media (max-width: 768px) {
    max-width: 100%;
  }
`;

const TableContainer = styled.div`
  background: ${colors.glass};
  backdrop-filter: blur(20px);
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 8px 32px ${colors.shadow};
  border: 1px solid rgba(255, 255, 255, 0.2);
  position: relative;

  &amp;amp;::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: ${gradients.primary};
  }
`;

const Table = styled.table`
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;

  th {
    background: ${gradients.primary};
    color: white;
    padding: ${spacing.xl} ${spacing.lg};
    text-align: left;
    font-weight: 600;
    font-size: 14px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    border: none;
    white-space: nowrap;
  }

  td {
    padding: ${spacing.xl} ${spacing.lg};
    color: ${colors.textSecondary};
    font-weight: 500;
    border-bottom: 1px solid rgba(226, 232, 240, 0.5);
    vertical-align: middle;
  }

  tr:hover {
    background: ${colors.shadowHover};
  }

  tr:nth-child(even) {
    background: rgba(248, 250, 252, 0.5);
  }

  @media (max-width: 1024px) {
    font-size: 14px;

    th, td {
      padding: ${spacing.md} ${spacing.sm};
    }
  }

  @media (max-width: 768px) {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }
`;

const StatusBadge = styled.span`
  padding: 6px ${spacing.md};
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;

  ${props =&amp;gt; props.status === 'SUCCESS' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(72, 187, 120, 0.2), rgba(56, 178, 172, 0.2));
    color: ${colors.success};
    border: 1px solid rgba(72, 187, 120, 0.3);
  `}

  ${props =&amp;gt; props.status === 'PENDING' &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(255, 193, 7, 0.2), rgba(255, 152, 0, 0.2));
    color: ${colors.warning};
    border: 1px solid rgba(255, 193, 7, 0.3);
  `}

  ${props =&amp;gt; (props.status === 'FAILED' || props.status === 'FAILURE') &amp;amp;&amp;amp; `
    background: linear-gradient(135deg, rgba(255, 107, 107, 0.2), rgba(238, 90, 82, 0.2));
    color: ${colors.error};
    border: 1px solid rgba(255, 107, 107, 0.3);
  `}
`;

const NewTag = styled.span`
  background: ${gradients.success};
  color: white;
  padding: 2px 6px;
  border-radius: 8px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  margin-left: ${spacing.sm};
`;

const LoadingSpinner = styled(motion.div)`
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 64px;
  color: ${colors.primary};

  svg {
    animation: spin 1s linear infinite;
  }

  @keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(360deg); }
  }
`;

const ErrorMessage = styled(motion.div)`
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: ${spacing.lg};
  padding: 64px ${spacing.xxxl};
  text-align: center;
  color: ${colors.error};

  h3 {
    margin: 0;
    font-size: 20px;
    font-weight: 600;
  }

  p {
    margin: 0;
    color: ${colors.textSecondary};
    line-height: 1.5;
  }
`;

const EmptyState = styled(motion.div)`
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: ${spacing.lg};
  padding: 64px ${spacing.xxxl};
  text-align: center;
  color: ${colors.textMuted};

  h3 {
    margin: 0;
    font-size: 20px;
    font-weight: 600;
  }

  p {
    margin: 0;
    line-height: 1.5;
  }
`;

// Mock useAuth hook for demonstration
const useAuth = () =&amp;gt; ({
  user: { id: 'user123' }
});

// Mock API function
const api = {
  get: async (endpoint) =&amp;gt; {
    await new Promise(resolve =&amp;gt; setTimeout(resolve, 1000));

    if (endpoint.includes('/accounts/user/')) {
      return {
        data: [
          { accountNumber: '123456789', accountType: 'SAVINGS', balance: 5000 },
          { accountNumber: '987654321', accountType: 'CHECKING', balance: 3000 },
          { accountNumber: '555666777', accountType: 'BUSINESS', balance: 10000 }
        ]
      };
    }

    if (endpoint.includes('/transactions/user/')) {
      return {
        data: [
          {
            id: 1,
            date: "2023-10-01",
            type: "TRANSFER",
            amount: 1500,
            fromAccount: { accountNumber: "123456789" },
            toAccount: { accountNumber: "987654321" },
            status: "SUCCESS",
            description: "Transfer to Savings",
          },
          {
            id: 2,
            date: "2023-10-02",
            type: "TRANSFER",
            amount: 2000,
            fromAccount: { accountNumber: "123456789" },
            toAccount: { accountNumber: "987654322" },
            status: "PENDING",
            description: "Transfer to Checking",
          },
          {
            id: 3,
            date: "2023-10-03",
            type: "DEPOSIT",
            amount: 750,
            fromAccount: null,
            toAccount: { accountNumber: "123456789" },
            status: "SUCCESS",
            description: "Salary deposit",
          },
          {
            id: 4,
            date: "2023-10-04",
            type: "TRANSFER",
            amount: 3000,
            fromAccount: { accountNumber: "987654321" },
            toAccount: { accountNumber: "123456789" },
            status: "FAILED",
            description: "Failed Transfer",
          },
        ]
      };
    }
  },

  post: async (endpoint, data) =&amp;gt; {
    await new Promise(resolve =&amp;gt; setTimeout(resolve, 1500));

    if (endpoint === '/transactions/transfer') {
      return {
        data: {
          data: {
            id: Date.now(),
            date: new Date().toISOString().split('T')[0],
            type: "TRANSFER",
            amount: data.amount,
            fromAccount: { accountNumber: data.fromAccountNumber },
            toAccount: { accountNumber: data.toAccountNumber },
            status: "SUCCESS",
            description: data.description,
            new: true
          }
        }
      };
    }
  }
};

// Mock query invalidation
const invalidateQueries = (queryKey) =&amp;gt; {
  console.log(`Invalidating queries: ${queryKey}`);
};

export default function Transfer() {
  const [transactions, setTransactions] = useState([]);
  const [userAccounts, setUserAccounts] = useState([]);
  const [form, setForm] = useState({
    fromAccountNumber: "",
    toAccountNumber: "",
    amount: "",
    description: ""
  });
  const [modalOpen, setModalOpen] = useState(false);
  const [loading, setLoading] = useState(true);
  const [accountsLoading, setAccountsLoading] = useState(true);
  const [transferring, setTransferring] = useState(false);
  const [error, setError] = useState(null);

  const { user } = useAuth();

  // Fetch user accounts
  const fetchUserAccounts = useCallback(async () =&amp;gt; {
    if (!user?.id) return;

    try {
      setAccountsLoading(true);
      const response = await api.get(`/accounts/user/${user.id}`);
      setUserAccounts(response.data);
    } catch (err) {
      console.error('Error fetching user accounts:', err);
      toast.error('Failed to load user accounts');
    } finally {
      setAccountsLoading(false);
    }
  }, [user?.id]);

  // Fetch transactions
  const fetchTransactions = useCallback(async () =&amp;gt; {
    if (!user?.id) return;

    try {
      setLoading(true);
      setError(null);
      const response = await api.get(`/transactions/user/${user.id}`);
      // Filter only transfer transactions
      const transferTransactions = response.data.filter(transaction =&amp;gt; 
        transaction.type === 'TRANSFER'
      );
      setTransactions(transferTransactions);
    } catch (err) {
      setError('Failed to load transactions. Please try again.');
      console.error('Error fetching transactions:', err);
    } finally {
      setLoading(false);
    }
  }, [user?.id]);

  // Initial load
  useEffect(() =&amp;gt; {
    fetchUserAccounts();
    fetchTransactions();
  }, [fetchUserAccounts, fetchTransactions]);

  const handleInputChange = (e) =&amp;gt; {
    setForm(prev =&amp;gt; ({
      ...prev,
      [e.target.name]: e.target.value
    }));
  };

  const handleTransfer = () =&amp;gt; {
    // Validation
    if (!form.fromAccountNumber || !form.toAccountNumber || !form.amount || !form.description) {
      toast.error('Please fill in all fields');
      return;
    }

    if (parseFloat(form.amount) &amp;lt;= 0) {
      toast.error('Amount must be greater than 0');
      return;
    }

    if (form.fromAccountNumber === form.toAccountNumber) {
      toast.error('From and To accounts cannot be the same');
      return;
    }

    setModalOpen(true);
  };

  const confirmTransfer = async () =&amp;gt; {
    try {
      setTransferring(true);

      const transferData = {
        fromAccountNumber: form.fromAccountNumber,
        toAccountNumber: form.toAccountNumber,
        amount: parseFloat(form.amount),
        description: form.description
      };

      const response = await api.post('/transactions/transfer', transferData);

      // Update transactions list with new transaction
      setTransactions(prev =&amp;gt; [response.data.data, ...prev]);

      // Invalidate accounts query to refresh balances
      invalidateQueries(['accounts']);

      toast.success('Money transferred successfully');

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

      setModalOpen(false);
    } catch (err) {
      console.error('Transfer error:', err);
      toast.error('Transfer failed. Please try again.');
    } finally {
      setTransferring(false);
    }
  };

  const cancelTransfer = () =&amp;gt; {
    toast.info('Transfer cancelled');
    setModalOpen(false);
  };

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

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

  return (
    &amp;lt;Container
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.6 }}
    &amp;gt;
      &amp;lt;h2&amp;gt;Money Transfer&amp;lt;/h2&amp;gt;

      &amp;lt;FormContainer
        initial={{ opacity: 0, scale: 0.95 }}
        animate={{ opacity: 1, scale: 1 }}
        transition={{ delay: 0.1, duration: 0.5 }}
      &amp;gt;
        &amp;lt;Select
          name="fromAccountNumber"
          value={form.fromAccountNumber}
          onChange={handleInputChange}
          disabled={accountsLoading}
        &amp;gt;
          &amp;lt;option value=""&amp;gt;Select From Account&amp;lt;/option&amp;gt;
          {userAccounts.map(account =&amp;gt; (
            &amp;lt;option key={account.accountNumber} value={account.accountNumber}&amp;gt;
              {account.accountNumber} ({account.accountType})
            &amp;lt;/option&amp;gt;
          ))}
        &amp;lt;/Select&amp;gt;

        &amp;lt;Input
          name="toAccountNumber"
          value={form.toAccountNumber}
          placeholder="To Account Number"
          onChange={handleInputChange}
        /&amp;gt;

        &amp;lt;Input
          name="amount"
          value={form.amount}
          type="number"
          placeholder="Amount"
          onChange={handleInputChange}
          min="0"
          step="0.01"
        /&amp;gt;

        &amp;lt;Input
          name="description"
          value={form.description}
          placeholder="Description"
          onChange={handleInputChange}
        /&amp;gt;

        &amp;lt;TransferButton
          onClick={handleTransfer}
          disabled={transferring || accountsLoading}
          whileHover={{ scale: 1.02 }}
          whileTap={{ scale: 0.98 }}
        &amp;gt;
          &amp;lt;Send size={18} /&amp;gt;
          {transferring ? 'Processing...' : 'Transfer'}
        &amp;lt;/TransferButton&amp;gt;
      &amp;lt;/FormContainer&amp;gt;

      &amp;lt;TableContainer&amp;gt;
        {loading ? (
          &amp;lt;LoadingSpinner
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
          &amp;gt;
            &amp;lt;RefreshCw size={32} /&amp;gt;
            &amp;lt;p style={{ marginLeft: spacing.lg, fontSize: '18px', fontWeight: '500' }}&amp;gt;
              Loading transfers...
            &amp;lt;/p&amp;gt;
          &amp;lt;/LoadingSpinner&amp;gt;
        ) : error ? (
          &amp;lt;ErrorMessage
            initial={{ opacity: 0, scale: 0.95 }}
            animate={{ opacity: 1, scale: 1 }}
          &amp;gt;
            &amp;lt;AlertCircle size={48} /&amp;gt;
            &amp;lt;h3&amp;gt;Something went wrong&amp;lt;/h3&amp;gt;
            &amp;lt;p&amp;gt;{error}&amp;lt;/p&amp;gt;
            &amp;lt;TransferButton
              onClick={fetchTransactions}
              whileHover={{ scale: 1.02 }}
              whileTap={{ scale: 0.98 }}
            &amp;gt;
              &amp;lt;RefreshCw size={16} /&amp;gt;
              Try Again
            &amp;lt;/TransferButton&amp;gt;
          &amp;lt;/ErrorMessage&amp;gt;
        ) : transactions.length === 0 ? (
          &amp;lt;EmptyState
            initial={{ opacity: 0, scale: 0.95 }}
            animate={{ opacity: 1, scale: 1 }}
          &amp;gt;
            &amp;lt;Filter size={48} /&amp;gt;
            &amp;lt;h3&amp;gt;No transfers found&amp;lt;/h3&amp;gt;
            &amp;lt;p&amp;gt;Start your first transfer using the form above&amp;lt;/p&amp;gt;
          &amp;lt;/EmptyState&amp;gt;
        ) : (
          &amp;lt;Table&amp;gt;
            &amp;lt;thead&amp;gt;
              &amp;lt;tr&amp;gt;
                &amp;lt;th&amp;gt;#&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;ID&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;From&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;To&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;Amount&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;Status&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;Date&amp;lt;/th&amp;gt;
                &amp;lt;th&amp;gt;Description&amp;lt;/th&amp;gt;
              &amp;lt;/tr&amp;gt;
            &amp;lt;/thead&amp;gt;
            &amp;lt;tbody&amp;gt;
              {transactions.map((transaction, idx) =&amp;gt; (
                &amp;lt;motion.tr
                  key={transaction.id}
                  initial={{ opacity: 0, y: 10 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{ duration: 0.3, delay: idx * 0.05 }}
                &amp;gt;
                  &amp;lt;td&amp;gt;{idx + 1}&amp;lt;/td&amp;gt;
                  &amp;lt;td&amp;gt;
                    &amp;lt;code style={{
                      background: colors.shadowHover,
                      padding: '4px 8px',
                      borderRadius: '6px',
                      fontSize: '14px',
                      fontWeight: '600'
                    }}&amp;gt;
                      T{String(transaction.id).padStart(3, '0')}
                    &amp;lt;/code&amp;gt;
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td&amp;gt;
                    &amp;lt;code style={{
                      background: colors.shadowHover,
                      padding: '4px 8px',
                      borderRadius: '6px',
                      fontSize: '14px',
                      fontWeight: '600'
                    }}&amp;gt;
                      {transaction.fromAccount?.accountNumber || '-'}
                    &amp;lt;/code&amp;gt;
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td&amp;gt;
                    &amp;lt;code style={{
                      background: colors.shadowHover,
                      padding: '4px 8px',
                      borderRadius: '6px',
                      fontSize: '14px',
                      fontWeight: '600'
                    }}&amp;gt;
                      {transaction.toAccount?.accountNumber || '-'}
                    &amp;lt;/code&amp;gt;
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td style={{
                    fontWeight: '600',
                    color: colors.primary
                  }}&amp;gt;
                    {formatCurrency(transaction.amount)}
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td&amp;gt;
                    &amp;lt;StatusBadge status={transaction.status}&amp;gt;
                      {transaction.status}
                    &amp;lt;/StatusBadge&amp;gt;
                    {transaction.new &amp;amp;&amp;amp; &amp;lt;NewTag&amp;gt;new&amp;lt;/NewTag&amp;gt;}
                  &amp;lt;/td&amp;gt;
                  &amp;lt;td&amp;gt;{formatDate(transaction.date)}&amp;lt;/td&amp;gt;
                  &amp;lt;td&amp;gt;{transaction.description}&amp;lt;/td&amp;gt;
                &amp;lt;/motion.tr&amp;gt;
              ))}
            &amp;lt;/tbody&amp;gt;
          &amp;lt;/Table&amp;gt;
        )}
      &amp;lt;/TableContainer&amp;gt;

      &amp;lt;ConfirmModal
        isOpen={modalOpen}
        onConfirm={confirmTransfer}
        onCancel={cancelTransfer}
        title="Confirm Transfer"
        message={`Transfer ${formatCurrency(parseFloat(form.amount) || 0)} from ${form.fromAccountNumber} to ${form.toAccountNumber}?`}
        loading={transferring}
      /&amp;gt;
    &amp;lt;/Container&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>frontend2</title>
      <dc:creator>Nebula</dc:creator>
      <pubDate>Wed, 25 Jun 2025 19:16:54 +0000</pubDate>
      <link>https://dev.to/nebula_3108/frontend2-1ph4</link>
      <guid>https://dev.to/nebula_3108/frontend2-1ph4</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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 = () =&amp;gt; {
    return "TXN" + Math.floor(100000 + Math.random() * 900000).toString();
  };

  // Validate form
  const validateForm = () =&amp;gt; {
    const newErrors = {};

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

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

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

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

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

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

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

    setToasts(prev =&amp;gt; [...prev, newToast]);

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

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

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

    setIsModalOpen(true);
  };

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

    try {
      // Simulate API call
      await new Promise(resolve =&amp;gt; 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 =&amp;gt; [...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 = () =&amp;gt; {
    setForm({
      toAccount: "",
      amount: "",
      description: ""
    });
    setErrors({});
  };

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

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

  return (
    &amp;lt;&amp;gt;
      &amp;lt;Container
        variants={containerVariants}
        initial="initial"
        animate="animate"
      &amp;gt;
        &amp;lt;h2&amp;gt;Deposit Funds&amp;lt;/h2&amp;gt;

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

          &amp;lt;InputGroup&amp;gt;
            &amp;lt;Label htmlFor="amount"&amp;gt;Amount&amp;lt;/Label&amp;gt;
            &amp;lt;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
              }}
            /&amp;gt;
            {errors.amount &amp;amp;&amp;amp; (
              &amp;lt;span style={{ color: '#ff6b6b', fontSize: '14px', marginTop: '4px' }}&amp;gt;
                {errors.amount}
              &amp;lt;/span&amp;gt;
            )}
          &amp;lt;/InputGroup&amp;gt;

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

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

            &amp;lt;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'
              }}
            &amp;gt;
              &amp;lt;Trash2 size={18} /&amp;gt;
              Clear
            &amp;lt;/CreateButton&amp;gt;
          &amp;lt;/div&amp;gt;
        &amp;lt;/Form&amp;gt;

        &amp;lt;h2 style={{ marginTop: '48px', marginBottom: '24px' }}&amp;gt;All Deposits&amp;lt;/h2&amp;gt;

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

      &amp;lt;Modal
        isOpen={isModalOpen}
        onClose={() =&amp;gt; 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"
      /&amp;gt;

      &amp;lt;ToastComponent 
        toasts={toasts} 
        removeToast={removeToast} 
      /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default Deposit;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
