DEV Community

AI Bug Slayer 🐞
AI Bug Slayer 🐞

Posted on

KendoReact Components Uses

This is a submission for the KendoReact Free Components Challenge.

What I Built

Here is the list of all KendoReact free components used in the previous App.jsx:

1️⃣ AppBar - Used for the top navigation bar displaying the store title and user actions.

2️⃣ Avatar - Displays the user’s profile image in the AppBar.

3️⃣ PanelBar - Provides collapsible panels for categories, sizes, and colors in the filter section.

4️⃣ PanelBarItem - Individual items within the PanelBar for organizing filter options.

5️⃣ Card - Used for displaying cart contents, collections, and other boxed content.

6️⃣ GridLayout - Organizes products in a grid layout within ExpansionPanels.

7️⃣ GridLayoutItem - Defines individual items within the GridLayout for product cards.

8️⃣ StackLayout - Aligns elements horizontally or vertically (e.g., in filters, footer).

9️⃣ TabStrip - Creates tabs for Shop, Wishlist, and Profile sections.

🔟 TabStripTab - Individual tabs within the TabStrip component.

1️⃣1️⃣ Drawer - Side navigation menu for additional options like Home and Contact.

1️⃣2️⃣ DrawerItem - Items within the Drawer for navigation links.

1️⃣3️⃣ ExpansionPanel - Collapsible sections for displaying multiple product collections.

1️⃣4️⃣ Breadcrumb - Shows navigation path (e.g., Home > Shop > Category).

1️⃣5️⃣ BottomNavigation - Footer navigation bar with Home, Cart, and Profile links.

1️⃣6️⃣ BottomNavigationItem - Individual items in the BottomNavigation.

1️⃣7️⃣ TileLayout - Used for the promotional banner section.

1️⃣8️⃣ TileLayoutItem - Individual tiles within the TileLayout.

1️⃣9️⃣ Menu - Dropdown menu for additional navigation options (e.g., Shop More).

2️⃣0️⃣ MenuItem - Items within the Menu component.

2️⃣1️⃣ Button - General-purpose buttons for actions like adding to cart, submitting forms, etc.

2️⃣2️⃣ ButtonGroup - Groups buttons together (e.g., in Grid actions).

2️⃣3️⃣ DropDownList - Dropdown selection for sorting, sizes, and colors.

2️⃣4️⃣ AutoComplete - Search input with autocomplete suggestions from product names.

2️⃣5️⃣ NumericTextBox - Numeric input for quantity selection and review ratings.

2️⃣6️⃣ Input - Text input for search, login, shipping, and payment fields.

2️⃣7️⃣ Switch - Toggle for showing/hiding advanced filters.

2️⃣8️⃣ Checkbox - Checkbox for advanced filter options (e.g., "In Stock Only").

2️⃣9️⃣ RadioButton - Individual radio buttons within RadioButtonGroup.

3️⃣0️⃣ RadioButtonGroup - Group of radio buttons for filter options (e.g., New/Sale).

3️⃣1️⃣ Slider - Slider for selecting a price range in advanced filters.

3️⃣2️⃣ TextArea - Text area for writing reviews or contact messages.

3️⃣3️⃣ Calendar - Calendar picker for selecting delivery dates (not used in final UI but imported).

3️⃣4️⃣ DatePicker - Date picker for selecting delivery dates (not used in final UI but imported).

3️⃣5️⃣ DateInput - Manual date input field (not used in final UI but imported).

3️⃣6️⃣ DateTimePicker - Date and time picker for delivery scheduling.

3️⃣7️⃣ Notification - Success notifications for adding to cart or placing an order.

3️⃣8️⃣ Grid - Tabular display for products, cart, wishlist, and order history.

3️⃣9️⃣ GridColumn - Defines columns within the Grid component.

4️⃣0️⃣ Tooltip - Hover tooltip for filter information button.

4️⃣1️⃣ Popover - Popover component (imported but not used in final UI).

4️⃣2️⃣ ListBox - List selection for categories, sizes, and colors in the PanelBar.

4️⃣3️⃣ Badge - Badge for displaying cart count (not used in final UI but imported).

4️⃣4️⃣ Loader - Loading indicator during checkout processing.

4️⃣5️⃣ Skeleton - Placeholder UI component (not used in final UI but imported).

4️⃣6️⃣ ProgressBar - Progress bar showing cart fill level.

4️⃣7️⃣ Dialog - Modal dialogs for login, product details, checkout, order history, wishlist, and contact form.

4️⃣8️⃣ SvgIcon - SVG icons for Home, User, Cart, Calendar, Email, Star, Search, Menu, Close, LinkedIn, GitHub, Twitter, and Globe.


Total Components Used: 48


App.jsx

import React, { useState } from 'react';
import './App.css';

// KendoReact Free Components Imports (Expanded to Use More)
import {
  AppBar,
  Avatar,
  PanelBar,
  PanelBarItem,
  Card,
  GridLayout,
  GridLayoutItem,
  StackLayout,
  TabStrip,
  TabStripTab,
  Drawer,
  DrawerItem,
  ExpansionPanel,
  Breadcrumb,
  BottomNavigation,
  BottomNavigationItem,
  TileLayout,
  TileLayoutItem,
  Menu,
  MenuItem,
} from '@progress/kendo-react-layout';
import { Button, ButtonGroup } from '@progress/kendo-react-buttons';
import { DropDownList, AutoComplete } from '@progress/kendo-react-dropdowns';
import { NumericTextBox, Input, Switch, Checkbox, RadioButton, RadioButtonGroup, Slider, TextArea } from '@progress/kendo-react-inputs';
import { Calendar, DatePicker, DateInput, DateTimePicker } from '@progress/kendo-react-dateinputs';
import { Notification } from '@progress/kendo-react-notification';
import { Grid, GridColumn } from '@progress/kendo-react-grid';
import { Tooltip, Popover } from '@progress/kendo-react-tooltip';
import { ListBox } from '@progress/kendo-react-listbox';
import { Badge, Loader, Skeleton } from '@progress/kendo-react-indicators';
import { ProgressBar } from '@progress/kendo-react-progressbars';
import { Dialog } from '@progress/kendo-react-dialogs';
import { SvgIcon } from '@progress/kendo-react-common';
import {
  homeIcon,
  userIcon,
  cartIcon,
  calendarIcon,
  emailIcon,
  starIcon,
  searchIcon,
  menuIcon,
  closeIcon,
  linkedinIcon,
  githubIcon,
  twitterIcon,
  globeIcon,
} from '@progress/kendo-svg-icons';

function App() {
  // Sample T-Shirt Products (Expanded Massively)
  const sampleProducts = Array.from({ length: 100 }, (_, i) => ({
    id: i + 1,
    name: `T-Shirt ${i + 1}`,
    price: (15 + i * 0.5).toFixed(2),
    category: ['Men', 'Women', 'Kids'][i % 3],
    stock: Math.floor(Math.random() * 100),
    description: `A premium T-shirt for ${['casual wear', 'sports', 'style'][i % 3]}.`,
    rating: (3.5 + Math.random() * 1.5).toFixed(1),
    image: `https://via.placeholder.com/150?text=T-Shirt+${i + 1}`,
    sizes: ['XS', 'S', 'M', 'L', 'XL', 'XXL'],
    colors: ['Red', 'Blue', 'Green', 'Black', 'White'],
  }));

  // Categories and Other Data
  const categories = ['All', 'Men', 'Women', 'Kids'];
  const sortOptions = ['Price Low to High', 'Price High to Low', 'Rating High to Low'];
  const sizes = ['XS', 'S', 'M', 'L', 'XL', 'XXL'];
  const colors = ['Red', 'Blue', 'Green', 'Black', 'White'];

  // State Management (Expanded)
  const [products] = useState(sampleProducts);
  const [selectedCategory, setSelectedCategory] = useState('All');
  const [cart, setCart] = useState([]);
  const [showNotification, setShowNotification] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');
  const [sortOption, setSortOption] = useState('Price Low to High');
  const [quantity, setQuantity] = useState(1);
  const [deliveryDate, setDeliveryDate] = useState(null);
  const [showFilters, setShowFilters] = useState(false);
  const [user, setUser] = useState({ name: 'Guest', email: '', avatar: 'https://via.placeholder.com/50' });
  const [showLogin, setShowLogin] = useState(false);
  const [loginEmail, setLoginEmail] = useState('');
  const [loginPassword, setLoginPassword] = useState('');
  const [showCheckout, setShowCheckout] = useState(false);
  const [checkoutStep, setCheckoutStep] = useState(0);
  const [shippingInfo, setShippingInfo] = useState({ address: '', city: '', zip: '', country: '' });
  const [paymentInfo, setPaymentInfo] = useState({ cardNumber: '', expiry: '', cvv: '', cardHolder: '' });
  const [orderHistory, setOrderHistory] = useState([]);
  const [showOrderHistory, setShowOrderHistory] = useState(false);
  const [selectedProduct, setSelectedProduct] = useState(null);
  const [showProductDetails, setShowProductDetails] = useState(false);
  const [reviews, setReviews] = useState({});
  const [drawerExpanded, setDrawerExpanded] = useState(false);
  const [tabSelected, setTabSelected] = useState(0);
  const [showWishlist, setShowWishlist] = useState(false);
  const [wishlist, setWishlist] = useState([]);
  const [showContactForm, setShowContactForm] = useState(false);
  const [contactForm, setContactForm] = useState({ name: '', email: '', message: '' });
  const [promoCode, setPromoCode] = useState('');
  const [discount, setDiscount] = useState(0);
  const [loading, setLoading] = useState(false);

  // Handlers
  const handleAddToCart = (item) => {
    setCart((prev) => [...prev, { ...item, quantity }]);
    setShowNotification(true);
    setTimeout(() => setShowNotification(false), 3000);
  };

  const handleRemoveFromCart = (index) => {
    setCart((prev) => prev.filter((_, i) => i !== index));
  };

  const handleAddToWishlist = (item) => {
    setWishlist((prev) => [...prev, item]);
  };

  const handleRemoveFromWishlist = (index) => {
    setWishlist((prev) => prev.filter((_, i) => i !== index));
  };

  const handleLogin = () => {
    if (loginEmail && loginPassword) {
      setUser({ name: loginEmail.split('@')[0], email: loginEmail, avatar: 'https://via.placeholder.com/50' });
      setShowLogin(false);
    }
  };

  const handleCheckout = () => {
    if (checkoutStep === 0 && shippingInfo.address && shippingInfo.city && shippingInfo.zip) {
      setCheckoutStep(1);
    } else if (checkoutStep === 1 && paymentInfo.cardNumber && paymentInfo.expiry && paymentInfo.cvv) {
      setCheckoutStep(2);
    } else if (checkoutStep === 2) {
      setLoading(true);
      setTimeout(() => {
        const total = cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
        const finalTotal = total - (total * discount) / 100;
        const order = {
          id: Date.now(),
          items: [...cart],
          total: finalTotal.toFixed(2),
          date: new Date().toLocaleDateString(),
          status: 'Pending',
          shipping: { ...shippingInfo },
          payment: { ...paymentInfo },
        };
        setOrderHistory((prev) => [...prev, order]);
        setCart([]);
        setShowCheckout(false);
        setCheckoutStep(0);
        setShowNotification(true);
        setLoading(false);
        setTimeout(() => setShowNotification(false), 3000);
      }, 2000);
    }
  };

  const handleViewProduct = (item) => {
    setSelectedProduct(item);
    setShowProductDetails(true);
  };

  const handleAddReview = (productId, comment, rating) => {
    setReviews((prev) => ({
      ...prev,
      [productId]: [...(prev[productId] || []), { user: user.name, comment, rating }],
    }));
  };

  const handleApplyPromo = () => {
    if (promoCode === 'SAVE20') setDiscount(20);
    else if (promoCode === 'SAVE10') setDiscount(10);
    else setDiscount(0);
  };

  // Filtering and Sorting
  const filteredProducts = searchQuery
    ? products.filter((p) => p.name.toLowerCase().includes(searchQuery.toLowerCase()))
    : selectedCategory === 'All'
    ? products
    : products.filter((p) => p.category === selectedCategory);

  const sortedProducts = [...filteredProducts].sort((a, b) => {
    if (sortOption === 'Price Low to High') return a.price - b.price;
    if (sortOption === 'Price High to Low') return b.price - a.price;
    return b.rating - a.rating;
  });

  return (
    <div className="App">
      {/* AppBar */}
      <AppBar className="appbar">
        <Button icon="menu" onClick={() => setDrawerExpanded(!drawerExpanded)} />
        <Avatar type="image" shape="circle" size="medium" imageUrl={user.avatar} onClick={() => setShowLogin(true)} />
        <h1>T-Shirt Mega Store</h1>
        <StackLayout gap={10} orientation="horizontal" className="appbar-actions">
          <Button onClick={() => setShowWishlist(true)}>
            <SvgIcon icon={starIcon} /> Wishlist ({wishlist.length})
          </Button>
          <Button onClick={() => setShowOrderHistory(true)}>
            <SvgIcon icon={calendarIcon} /> Orders
          </Button>
          <Button icon="cart">{cart.length}</Button>
        </StackLayout>
      </AppBar>

      {/* Drawer Navigation */}
      <Drawer
        expanded={drawerExpanded}
        position="start"
        mode="push"
        onOverlayClick={() => setDrawerExpanded(false)}
      >
        <DrawerItem>
          <SvgIcon icon={homeIcon} /> Home
        </DrawerItem>
        <DrawerItem onClick={() => setShowContactForm(true)}>
          <SvgIcon icon={emailIcon} /> Contact Us
        </DrawerItem>
        <DrawerItem onClick={() => setShowWishlist(true)}>
          <SvgIcon icon={starIcon} /> Wishlist
        </DrawerItem>
      </Drawer>

      <div className="content">
        {/* Promotional Banner */}
        <TileLayout columns={1} gap={10}>
          <TileLayoutItem>
            <div className="promo-banner">
              <h2>Summer Sale Extravaganza!</h2>
              <p>Use code SAVE20 for 20% off!</p>
            </div>
          </TileLayoutItem>
        </TileLayout>

        {/* Breadcrumb */}
        <Breadcrumb items={[{ text: 'Home' }, { text: 'Shop' }, { text: selectedCategory }]} />

        {/* Main Content Tabs */}
        <TabStrip selected={tabSelected} onSelect={(e) => setTabSelected(e.selected)}>
          <TabStripTab title="Shop">
            {/* Filters */}
            <GridLayout cols={[{ width: '25%' }, { width: '75%' }]} gap={{ rows: 10, cols: 10 }}>
              <GridLayoutItem>
                <PanelBar>
                  <PanelBarItem title="Categories">
                    <ListBox
                      data={categories}
                      value={selectedCategory}
                      onChange={(e) => setSelectedCategory(e.value)}
                    />
                  </PanelBarItem>
                  <PanelBarItem title="Sizes">
                    <ListBox data={sizes} />
                  </PanelBarItem>
                  <PanelBarItem title="Colors">
                    <ListBox data={colors} />
                  </PanelBarItem>
                </PanelBar>
              </GridLayoutItem>
              <GridLayoutItem>
                <StackLayout gap={15} orientation="horizontal" className="filters">
                  <AutoComplete data={products.map((p) => p.name)} value={searchQuery} onChange={(e) => setSearchQuery(e.value)} placeholder="Search..." />
                  <DropDownList data={sortOptions} value={sortOption} onChange={(e) => setSortOption(e.value)} />
                  <NumericTextBox min={1} value={quantity} onChange={(e) => setQuantity(e.value || 1)} />
                  <DateTimePicker value={deliveryDate} onChange={(e) => setDeliveryDate(e.value)} />
                  <Switch checked={showFilters} onChange={(e) => setShowFilters(e.checked)} label="Advanced Filters" />
                  <Tooltip anchorElement="target" position="top">
                    <Button title="Filter Info"><SvgIcon icon={searchIcon} /></Button>
                  </Tooltip>
                </StackLayout>

                {/* Advanced Filters */}
                {showFilters && (
                  <ExpansionPanel title="Advanced Filters">
                    <StackLayout gap={10}>
                      <Checkbox label="In Stock Only" />
                      <RadioButtonGroup
                        data={[{ label: 'New', value: 'new' }, { label: 'Sale', value: 'sale' }]}
                        defaultValue="new"
                      />
                      <Slider min={0} max={50} step={5} defaultValue={20} />
                    </StackLayout>
                  </ExpansionPanel>
                )}

                {/* Product Grid */}
                <Grid data={sortedProducts.slice(0, 50)} className="product-grid">
                  <GridColumn field="name" title="Name" />
                  <GridColumn field="price" title="Price" cell={(props) => <td>${props.dataItem.price}</td>} />
                  <GridColumn field="category" title="Category" />
                  <GridColumn field="stock" title="Stock" />
                  <GridColumn field="rating" title="Rating" cell={(props) => <td>{props.dataItem.rating} <SvgIcon icon={starIcon} /></td>} />
                  <GridColumn
                    title="Actions"
                    cell={(props) => (
                      <td>
                        <ButtonGroup>
                          <Button onClick={() => handleAddToCart(props.dataItem)}><SvgIcon icon={cartIcon} /></Button>
                          <Button onClick={() => handleViewProduct(props.dataItem)}>View</Button>
                          <Button onClick={() => handleAddToWishlist(props.dataItem)}><SvgIcon icon={starIcon} /></Button>
                        </ButtonGroup>
                      </td>
                    )}
                  />
                </Grid>
              </GridLayoutItem>
            </GridLayout>

            {/* Cart */}
            <Card className="cart">
              <h3>Your Cart</h3>
              {cart.length === 0 ? (
                <p>Empty</p>
              ) : (
                <>
                  <Grid data={cart}>
                    <GridColumn field="name" title="Item" />
                    <GridColumn field="price" title="Price" cell={(props) => <td>${props.dataItem.price}</td>} />
                    <GridColumn field="quantity" title="Qty" />
                    <GridColumn
                      title="Remove"
                      cell={(props) => <td><Button onClick={() => handleRemoveFromCart(props.dataIndex)}>Remove</Button></td>}
                    />
                  </Grid>
                  <p>Total: ${cart.reduce((sum, item) => sum + item.price * item.quantity, 0).toFixed(2)}</p>
                  <Input placeholder="Promo Code" value={promoCode} onChange={(e) => setPromoCode(e.value)} />
                  <Button onClick={handleApplyPromo}>Apply Promo</Button>
                  <p>Discount: {discount}%</p>
                  <Button onClick={() => setShowCheckout(true)}>Checkout</Button>
                </>
              )}
            </Card>
          </TabStripTab>

          <TabStripTab title="Wishlist">
            <Grid data={wishlist}>
              <GridColumn field="name" title="Name" />
              <GridColumn field="price" title="Price" cell={(props) => <td>${props.dataItem.price}</td>} />
              <GridColumn
                title="Actions"
                cell={(props) => (
                  <td>
                    <Button onClick={() => handleAddToCart(props.dataItem)}>Add to Cart</Button>
                    <Button onClick={() => handleRemoveFromWishlist(props.dataIndex)}>Remove</Button>
                  </td>
                )}
              />
            </Grid>
          </TabStripTab>

          <TabStripTab title="Profile">
            <Card>
              <h3>User Profile</h3>
              <p>Name: {user.name}</p>
              <p>Email: {user.email || 'Not logged in'}</p>
              <Button onClick={() => setShowLogin(true)}>Login/Update</Button>
            </Card>
          </TabStripTab>
        </TabStrip>

        {/* Modals */}
        {showLogin && (
          <Dialog title="Login" onClose={() => setShowLogin(false)}>
            <StackLayout gap={10}>
              <Input placeholder="Email" value={loginEmail} onChange={(e) => setLoginEmail(e.value)} />
              <Input type="password" placeholder="Password" value={loginPassword} onChange={(e) => setLoginPassword(e.value)} />
              <Button onClick={handleLogin}>Login</Button>
            </StackLayout>
          </Dialog>
        )}

        {showProductDetails && selectedProduct && (
          <Dialog title={selectedProduct.name} onClose={() => setShowProductDetails(false)} width={500}>
            <img src={selectedProduct.image} alt={selectedProduct.name} className="product-image" />
            <p>{selectedProduct.description}</p>
            <p>Price: ${selectedProduct.price}</p>
            <p>Rating: {selectedProduct.rating} <SvgIcon icon={starIcon} /></p>
            <DropDownList data={selectedProduct.sizes} defaultValue="M" />
            <DropDownList data={selectedProduct.colors} defaultValue="Black" />
            <Button onClick={() => handleAddToCart(selectedProduct)}>Add to Cart</Button>
            <ExpansionPanel title="Reviews">
              {(reviews[selectedProduct.id] || []).map((r, i) => (
                <p key={i}>{r.user}: {r.comment} ({r.rating}/5)</p>
              ))}
              <TextArea placeholder="Add a review" />
              <NumericTextBox min={1} max={5} defaultValue={5} />
              <Button onClick={() => handleAddReview(selectedProduct.id, 'Great!', 5)}>Submit Review</Button>
            </ExpansionPanel>
          </Dialog>
        )}

        {showCheckout && (
          <Dialog title="Checkout" onClose={() => setShowCheckout(false)} width={600}>
            {loading ? <Loader /> : (
              <>
                <div className="checkout-steps">
                  <span className={checkoutStep === 0 ? 'active' : ''}>Shipping</span>
                  <span className={checkoutStep === 1 ? 'active' : ''}>Payment</span>
                  <span className={checkoutStep === 2 ? 'active' : ''}>Confirm</span>
                </div>
                {checkoutStep === 0 && (
                  <StackLayout gap={10}>
                    <Input placeholder="Address" value={shippingInfo.address} onChange={(e) => setShippingInfo({ ...shippingInfo, address: e.value })} />
                    <Input placeholder="City" value={shippingInfo.city} onChange={(e) => setShippingInfo({ ...shippingInfo, city: e.value })} />
                    <Input placeholder="ZIP" value={shippingInfo.zip} onChange={(e) => setShippingInfo({ ...shippingInfo, zip: e.value })} />
                    <Input placeholder="Country" value={shippingInfo.country} onChange={(e) => setShippingInfo({ ...shippingInfo, country: e.value })} />
                  </StackLayout>
                )}
                {checkoutStep === 1 && (
                  <StackLayout gap={10}>
                    <Input placeholder="Card Number" value={paymentInfo.cardNumber} onChange={(e) => setPaymentInfo({ ...paymentInfo, cardNumber: e.value })} />
                    <Input placeholder="Expiry (MM/YY)" value={paymentInfo.expiry} onChange={(e) => setPaymentInfo({ ...paymentInfo, expiry: e.value })} />
                    <Input placeholder="CVV" value={paymentInfo.cvv} onChange={(e) => setPaymentInfo({ ...paymentInfo, cvv: e.value })} />
                    <Input placeholder="Card Holder" value={paymentInfo.cardHolder} onChange={(e) => setPaymentInfo({ ...paymentInfo, cardHolder: e.value })} />
                  </StackLayout>
                )}
                {checkoutStep === 2 && (
                  <>
                    <Grid data={cart}>
                      <GridColumn field="name" title="Item" />
                      <GridColumn field="price" title="Price" cell={(props) => <td>${props.dataItem.price}</td>} />
                      <GridColumn field="quantity" title="Qty" />
                    </Grid>
                    <p>Total: ${(cart.reduce((sum, item) => sum + item.price * item.quantity, 0) * (1 - discount / 100)).toFixed(2)}</p>
                  </>
                )}
                <ButtonGroup>
                  {checkoutStep > 0 && <Button onClick={() => setCheckoutStep(checkoutStep - 1)}>Previous</Button>}
                  <Button onClick={handleCheckout}>{checkoutStep === 2 ? 'Place Order' : 'Next'}</Button>
                </ButtonGroup>
              </>
            )}
          </Dialog>
        )}

        {showOrderHistory && (
          <Dialog title="Order History" onClose={() => setShowOrderHistory(false)} width={700}>
            <Grid data={orderHistory}>
              <GridColumn field="id" title="Order #" />
              <GridColumn field="date" title="Date" />
              <GridColumn field="total" title="Total" />
              <GridColumn field="status" title="Status" />
            </Grid>
          </Dialog>
        )}

        {showContactForm && (
          <Dialog title="Contact Us" onClose={() => setShowContactForm(false)}>
            <StackLayout gap={10}>
              <Input placeholder="Name" value={contactForm.name} onChange={(e) => setContactForm({ ...contactForm, name: e.value })} />
              <Input placeholder="Email" value={contactForm.email} onChange={(e) => setContactForm({ ...contactForm, email: e.value })} />
              <TextArea placeholder="Message" value={contactForm.message} onChange={(e) => setContactForm({ ...contactForm, message: e.value })} />
              <Button onClick={() => alert('Message Sent!')}>Send</Button>
            </StackLayout>
          </Dialog>
        )}

        {showWishlist && (
          <Dialog title="Wishlist" onClose={() => setShowWishlist(false)}>
            <Grid data={wishlist}>
              <GridColumn field="name" title="Name" />
              <GridColumn field="price" title="Price" cell={(props) => <td>${props.dataItem.price}</td>} />
              <GridColumn
                title="Actions"
                cell={(props) => <td><Button onClick={() => handleAddToCart(props.dataItem)}>Add to Cart</Button></td>}
              />
            </Grid>
          </Dialog>
        )}

        {/* Notification */}
        {showNotification && (
          <Notification type={{ style: 'success', icon: true }} closable={true}>
            {checkoutStep === 2 ? 'Order placed!' : 'Added to cart!'}
          </Notification>
        )}

        {/* Massive Additional Content */}
        <Menu>
          <MenuItem text="Shop More" icon="shop">
            <MenuItem text="New Arrivals" />
            <MenuItem text="Best Sellers" />
          </MenuItem>
          <MenuItem text="Support" icon="help" />
        </Menu>

        {Array.from({ length: 20 }, (_, i) => (
          <ExpansionPanel key={i} title={`Collection ${i + 1}`}>
            <GridLayout cols={[{ width: '33%' }, { width: '33%' }, { width: '33%' }]}>
              {products.slice(i * 5, i * 5 + 5).map((p) => (
                <GridLayoutItem key={p.id}>
                  <Card>
                    <img src={p.image} alt={p.name} className="product-image" />
                    <p>{p.name}</p>
                    <p>${p.price}</p>
                    <Button onClick={() => handleAddToCart(p)}>Add</Button>
                  </Card>
                </GridLayoutItem>
              ))}
            </GridLayout>
          </ExpansionPanel>
        ))}

        <ProgressBar value={cart.length * 10} max={100} label="Cart Progress" />

        {/* Bottom Navigation */}
        <BottomNavigation>
          <BottomNavigationItem icon="home" text="Home" />
          <BottomNavigationItem icon="cart" text="Cart" onClick={() => setShowCheckout(true)} />
          <BottomNavigationItem icon="user" text="Profile" onClick={() => setShowLogin(true)} />
        </BottomNavigation>

        {/* Footer */}
        <footer className="footer">
          <h3>Owner: Aniruddha Adak</h3>
          <StackLayout gap={20} orientation="horizontal" className="social-links">
            <a href="https://www.linkedin.com/in/aniruddha-adak" target="_blank" rel="noopener noreferrer">
              <SvgIcon icon={linkedinIcon} size="large" />
            </a>
            <a href="https://github.com/AniruddhaAdak" target="_blank" rel="noopener noreferrer">
              <SvgIcon icon={githubIcon} size="large" />
            </a>
            <a href="https://x.com/aniruddhadak" target="_blank" rel="noopener noreferrer">
              <SvgIcon icon={twitterIcon} size="large" />
            </a>
            <a href="https://dev.to/aniruddhaadak" target="_blank" rel="noopener noreferrer">
              <SvgIcon icon={globeIcon} size="large" />
            </a>
            <a href="https://aniruddha-adak.vercel.app" target="_blank" rel="noopener noreferrer">
              <SvgIcon icon={userIcon} size="large" />
            </a>
            <a href="mailto:aniruddhaadak80@gmail.com">
              <SvgIcon icon={emailIcon} size="large" />
            </a>
          </StackLayout>
          <p>&copy; 2025 Aniruddha Adak. All rights reserved.</p>
        </footer>
      </div>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

App.css

/* General Styles */
.App {
  font-family: 'Roboto', Arial, sans-serif;
  background: linear-gradient(135deg, #f0f4f8, #d9e2ec);
  min-height: 100vh;
  color: #333;
}

h1, h2, h3 {
  color: #2c3e50;
}

.content {
  max-width: 1400px;
  margin: 0 auto;
  padding: 20px;
}

/* AppBar */
.appbar {
  background: #2980b9 !important;
  padding: 15px 20px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}

.appbar-actions {
  margin-left: auto;
}

/* Drawer */
.k-drawer {
  background: #34495e;
  color: white;
}

.k-drawer-item:hover {
  background: #3e5f7e;
}

/* Promo Banner */
.promo-banner {
  background: #f1c40f;
  padding: 20px;
  text-align: center;
  border-radius: 8px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}

/* Filters */
.filters {
  background: #fff;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 3px 15px rgba(0, 0, 0, 0.1);
  flex-wrap: wrap;
}

/* Grid */
.product-grid {
  background: #fff;
  border-radius: 8px;
  overflow-x: auto;
}

.k-grid th {
  background: #3498db;
  color: white;
}

.k-grid td {
  border-bottom: 1px solid #ecf0f1;
}

/* Card */
.cart, .k-card {
  background: #fff;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 3px 15px rgba(0, 0, 0, 0.1);
  margin: 20px 0;
}

/* Dialog */
.k-dialog {
  border-radius: 8px;
  box-shadow: 0 5px 20px rgba(0, 0, 0, 0.3);
}

.checkout-steps {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}

.checkout-steps span {
  padding: 8px 15px;
  background: #ddd;
  border-radius: 20px;
}

.checkout-steps .active {
  background: #2980b9;
  color: white;
}

/* Product Image */
.product-image {
  width: 100%;
  max-height: 250px;
  object-fit: cover;
  border-radius: 8px;
}

/* Footer */
.footer {
  background: #2c3e50;
  color: white;
  padding: 40px 20px;
  text-align: center;
  margin-top: 40px;
  border-top: 4px solid #3498db;
}

.social-links .k-svg-icon {
  font-size: 32px !important;
  color: #ecf0f1;
  transition: color 0.3s;
}

.social-links .k-svg-icon:hover {
  color: #3498db;
}

/* Responsive Design */
@media (max-width: 1024px) {
  .content {
    padding: 15px;
  }

  .filters {
    flex-direction: column;
    gap: 10px;
  }

  .k-grid {
    font-size: 14px;
  }

  .k-dialog {
    width: 90% !important;
  }
}

@media (max-width: 768px) {
  .appbar {
    flex-direction: column;
    align-items: flex-start;
    padding: 10px;
  }

  .appbar-actions {
    margin-top: 10px;
    width: 100%;
    justify-content: space-between;
  }

  .promo-banner {
    padding: 15px;
  }

  .k-grid th, .k-grid td {
    padding: 8px;
  }

  .footer {
    padding: 20px;
  }

  .social-links {
    flex-wrap: wrap;
    gap: 15px;
  }
}

@media (max-width: 480px) {
  h1 { font-size: 20px; }
  h2 { font-size: 18px; }
  h3 { font-size: 16px; }
  p { font-size: 12px; }

  .filters {
    padding: 10px;
  }

  .k-button {
    padding: 6px 12px;
    font-size: 12px;
  }

  .product-image {
    max-height: 150px;
  }

  .social-links .k-svg-icon {
    font-size: 24px !important;
  }
}

Enter fullscreen mode Exit fullscreen mode

Heroku

Deploy with ease. Manage efficiently. Scale faster.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

🌶️ Newest Episode of Leet Heat: A Game Show For Developers!

Contestants face rapid-fire full stack web dev questions. Wrong answers? The spice level goes up. Can they keep cool while eating progressively hotter sauces?

View Episode Post

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️