fix: Remove demo pages and add testDataService for production build
This commit is contained in:
@@ -1,839 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from 'primereact/button';
|
||||
import { Checkbox } from 'primereact/checkbox';
|
||||
import { Chip } from 'primereact/chip';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import React, { useState } from 'react';
|
||||
import BlockViewer from '../../../demo/components/BlockViewer';
|
||||
|
||||
const BlocksDemo = () => {
|
||||
const [checked, setChecked] = useState(false);
|
||||
|
||||
const block1 = `
|
||||
<div className="grid grid-nogutter surface-section text-800">
|
||||
<div className="col-12 md:col-6 p-6 text-center md:text-left flex align-items-center ">
|
||||
<section>
|
||||
<span className="block text-6xl font-bold mb-1">Create the screens</span>
|
||||
<div className="text-6xl text-primary font-bold mb-3">your visitors deserve to see</div>
|
||||
<p className="mt-0 mb-4 text-700 line-height-3">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
|
||||
|
||||
<Button label="Learn More" type="button" className="mr-3" raised />
|
||||
<Button label="Live Demo" type="button" outlined />
|
||||
</section>
|
||||
</div>
|
||||
<div className="col-12 md:col-6 overflow-hidden">
|
||||
<img src="assets/images/blocks/hero/hero-1.png" alt="hero-1" className="md:ml-auto block md:h-full" style={{ clipPath: 'polygon(8% 0, 100% 0%, 100% 100%, 0 100%)' }} />
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const block2 = `
|
||||
<div className="surface-section px-4 py-8 md:px-6 lg:px-8 text-center">
|
||||
<div className="mb-3 font-bold text-3xl">
|
||||
<span className="text-900">One Product, </span>
|
||||
<span className="text-blue-600">Many Solutions</span>
|
||||
</div>
|
||||
<div className="text-700 mb-6">Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.</div>
|
||||
<div className="grid">
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-desktop text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Built for Developers</div>
|
||||
<span className="text-700 line-height-3">Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-lock text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">End-to-End Encryption</div>
|
||||
<span className="text-700 line-height-3">Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis.</span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-check-circle text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Easy to Use</div>
|
||||
<span className="text-700 line-height-3">Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper.</span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-globe text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Fast & Global Support</div>
|
||||
<span className="text-700 line-height-3">Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus.</span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-github text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Open Source</div>
|
||||
<span className="text-700 line-height-3">Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. </span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 md:mb-4 mb-0 px-3">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-shield text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Trusted Securitty</div>
|
||||
<span className="text-700 line-height-3">Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const block3 = `<div className="surface-ground px-4 py-8 md:px-6 lg:px-8">
|
||||
<div className="text-900 font-bold text-6xl mb-4 text-center">Pricing Plans</div>
|
||||
<div className="text-700 text-xl mb-6 text-center line-height-3">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.</div>
|
||||
|
||||
<div className="grid">
|
||||
<div className="col-12 lg:col-4">
|
||||
<div className="p-3 h-full">
|
||||
<div className="shadow-2 p-3 h-full flex flex-column surface-card" style="border-radius: "6px"">
|
||||
<div className="text-900 font-medium text-xl mb-2">Basic</div>
|
||||
<div className="text-600">Plan description</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<div className="flex align-items-center">
|
||||
<span className="font-bold text-2xl text-900">$9</span>
|
||||
<span className="ml-2 font-medium text-600">per month</span>
|
||||
</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<ul className="list-none p-0 m-0 flex-grow-1">
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Arcu vitae elementum</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Dui faucibus in ornare</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Morbi tincidunt augue</span>
|
||||
</li>
|
||||
</ul>
|
||||
<hr className="mb-3 mx-0 border-top-1 border-none surface-border mt-auto" />
|
||||
<Button label="Buy Now" className="p-3 w-full mt-auto"></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12 lg:col-4">
|
||||
<div className="p-3 h-full">
|
||||
<div className="shadow-2 p-3 h-full flex flex-column surface-card" style="border-radius: 6px">
|
||||
<div className="text-900 font-medium text-xl mb-2">Premium</div>
|
||||
<div className="text-600">Plan description</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<div className="flex align-items-center">
|
||||
<span className="font-bold text-2xl text-900">$29</span>
|
||||
<span className="ml-2 font-medium text-600">per month</span>
|
||||
</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<ul className="list-none p-0 m-0 flex-grow-1">
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Arcu vitae elementum</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Dui faucibus in ornare</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Morbi tincidunt augue</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Duis ultricies lacus sed</span>
|
||||
</li>
|
||||
</ul>
|
||||
<hr className="mb-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<Button label="Buy Now" className="p-3 w-full"></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12 lg:col-4">
|
||||
<div className="p-3 h-full">
|
||||
<div className="shadow-2 p-3 flex flex-column surface-card" style="border-radius: 6px">
|
||||
<div className="text-900 font-medium text-xl mb-2">Enterprise</div>
|
||||
<div className="text-600">Plan description</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<div className="flex align-items-center">
|
||||
<span className="font-bold text-2xl text-900">$49</span>
|
||||
<span className="ml-2 font-medium text-600">per month</span>
|
||||
</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<ul className="list-none p-0 m-0 flex-grow-1">
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Arcu vitae elementum</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Dui faucibus in ornare</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Morbi tincidunt augue</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Duis ultricies lacus sed</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Imperdiet proin</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Nisi scelerisque</span>
|
||||
</li>
|
||||
</ul>
|
||||
<hr className="mb-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<Button label="Buy Now" className="p-3 w-full" outlined></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
const block4 = `
|
||||
<div className="surface-section text-700 text-center">
|
||||
<div className="text-blue-600 font-bold mb-3"><i className="pi pi-discord"></i> POWERED BY DISCORD</div>
|
||||
<div className="text-900 font-bold text-5xl mb-3">Join Our Design Community</div>
|
||||
<div className="text-700 text-2xl mb-5">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.</div>
|
||||
<Button label="Join Now" icon="pi pi-discord" className="font-bold px-5 py-3 white-space-nowrap" rounded raised />
|
||||
</div>
|
||||
`;
|
||||
|
||||
const block5 = `
|
||||
<div className="bg-bluegray-900 text-gray-100 p-3 flex justify-content-between lg:justify-content-center align-items-center flex-wrap">
|
||||
<div className="font-bold mr-8">🔥 Hot Deals!</div>
|
||||
<div className="align-items-center hidden lg:flex">
|
||||
<span className="line-height-3">Libero voluptatum atque exercitationem praesentium provident odit.</span>
|
||||
</div>
|
||||
<a className="flex align-items-center ml-2 mr-8">
|
||||
<span className="underline font-bold">Learn More</span>
|
||||
</a>
|
||||
<a className="flex align-items-center no-underline justify-content-center border-circle text-100 hover:bg-bluegray-700 cursor-pointer transition-colors transition-duration-150" style={{ width: '2rem', height: '2rem' }}>
|
||||
<i className="pi pi-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const block6 = `
|
||||
<div className="surface-section">
|
||||
<ul className="list-none p-0 m-0 flex align-items-center font-medium mb-3">
|
||||
<li>
|
||||
<a className="text-500 no-underline line-height-3 cursor-pointer">Application</a>
|
||||
</li>
|
||||
<li className="px-2">
|
||||
<i className="pi pi-angle-right text-500 line-height-3"></i>
|
||||
</li>
|
||||
<li>
|
||||
<span className="text-900 line-height-3">Analytics</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex align-items-start flex-column lg:justify-content-between lg:flex-row">
|
||||
<div>
|
||||
<div className="font-medium text-3xl text-900">Customers</div>
|
||||
<div className="flex align-items-center text-700 flex-wrap">
|
||||
<div className="mr-5 flex align-items-center mt-3">
|
||||
<i className="pi pi-users mr-2"></i>
|
||||
<span>332 Active Users</span>
|
||||
</div>
|
||||
<div className="mr-5 flex align-items-center mt-3">
|
||||
<i className="pi pi-globe mr-2"></i>
|
||||
<span>9402 Sessions</span>
|
||||
</div>
|
||||
<div className="flex align-items-center mt-3">
|
||||
<i className="pi pi-clock mr-2"></i>
|
||||
<span>2.32m Avg. Duration</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3 lg:mt-0">
|
||||
<Button label="Add" className="mr-2" icon="pi pi-user-plus" outlined />
|
||||
<Button label="Save" icon="pi pi-check" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const block7 = `
|
||||
<div className="grid">
|
||||
<div className="col-12 md:col-6 lg:col-3">
|
||||
<div className="surface-section shadow-2 p-3 border-1 border-50 border-round">
|
||||
<div className="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span className="block text-500 font-medium mb-3">Orders</span>
|
||||
<div className="text-900 font-medium text-xl">152</div>
|
||||
</div>
|
||||
<div className="flex align-items-center justify-content-center bg-blue-100 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
|
||||
<i className="pi pi-shopping-cart text-blue-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-green-500 font-medium">24 new </span>
|
||||
<span className="text-500">since last visit</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 md:col-6 lg:col-3">
|
||||
<div className="surface-section shadow-2 p-3 border-1 border-50 border-round">
|
||||
<div className="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span className="block text-500 font-medium mb-3">Revenue</span>
|
||||
<div className="text-900 font-medium text-xl">$2.100</div>
|
||||
</div>
|
||||
<div className="flex align-items-center justify-content-center bg-orange-100 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
|
||||
<i className="pi pi-map-marker text-orange-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-green-500 font-medium">%52+ </span>
|
||||
<span className="text-500">since last week</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 md:col-6 lg:col-3">
|
||||
<div className="surface-section shadow-2 p-3 border-1 border-50 border-round">
|
||||
<div className="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span className="block text-500 font-medium mb-3">Customers</span>
|
||||
<div className="text-900 font-medium text-xl">28441</div>
|
||||
</div>
|
||||
<div className="flex align-items-center justify-content-center bg-cyan-100 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
|
||||
<i className="pi pi-inbox text-cyan-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-green-500 font-medium">520 </span>
|
||||
<span className="text-500">newly registered</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 md:col-6 lg:col-3">
|
||||
<div className="surface-section shadow-2 p-3 border-1 border-50 border-round">
|
||||
<div className="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span className="block text-500 font-medium mb-3">Comments</span>
|
||||
<div className="text-900 font-medium text-xl">152 Unread</div>
|
||||
</div>
|
||||
<div className="flex align-items-center justify-content-center bg-purple-100 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
|
||||
<i className="pi pi-comment text-purple-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-green-500 font-medium">85 </span>
|
||||
<span className="text-500">responded</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const block8 = `
|
||||
<div className="flex align-items-center justify-content-center">
|
||||
<div className="surface-card p-4 shadow-2 border-round w-full lg:w-6">
|
||||
<div className="text-center mb-5">
|
||||
<img src="assets/images/blocks/logos/hyper.svg" alt="hyper" height={50} className="mb-3" />
|
||||
<div className="text-900 text-3xl font-medium mb-3">Welcome Back</div>
|
||||
<span className="text-600 font-medium line-height-3">Do not have an account?</span>
|
||||
<a className="font-medium no-underline ml-2 text-blue-500 cursor-pointer">Create today!</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-900 font-medium mb-2">Email</label>
|
||||
<InputText id="email" type="text" placeholder="Email address" className="w-full mb-3" />
|
||||
|
||||
<label htmlFor="password" className="block text-900 font-medium mb-2">Password</label>
|
||||
<InputText id="password" type="password" placeholder="Password" className="w-full mb-3" />
|
||||
|
||||
<div className="flex align-items-center justify-content-between mb-6">
|
||||
<div className="flex align-items-center">
|
||||
<Checkbox id="rememberme" onChange={e => setChecked(e.checked)} checked={checked} className="mr-2" />
|
||||
<label htmlFor="rememberme" className="text-900">Remember me</label>
|
||||
</div>
|
||||
<a className="font-medium no-underline ml-2 text-blue-500 text-right cursor-pointer">Forgot your password?</a>
|
||||
</div>
|
||||
|
||||
<Button label="Sign In" icon="pi pi-user" className="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const block9 = `
|
||||
<div className="surface-section">
|
||||
<div className="font-medium text-3xl text-900 mb-3">Movie Information</div>
|
||||
<div className="text-500 mb-5">Morbi tristique blandit turpis. In viverra ligula id nulla hendrerit rutrum.</div>
|
||||
<ul className="list-none p-0 m-0">
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Title</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1">Heat</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Genre</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1">
|
||||
<Chip label="Crime" className="mr-2" />
|
||||
<Chip label="Drama" className="mr-2" />
|
||||
<Chip label="Thriller" />
|
||||
</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Director</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1">Michael Mann</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Actors</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1">Robert De Niro, Al Pacino</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-bottom-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Plot</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1 line-height-3">
|
||||
A group of professional bank robbers start to feel the heat from police
|
||||
when they unknowingly leave a clue at their latest heist.</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const block10 = `
|
||||
<div className="surface-card p-4 shadow-2 border-round">
|
||||
<div className="text-3xl font-medium text-900 mb-3">Card Title</div>
|
||||
<div className="font-medium text-500 mb-3">Vivamus id nisl interdum, blandit augue sit amet, eleifend mi.</div>
|
||||
<div style={{ height: '150px' }} className="border-2 border-dashed surface-border"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<BlockViewer header="Hero" code={block1} free>
|
||||
<div className="grid grid-nogutter surface-section text-800">
|
||||
<div className="col-12 md:col-6 p-6 text-center md:text-left flex align-items-center ">
|
||||
<section>
|
||||
<span className="block text-6xl font-bold mb-1">Create the screens</span>
|
||||
<div className="text-6xl text-primary font-bold mb-3">your visitors deserve to see</div>
|
||||
<p className="mt-0 mb-4 text-700 line-height-3">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
|
||||
|
||||
<Button label="Learn More" type="button" className="mr-3" raised />
|
||||
<Button label="Live Demo" type="button" outlined />
|
||||
</section>
|
||||
</div>
|
||||
<div className="col-12 md:col-6 overflow-hidden">
|
||||
<img src="/demo/images/blocks/hero/hero-1.png" alt="hero-1" className="md:ml-auto block md:h-full" style={{ clipPath: 'polygon(8% 0, 100% 0%, 100% 100%, 0 100%)' }} />
|
||||
</div>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<BlockViewer header="Feature" code={block2} free>
|
||||
<div className="surface-section px-4 py-8 md:px-6 lg:px-8 text-center">
|
||||
<div className="mb-3 font-bold text-3xl">
|
||||
<span className="text-900">One Product, </span>
|
||||
<span className="text-blue-600">Many Solutions</span>
|
||||
</div>
|
||||
<div className="text-700 mb-6">Ac turpis egestas maecenas pharetra convallis posuere morbi leo urna.</div>
|
||||
<div className="grid">
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-desktop text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Built for Developers</div>
|
||||
<span className="text-700 line-height-3">Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-lock text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">End-to-End Encryption</div>
|
||||
<span className="text-700 line-height-3">Risus nec feugiat in fermentum posuere urna nec. Posuere sollicitudin aliquam ultrices sagittis.</span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-check-circle text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Easy to Use</div>
|
||||
<span className="text-700 line-height-3">Ornare suspendisse sed nisi lacus sed viverra tellus. Neque volutpat ac tincidunt vitae semper.</span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-globe text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Fast & Global Support</div>
|
||||
<span className="text-700 line-height-3">Fermentum et sollicitudin ac orci phasellus egestas tellus rutrum tellus.</span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 mb-4 px-5">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-github text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Open Source</div>
|
||||
<span className="text-700 line-height-3">Nec tincidunt praesent semper feugiat. Sed adipiscing diam donec adipiscing tristique risus nec feugiat. </span>
|
||||
</div>
|
||||
<div className="col-12 md:col-4 md:mb-4 mb-0 px-3">
|
||||
<span className="p-3 shadow-2 mb-3 inline-block surface-card" style={{ borderRadius: '10px' }}>
|
||||
<i className="pi pi-shield text-4xl text-blue-500"></i>
|
||||
</span>
|
||||
<div className="text-900 text-xl mb-3 font-medium">Trusted Securitty</div>
|
||||
<span className="text-700 line-height-3">Mattis rhoncus urna neque viverra justo nec ultrices. Id cursus metus aliquam eleifend.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<BlockViewer header="Pricing" code={block3} free>
|
||||
<div className="surface-ground px-4 py-8 md:px-6 lg:px-8">
|
||||
<div className="text-900 font-bold text-6xl mb-4 text-center">Pricing Plans</div>
|
||||
<div className="text-700 text-xl mb-6 text-center line-height-3">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.</div>
|
||||
|
||||
<div className="grid">
|
||||
<div className="col-12 lg:col-4">
|
||||
<div className="p-3 h-full">
|
||||
<div className="shadow-2 p-3 h-full flex flex-column surface-card" style={{ borderRadius: '6px' }}>
|
||||
<div className="text-900 font-medium text-xl mb-2">Basic</div>
|
||||
<div className="text-600">Plan description</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<div className="flex align-items-center">
|
||||
<span className="font-bold text-2xl text-900">$9</span>
|
||||
<span className="ml-2 font-medium text-600">per month</span>
|
||||
</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<ul className="list-none p-0 m-0 flex-grow-1">
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Arcu vitae elementum</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Dui faucibus in ornare</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Morbi tincidunt augue</span>
|
||||
</li>
|
||||
</ul>
|
||||
<hr className="mb-3 mx-0 border-top-1 border-none surface-border mt-auto" />
|
||||
<Button label="Buy Now" className="p-3 w-full mt-auto"></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12 lg:col-4">
|
||||
<div className="p-3 h-full">
|
||||
<div className="shadow-2 p-3 h-full flex flex-column surface-card" style={{ borderRadius: '6px' }}>
|
||||
<div className="text-900 font-medium text-xl mb-2">Premium</div>
|
||||
<div className="text-600">Plan description</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<div className="flex align-items-center">
|
||||
<span className="font-bold text-2xl text-900">$29</span>
|
||||
<span className="ml-2 font-medium text-600">per month</span>
|
||||
</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<ul className="list-none p-0 m-0 flex-grow-1">
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Arcu vitae elementum</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Dui faucibus in ornare</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Morbi tincidunt augue</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Duis ultricies lacus sed</span>
|
||||
</li>
|
||||
</ul>
|
||||
<hr className="mb-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<Button label="Buy Now" className="p-3 w-full"></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-12 lg:col-4">
|
||||
<div className="p-3 h-full">
|
||||
<div className="shadow-2 p-3 flex flex-column surface-card" style={{ borderRadius: '6px' }}>
|
||||
<div className="text-900 font-medium text-xl mb-2">Enterprise</div>
|
||||
<div className="text-600">Plan description</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<div className="flex align-items-center">
|
||||
<span className="font-bold text-2xl text-900">$49</span>
|
||||
<span className="ml-2 font-medium text-600">per month</span>
|
||||
</div>
|
||||
<hr className="my-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<ul className="list-none p-0 m-0 flex-grow-1">
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Arcu vitae elementum</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Dui faucibus in ornare</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Morbi tincidunt augue</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Duis ultricies lacus sed</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Imperdiet proin</span>
|
||||
</li>
|
||||
<li className="flex align-items-center mb-3">
|
||||
<i className="pi pi-check-circle text-green-500 mr-2"></i>
|
||||
<span>Nisi scelerisque</span>
|
||||
</li>
|
||||
</ul>
|
||||
<hr className="mb-3 mx-0 border-top-1 border-none surface-border" />
|
||||
<Button label="Buy Now" className="p-3 w-full" outlined></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<BlockViewer header="Call to Action" code={block4} containerClassName="surface-section px-4 py-8 md:px-6 lg:px-8" free>
|
||||
<div className="surface-section text-700 text-center">
|
||||
<div className="text-blue-600 font-bold mb-3">
|
||||
<i className="pi pi-discord"></i> POWERED BY DISCORD
|
||||
</div>
|
||||
<div className="text-900 font-bold text-5xl mb-3">Join Our Design Community</div>
|
||||
<div className="text-700 text-2xl mb-5">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Velit numquam eligendi quos.</div>
|
||||
<Button label="Join Now" icon="pi pi-discord" className="font-bold px-5 py-3 white-space-nowrap" raised rounded />
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<BlockViewer header="Banner" code={block5} containerClassName="surface-section py-8" free>
|
||||
<div className="bg-bluegray-900 text-gray-100 p-3 flex justify-content-between lg:justify-content-center align-items-center flex-wrap">
|
||||
<div className="font-bold mr-8">🔥 Hot Deals!</div>
|
||||
<div className="align-items-center hidden lg:flex">
|
||||
<span className="line-height-3">Libero voluptatum atque exercitationem praesentium provident odit.</span>
|
||||
</div>
|
||||
<a className="flex align-items-center ml-2 mr-8">
|
||||
<span className="underline font-bold">Learn More</span>
|
||||
</a>
|
||||
<a className="flex align-items-center no-underline justify-content-center border-circle text-100 hover:bg-bluegray-700 cursor-pointer transition-colors transition-duration-150" style={{ width: '2rem', height: '2rem' }}>
|
||||
<i className="pi pi-times"></i>
|
||||
</a>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<div className="block-category-title">Application UI</div>
|
||||
<BlockViewer header="Page Heading" code={block6} containerClassName="surface-section px-4 py-5 md:px-6 lg:px-8" free>
|
||||
<div className="surface-section">
|
||||
<ul className="list-none p-0 m-0 flex align-items-center font-medium mb-3">
|
||||
<li>
|
||||
<a className="text-500 no-underline line-height-3 cursor-pointer">Application</a>
|
||||
</li>
|
||||
<li className="px-2">
|
||||
<i className="pi pi-angle-right text-500 line-height-3"></i>
|
||||
</li>
|
||||
<li>
|
||||
<span className="text-900 line-height-3">Analytics</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div className="flex align-items-start flex-column lg:justify-content-between lg:flex-row">
|
||||
<div>
|
||||
<div className="font-medium text-3xl text-900">Customers</div>
|
||||
<div className="flex align-items-center text-700 flex-wrap">
|
||||
<div className="mr-5 flex align-items-center mt-3">
|
||||
<i className="pi pi-users mr-2"></i>
|
||||
<span>332 Active Users</span>
|
||||
</div>
|
||||
<div className="mr-5 flex align-items-center mt-3">
|
||||
<i className="pi pi-globe mr-2"></i>
|
||||
<span>9402 Sessions</span>
|
||||
</div>
|
||||
<div className="flex align-items-center mt-3">
|
||||
<i className="pi pi-clock mr-2"></i>
|
||||
<span>2.32m Avg. Duration</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3 lg:mt-0">
|
||||
<Button label="Add" className="mr-2" outlined icon="pi pi-user-plus" />
|
||||
<Button label="Save" icon="pi pi-check" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<BlockViewer header="Stats" code={block7} free>
|
||||
<div className="surface-ground px-4 py-5 md:px-6 lg:px-8">
|
||||
<div className="grid">
|
||||
<div className="col-12 md:col-6 lg:col-3">
|
||||
<div className="surface-card shadow-2 p-3 border-round">
|
||||
<div className="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span className="block text-500 font-medium mb-3">Orders</span>
|
||||
<div className="text-900 font-medium text-xl">152</div>
|
||||
</div>
|
||||
<div className="flex align-items-center justify-content-center bg-blue-100 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
|
||||
<i className="pi pi-shopping-cart text-blue-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-green-500 font-medium">24 new </span>
|
||||
<span className="text-500">since last visit</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 md:col-6 lg:col-3">
|
||||
<div className="surface-card shadow-2 p-3 border-round">
|
||||
<div className="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span className="block text-500 font-medium mb-3">Revenue</span>
|
||||
<div className="text-900 font-medium text-xl">$2.100</div>
|
||||
</div>
|
||||
<div className="flex align-items-center justify-content-center bg-orange-100 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
|
||||
<i className="pi pi-map-marker text-orange-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-green-500 font-medium">%52+ </span>
|
||||
<span className="text-500">since last week</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 md:col-6 lg:col-3">
|
||||
<div className="surface-card shadow-2 p-3 border-round">
|
||||
<div className="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span className="block text-500 font-medium mb-3">Customers</span>
|
||||
<div className="text-900 font-medium text-xl">28441</div>
|
||||
</div>
|
||||
<div className="flex align-items-center justify-content-center bg-cyan-100 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
|
||||
<i className="pi pi-inbox text-cyan-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-green-500 font-medium">520 </span>
|
||||
<span className="text-500">newly registered</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 md:col-6 lg:col-3">
|
||||
<div className="surface-card shadow-2 p-3 border-round">
|
||||
<div className="flex justify-content-between mb-3">
|
||||
<div>
|
||||
<span className="block text-500 font-medium mb-3">Comments</span>
|
||||
<div className="text-900 font-medium text-xl">152 Unread</div>
|
||||
</div>
|
||||
<div className="flex align-items-center justify-content-center bg-purple-100 border-round" style={{ width: '2.5rem', height: '2.5rem' }}>
|
||||
<i className="pi pi-comment text-purple-500 text-xl"></i>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-green-500 font-medium">85 </span>
|
||||
<span className="text-500">responded</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<BlockViewer header="Sign-In" code={block8} containerClassName="px-4 py-8 md:px-6 lg:px-8" free>
|
||||
<div className="flex align-items-center justify-content-center">
|
||||
<div className="surface-card p-4 shadow-2 border-round w-full lg:w-6">
|
||||
<div className="text-center mb-5">
|
||||
<img src="/demo/images/blocks/logos/hyper.svg" alt="hyper" height={50} className="mb-3" />
|
||||
<div className="text-900 text-3xl font-medium mb-3">Welcome Back</div>
|
||||
<span className="text-600 font-medium line-height-3">Do not have an account?</span>
|
||||
<a className="font-medium no-underline ml-2 text-blue-500 cursor-pointer">Create today!</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-900 font-medium mb-2">
|
||||
Email
|
||||
</label>
|
||||
<InputText id="email" type="text" placeholder="Email address" className="w-full mb-3" />
|
||||
|
||||
<label htmlFor="password" className="block text-900 font-medium mb-2">
|
||||
Password
|
||||
</label>
|
||||
<InputText id="password" type="password" placeholder="Password" className="w-full mb-3" />
|
||||
|
||||
<div className="flex align-items-center justify-content-between mb-6">
|
||||
<div className="flex align-items-center">
|
||||
<Checkbox id="rememberme" onChange={(e) => setChecked(e.checked as boolean)} checked={checked} className="mr-2" />
|
||||
<label htmlFor="rememberme" className="text-900">
|
||||
Remember me
|
||||
</label>
|
||||
</div>
|
||||
<a className="font-medium no-underline ml-2 text-blue-500 text-right cursor-pointer">Forgot your password?</a>
|
||||
</div>
|
||||
|
||||
<Button label="Sign In" icon="pi pi-user" className="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<BlockViewer header="Description List" code={block9} containerClassName="surface-section px-4 py-8 md:px-6 lg:px-8" free>
|
||||
<div className="surface-section">
|
||||
<div className="font-medium text-3xl text-900 mb-3">Movie Information</div>
|
||||
<div className="text-500 mb-5">Morbi tristique blandit turpis. In viverra ligula id nulla hendrerit rutrum.</div>
|
||||
<ul className="list-none p-0 m-0">
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Title</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1">Heat</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Genre</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1">
|
||||
<Chip label="Crime" className="mr-2" />
|
||||
<Chip label="Drama" className="mr-2" />
|
||||
<Chip label="Thriller" />
|
||||
</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Director</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1">Michael Mann</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Actors</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1">Robert De Niro, Al Pacino</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
<li className="flex align-items-center py-3 px-2 border-top-1 border-bottom-1 border-300 flex-wrap">
|
||||
<div className="text-500 w-6 md:w-2 font-medium">Plot</div>
|
||||
<div className="text-900 w-full md:w-8 md:flex-order-0 flex-order-1 line-height-3">A group of professional bank robbers start to feel the heat from police when they unknowingly leave a clue at their latest heist.</div>
|
||||
<div className="w-6 md:w-2 flex justify-content-end">
|
||||
<Button label="Edit" icon="pi pi-pencil" text />
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
|
||||
<BlockViewer header="Card" code={block10} containerClassName="px-4 py-8 md:px-6 lg:px-8" free>
|
||||
<div className="surface-card p-4 shadow-2 border-round">
|
||||
<div className="text-3xl font-medium text-900 mb-3">Card Title</div>
|
||||
<div className="font-medium text-500 mb-3">Vivamus id nisl interdum, blandit augue sit amet, eleifend mi.</div>
|
||||
<div style={{ height: '150px' }} className="border-2 border-dashed surface-border"></div>
|
||||
</div>
|
||||
</BlockViewer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlocksDemo;
|
||||
@@ -1,429 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from 'primereact/button';
|
||||
import { Column } from 'primereact/column';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import { FileUpload } from 'primereact/fileupload';
|
||||
import { InputNumber } from 'primereact/inputnumber';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import { RadioButton } from 'primereact/radiobutton';
|
||||
import { Rating } from 'primereact/rating';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { Toolbar } from 'primereact/toolbar';
|
||||
import { classNames } from 'primereact/utils';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { ProductService } from '../../../../demo/service/ProductService';
|
||||
import type { Demo } from '@/types';
|
||||
|
||||
const Crud = () => {
|
||||
let emptyProduct: Demo.Product = {
|
||||
id: null,
|
||||
name: '',
|
||||
image: null,
|
||||
description: '',
|
||||
category: null,
|
||||
price: 0,
|
||||
quantity: 0,
|
||||
rating: 0,
|
||||
inventoryStatus: 'INSTOCK'
|
||||
};
|
||||
|
||||
const [products, setProducts] = useState(null);
|
||||
const [productDialog, setProductDialog] = useState(false);
|
||||
const [deleteProductDialog, setDeleteProductDialog] = useState(false);
|
||||
const [deleteProductsDialog, setDeleteProductsDialog] = useState(false);
|
||||
const [product, setProduct] = useState(emptyProduct);
|
||||
const [selectedProducts, setSelectedProducts] = useState(null);
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
const [globalFilter, setGlobalFilter] = useState(null);
|
||||
const toast = useRef(null);
|
||||
const dt = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
ProductService.getProducts().then((data) => setProducts(data));
|
||||
}, []);
|
||||
|
||||
const formatCurrency = (value) => {
|
||||
return value.toLocaleString('en-US', {
|
||||
style: 'currency',
|
||||
currency: 'USD'
|
||||
});
|
||||
};
|
||||
|
||||
const openNew = () => {
|
||||
setProduct(emptyProduct);
|
||||
setSubmitted(false);
|
||||
setProductDialog(true);
|
||||
};
|
||||
|
||||
const hideDialog = () => {
|
||||
setSubmitted(false);
|
||||
setProductDialog(false);
|
||||
};
|
||||
|
||||
const hideDeleteProductDialog = () => {
|
||||
setDeleteProductDialog(false);
|
||||
};
|
||||
|
||||
const hideDeleteProductsDialog = () => {
|
||||
setDeleteProductsDialog(false);
|
||||
};
|
||||
|
||||
const saveProduct = () => {
|
||||
setSubmitted(true);
|
||||
|
||||
if (product.name.trim()) {
|
||||
let _products = [...products];
|
||||
let _product = { ...product };
|
||||
if (product.id) {
|
||||
const index = findIndexById(product.id);
|
||||
|
||||
_products[index] = _product;
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: 'Successful',
|
||||
detail: 'Product Updated',
|
||||
life: 3000
|
||||
});
|
||||
} else {
|
||||
_product.id = createId();
|
||||
_product.code = createId();
|
||||
_product.image = 'product-placeholder.svg';
|
||||
_products.push(_product);
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: 'Successful',
|
||||
detail: 'Product Created',
|
||||
life: 3000
|
||||
});
|
||||
}
|
||||
|
||||
setProducts(_products);
|
||||
setProductDialog(false);
|
||||
setProduct(emptyProduct);
|
||||
}
|
||||
};
|
||||
|
||||
const editProduct = (product) => {
|
||||
setProduct({ ...product });
|
||||
setProductDialog(true);
|
||||
};
|
||||
|
||||
const confirmDeleteProduct = (product) => {
|
||||
setProduct(product);
|
||||
setDeleteProductDialog(true);
|
||||
};
|
||||
|
||||
const deleteProduct = () => {
|
||||
let _products = products.filter((val) => val.id !== product.id);
|
||||
setProducts(_products);
|
||||
setDeleteProductDialog(false);
|
||||
setProduct(emptyProduct);
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: 'Successful',
|
||||
detail: 'Product Deleted',
|
||||
life: 3000
|
||||
});
|
||||
};
|
||||
|
||||
const findIndexById = (id) => {
|
||||
let index = -1;
|
||||
for (let i = 0; i < products.length; i++) {
|
||||
if (products[i].id === id) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
const createId = () => {
|
||||
let id = '';
|
||||
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
for (let i = 0; i < 5; i++) {
|
||||
id += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
return id;
|
||||
};
|
||||
|
||||
const exportCSV = () => {
|
||||
dt.current.exportCSV();
|
||||
};
|
||||
|
||||
const confirmDeleteSelected = () => {
|
||||
setDeleteProductsDialog(true);
|
||||
};
|
||||
|
||||
const deleteSelectedProducts = () => {
|
||||
let _products = products.filter((val) => !selectedProducts.includes(val));
|
||||
setProducts(_products);
|
||||
setDeleteProductsDialog(false);
|
||||
setSelectedProducts(null);
|
||||
toast.current.show({
|
||||
severity: 'success',
|
||||
summary: 'Successful',
|
||||
detail: 'Products Deleted',
|
||||
life: 3000
|
||||
});
|
||||
};
|
||||
|
||||
const onCategoryChange = (e) => {
|
||||
let _product = { ...product };
|
||||
_product['category'] = e.value;
|
||||
setProduct(_product);
|
||||
};
|
||||
|
||||
const onInputChange = (e, name) => {
|
||||
const val = (e.target && e.target.value) || '';
|
||||
let _product = { ...product };
|
||||
_product[`${name}`] = val;
|
||||
|
||||
setProduct(_product);
|
||||
};
|
||||
|
||||
const onInputNumberChange = (e, name) => {
|
||||
const val = e.value || 0;
|
||||
let _product = { ...product };
|
||||
_product[`${name}`] = val;
|
||||
|
||||
setProduct(_product);
|
||||
};
|
||||
|
||||
const leftToolbarTemplate = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="my-2">
|
||||
<Button severity="success" label="New" icon="pi pi-plus" className="mr-2" onClick={openNew} />
|
||||
<Button severity="danger" label="Delete" icon="pi pi-trash" onClick={confirmDeleteSelected} disabled={!selectedProducts || !selectedProducts.length} />
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const rightToolbarTemplate = () => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<FileUpload mode="basic" accept="image/*" maxFileSize={1000000} chooseLabel="Import" className="mr-2 inline-block" />
|
||||
<Button severity="help" label="Export" icon="pi pi-upload" onClick={exportCSV} />
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const codeBodyTemplate = (rowData) => {
|
||||
return (
|
||||
<>
|
||||
<span className="p-column-title">Code</span>
|
||||
{rowData.code}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const nameBodyTemplate = (rowData) => {
|
||||
return (
|
||||
<>
|
||||
<span className="p-column-title">Name</span>
|
||||
{rowData.name}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const imageBodyTemplate = (rowData) => {
|
||||
return (
|
||||
<>
|
||||
<span className="p-column-title">Image</span>
|
||||
<img src={`/demo/images/product/${rowData.image}`} alt={rowData.image} className="shadow-2" width="100" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const priceBodyTemplate = (rowData) => {
|
||||
return (
|
||||
<>
|
||||
<span className="p-column-title">Price</span>
|
||||
{formatCurrency(rowData.price)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const categoryBodyTemplate = (rowData) => {
|
||||
return (
|
||||
<>
|
||||
<span className="p-column-title">Category</span>
|
||||
{rowData.category}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const ratingBodyTemplate = (rowData) => {
|
||||
return (
|
||||
<>
|
||||
<span className="p-column-title">Reviews</span>
|
||||
<Rating value={rowData.rating} readOnly cancel={false} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData) => {
|
||||
return (
|
||||
<>
|
||||
<span className="p-column-title">Status</span>
|
||||
<span className={`product-badge status-${rowData.inventoryStatus.toLowerCase()}`}>{rowData.inventoryStatus}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const actionBodyTemplate = (rowData) => {
|
||||
return (
|
||||
<>
|
||||
<Button icon="pi pi-pencil" rounded severity="success" className="mr-2" onClick={() => editProduct(rowData)} />
|
||||
<Button icon="pi pi-trash" rounded severity="warning" onClick={() => confirmDeleteProduct(rowData)} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const header = (
|
||||
<div className="flex flex-column md:flex-row md:justify-content-between md:align-items-center">
|
||||
<h5 className="m-0">Manage Products</h5>
|
||||
<span className="block mt-2 md:mt-0 p-input-icon-left">
|
||||
<i className="pi pi-search" />
|
||||
<InputText type="search" onInput={(e) => setGlobalFilter((e.target as HTMLInputElement).value)} placeholder="Search..." />
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
const productDialogFooter = (
|
||||
<>
|
||||
<Button label="Cancel" icon="pi pi-times" text onClick={hideDialog} />
|
||||
<Button label="Save" icon="pi pi-check" text onClick={saveProduct} />
|
||||
</>
|
||||
);
|
||||
const deleteProductDialogFooter = (
|
||||
<>
|
||||
<Button label="No" icon="pi pi-times" text onClick={hideDeleteProductDialog} />
|
||||
<Button label="Yes" icon="pi pi-check" text onClick={deleteProduct} />
|
||||
</>
|
||||
);
|
||||
const deleteProductsDialogFooter = (
|
||||
<>
|
||||
<Button label="No" icon="pi pi-times" text onClick={hideDeleteProductsDialog} />
|
||||
<Button label="Yes" icon="pi pi-check" text onClick={deleteSelectedProducts} />
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="grid crud-demo">
|
||||
<div className="col-12">
|
||||
<div className="card">
|
||||
<Toast ref={toast} />
|
||||
<Toolbar className="mb-4" left={leftToolbarTemplate} right={rightToolbarTemplate}></Toolbar>
|
||||
|
||||
<DataTable
|
||||
ref={dt}
|
||||
value={products}
|
||||
selection={selectedProducts}
|
||||
onSelectionChange={(e) => setSelectedProducts(e.value)}
|
||||
paginator
|
||||
rows={10}
|
||||
rowsPerPageOptions={[5, 10, 25]}
|
||||
className="datatable-responsive"
|
||||
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
|
||||
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} products"
|
||||
globalFilter={globalFilter}
|
||||
emptyMessage="No products found."
|
||||
header={header}
|
||||
responsiveLayout="scroll"
|
||||
>
|
||||
<Column selectionMode="multiple" headerStyle={{ width: '4rem' }}></Column>
|
||||
<Column field="code" header="Code" sortable body={codeBodyTemplate} headerStyle={{ minWidth: '15rem' }}></Column>
|
||||
<Column field="name" header="Name" sortable body={nameBodyTemplate} headerStyle={{ minWidth: '15rem' }}></Column>
|
||||
<Column header="Image" body={imageBodyTemplate}></Column>
|
||||
<Column field="price" header="Price" body={priceBodyTemplate} sortable></Column>
|
||||
<Column field="category" header="Category" sortable body={categoryBodyTemplate} headerStyle={{ minWidth: '10rem' }}></Column>
|
||||
<Column field="rating" header="Reviews" body={ratingBodyTemplate} sortable></Column>
|
||||
<Column field="inventoryStatus" header="Status" body={statusBodyTemplate} sortable headerStyle={{ minWidth: '10rem' }}></Column>
|
||||
<Column body={actionBodyTemplate} headerStyle={{ minWidth: '10rem' }}></Column>
|
||||
</DataTable>
|
||||
|
||||
<Dialog visible={productDialog} style={{ width: '450px' }} header="Product Details" modal className="p-fluid" footer={productDialogFooter} onHide={hideDialog}>
|
||||
{product.image && <img src={`/demo/images/product/${product.image}`} alt={product.image} width="150" className="mt-0 mx-auto mb-5 block shadow-2" />}
|
||||
<div className="field">
|
||||
<label htmlFor="name">Name</label>
|
||||
<InputText
|
||||
id="name"
|
||||
value={product.name}
|
||||
onChange={(e) => onInputChange(e, 'name')}
|
||||
required
|
||||
autoFocus
|
||||
className={classNames({
|
||||
'p-invalid': submitted && !product.name
|
||||
})}
|
||||
/>
|
||||
{submitted && !product.name && <small className="p-invalid">Name is required.</small>}
|
||||
</div>
|
||||
<div className="field">
|
||||
<label htmlFor="description">Description</label>
|
||||
<InputTextarea id="description" value={product.description} onChange={(e) => onInputChange(e, 'description')} required rows={3} cols={20} />
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label className="mb-3">Category</label>
|
||||
<div className="formgrid grid">
|
||||
<div className="field-radiobutton col-6">
|
||||
<RadioButton inputId="category1" name="category" value="Accessories" onChange={onCategoryChange} checked={product.category === 'Accessories'} />
|
||||
<label htmlFor="category1">Accessories</label>
|
||||
</div>
|
||||
<div className="field-radiobutton col-6">
|
||||
<RadioButton inputId="category2" name="category" value="Clothing" onChange={onCategoryChange} checked={product.category === 'Clothing'} />
|
||||
<label htmlFor="category2">Clothing</label>
|
||||
</div>
|
||||
<div className="field-radiobutton col-6">
|
||||
<RadioButton inputId="category3" name="category" value="Electronics" onChange={onCategoryChange} checked={product.category === 'Electronics'} />
|
||||
<label htmlFor="category3">Electronics</label>
|
||||
</div>
|
||||
<div className="field-radiobutton col-6">
|
||||
<RadioButton inputId="category4" name="category" value="Fitness" onChange={onCategoryChange} checked={product.category === 'Fitness'} />
|
||||
<label htmlFor="category4">Fitness</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="formgrid grid">
|
||||
<div className="field col">
|
||||
<label htmlFor="price">Price</label>
|
||||
<InputNumber id="price" value={product.price as number} onValueChange={(e) => onInputNumberChange(e, 'price')} mode="currency" currency="USD" locale="en-US" />
|
||||
</div>
|
||||
<div className="field col">
|
||||
<label htmlFor="quantity">Quantity</label>
|
||||
<InputNumber id="quantity" value={product.quantity} onValueChange={(e) => onInputNumberChange(e, 'quantity')} />
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
<Dialog visible={deleteProductDialog} style={{ width: '450px' }} header="Confirm" modal footer={deleteProductDialogFooter} onHide={hideDeleteProductDialog}>
|
||||
<div className="flex align-items-center justify-content-center">
|
||||
<i className="pi pi-exclamation-triangle mr-3" style={{ fontSize: '2rem' }} />
|
||||
{product && (
|
||||
<span>
|
||||
Are you sure you want to delete <b>{product.name}</b>?
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</Dialog>
|
||||
|
||||
<Dialog visible={deleteProductsDialog} style={{ width: '450px' }} header="Confirm" modal footer={deleteProductsDialogFooter} onHide={hideDeleteProductsDialog}>
|
||||
<div className="flex align-items-center justify-content-center">
|
||||
<i className="pi pi-exclamation-triangle mr-3" style={{ fontSize: '2rem' }} />
|
||||
{product && <span>Are you sure you want to delete the selected products?</span>}
|
||||
</div>
|
||||
</Dialog>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Crud;
|
||||
@@ -1,149 +0,0 @@
|
||||
'use client';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { FilterMatchMode, FilterOperator } from 'primereact/api';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Column } from 'primereact/column';
|
||||
import { DataTable, DataTableFilterMeta } from 'primereact/datatable';
|
||||
import { InputText } from 'primereact/inputtext';
|
||||
import { ProgressBar } from 'primereact/progressbar';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { CustomerService } from '../../../../demo/service/CustomerService';
|
||||
import type { Demo } from '@/types';
|
||||
|
||||
function List() {
|
||||
const [customers, setCustomers] = useState<Demo.Customer[]>([]);
|
||||
const [filters, setFilters] = useState<DataTableFilterMeta>({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [globalFilterValue, setGlobalFilterValue] = useState('');
|
||||
const router = useRouter();
|
||||
const dt = useRef(null);
|
||||
|
||||
const getCustomers = (data: Demo.Customer[]) => {
|
||||
return [...(data || [])].map((d) => {
|
||||
d.date = new Date(d.date);
|
||||
return d;
|
||||
});
|
||||
};
|
||||
|
||||
const formatDate = (value: Date) => {
|
||||
return value.toLocaleDateString('en-US', {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric'
|
||||
});
|
||||
};
|
||||
const clearFilter = () => {
|
||||
initFilters();
|
||||
};
|
||||
|
||||
const initFilters = () => {
|
||||
setFilters({
|
||||
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||
name: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
'country.name': {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }]
|
||||
},
|
||||
representative: { value: null, matchMode: FilterMatchMode.IN },
|
||||
date: {
|
||||
operator: FilterOperator.AND,
|
||||
constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }]
|
||||
},
|
||||
activity: { value: null, matchMode: FilterMatchMode.BETWEEN }
|
||||
});
|
||||
setGlobalFilterValue('');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
CustomerService.getCustomersLarge().then((data) => {
|
||||
setCustomers(getCustomers(data));
|
||||
setLoading(false);
|
||||
});
|
||||
initFilters();
|
||||
}, []);
|
||||
|
||||
const onGlobalFilterChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { value } = e.target;
|
||||
let _filters = { ...filters };
|
||||
(_filters['global'] as any).value = value;
|
||||
setFilters(_filters);
|
||||
setGlobalFilterValue(value);
|
||||
};
|
||||
|
||||
const renderHeader = () => {
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2 align-items-center justify-content-between">
|
||||
<span className="p-input-icon-left w-full sm:w-20rem flex-order-1 sm:flex-order-0">
|
||||
<i className="pi pi-search"></i>
|
||||
<InputText value={globalFilterValue} onChange={onGlobalFilterChange} placeholder="Global Search" className="w-full" />
|
||||
</span>
|
||||
<Button type="button" icon="pi pi-user-plus" label="Add New" className="w-full sm:w-auto flex-order-0 sm:flex-order-1" outlined onClick={() => router.push('/profile/create')} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const nameBodyTemplate = (customer: Demo.Customer) => {
|
||||
return (
|
||||
<>
|
||||
<span className="p-column-title">Name</span>
|
||||
{customer.name}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const countryBodyTemplate = (customer: Demo.Customer) => {
|
||||
return (
|
||||
<>
|
||||
<img alt={customer.country.name} src={`/demo/images/flag/flag_placeholder.png`} className={'w-2rem mr-2 flag flag-' + customer.country.code} />
|
||||
<span className="image-text">{customer.country.name}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const createdByBodyTemplate = (customer: Demo.Customer) => {
|
||||
return (
|
||||
<div className="inline-flex align-items-center">
|
||||
<img alt={customer.representative.name} src={`/demo/images/avatar/${customer.representative.image}`} className="w-2rem mr-2" />
|
||||
<span>{customer.representative.name}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const dateBodyTemplate = (customer: Demo.Customer) => {
|
||||
return formatDate(customer.date);
|
||||
};
|
||||
|
||||
const activityBodyTemplate = (customer: Demo.Customer) => {
|
||||
return <ProgressBar value={customer.activity} showValue={false} style={{ height: '.5rem' }} />;
|
||||
};
|
||||
|
||||
const header = renderHeader();
|
||||
|
||||
return (
|
||||
<div className="card">
|
||||
<DataTable
|
||||
ref={dt}
|
||||
value={customers}
|
||||
header={header}
|
||||
paginator
|
||||
rows={10}
|
||||
responsiveLayout="scroll"
|
||||
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
|
||||
rowsPerPageOptions={[10, 25, 50]}
|
||||
filters={filters}
|
||||
loading={loading}
|
||||
>
|
||||
<Column field="name" header="Name" sortable body={nameBodyTemplate} headerClassName="white-space-nowrap" style={{ width: '25%' }}></Column>
|
||||
<Column field="country.name" header="Country" sortable body={countryBodyTemplate} headerClassName="white-space-nowrap" style={{ width: '25%' }}></Column>
|
||||
<Column field="date" header="Join Date" sortable body={dateBodyTemplate} headerClassName="white-space-nowrap" style={{ width: '25%' }}></Column>
|
||||
<Column field="representative.name" header="Created By" body={createdByBodyTemplate} headerClassName="white-space-nowrap" style={{ width: '25%' }} sortable></Column>
|
||||
<Column field="activity" header="Activity" body={activityBodyTemplate} headerClassName="white-space-nowrap" style={{ width: '25%' }} sortable></Column>
|
||||
</DataTable>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default List;
|
||||
@@ -1,369 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Panel } from 'primereact/panel';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Message } from 'primereact/message';
|
||||
import { Divider } from 'primereact/divider';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { useRef } from 'react';
|
||||
import TestDataGenerator from '../../../../components/test/TestDataGenerator';
|
||||
import TestResults from '../../../../components/test/TestResults';
|
||||
import WorkflowTests from '../../../../components/test/WorkflowTests';
|
||||
import SystemIntegrationTest from '../../../../components/test/SystemIntegrationTest';
|
||||
import PhasesQuickPreview from '../../../../components/phases/PhasesQuickPreview';
|
||||
import PhaseValidationPanel from '../../../../components/phases/PhaseValidationPanel';
|
||||
import AtlantisResponsivePhasesTable from '../../../../components/phases/AtlantisResponsivePhasesTable';
|
||||
import AtlantisAccessibilityControls from '../../../../components/phases/AtlantisAccessibilityControls';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { Badge } from 'primereact/badge';
|
||||
import { Dialog } from 'primereact/dialog';
|
||||
import testDataService from '../../../../services/testDataService';
|
||||
import phaseValidationService from '../../../../services/phaseValidationService';
|
||||
import type { PhaseChantier, Chantier, Client } from '../../../../types/btp';
|
||||
|
||||
interface TestData {
|
||||
client: Client;
|
||||
chantier: Chantier;
|
||||
phases: PhaseChantier[];
|
||||
}
|
||||
|
||||
const TestPhasesPage: React.FC = () => {
|
||||
const [testData, setTestData] = useState<TestData[]>([]);
|
||||
const [selectedData, setSelectedData] = useState<TestData | null>(null);
|
||||
const [validationDialogVisible, setValidationDialogVisible] = useState(false);
|
||||
const [selectedPhase, setSelectedPhase] = useState<PhaseChantier | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const toast = useRef<Toast>(null);
|
||||
|
||||
// Auto-générer des données de test au chargement
|
||||
useEffect(() => {
|
||||
generateInitialData();
|
||||
}, []);
|
||||
|
||||
const generateInitialData = async () => {
|
||||
try {
|
||||
const initialData = testDataService.generateTestDataset(2);
|
||||
setTestData(initialData);
|
||||
if (initialData.length > 0) {
|
||||
setSelectedData(initialData[0]);
|
||||
}
|
||||
|
||||
toast.current?.show({
|
||||
severity: 'success',
|
||||
summary: 'Données de test générées',
|
||||
detail: `${initialData.length} projets avec phases créés`,
|
||||
life: 3000
|
||||
});
|
||||
} catch (error) {
|
||||
toast.current?.show({
|
||||
severity: 'error',
|
||||
summary: 'Erreur',
|
||||
detail: 'Impossible de générer les données de test',
|
||||
life: 5000
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleDataGenerated = (newData: any) => {
|
||||
if (Array.isArray(newData)) {
|
||||
setTestData(prev => [...prev, ...newData]);
|
||||
if (!selectedData && newData.length > 0) {
|
||||
setSelectedData(newData[0]);
|
||||
}
|
||||
} else {
|
||||
// Données individuelles (phases uniquement, etc.)
|
||||
const dataItem: TestData = {
|
||||
client: newData.client || testDataService.generateTestClient(Date.now()),
|
||||
chantier: newData.chantier || testDataService.generateTestChantier(Date.now(), 'MAISON_INDIVIDUELLE', newData.client),
|
||||
phases: newData.phases || []
|
||||
};
|
||||
setTestData(prev => [...prev, dataItem]);
|
||||
setSelectedData(dataItem);
|
||||
}
|
||||
|
||||
toast.current?.show({
|
||||
severity: 'success',
|
||||
summary: 'Nouvelles données générées',
|
||||
detail: 'Les données ont été ajoutées avec succès',
|
||||
life: 3000
|
||||
});
|
||||
};
|
||||
|
||||
const handlePhaseValidation = (phase: PhaseChantier) => {
|
||||
setSelectedPhase(phase);
|
||||
setValidationDialogVisible(true);
|
||||
};
|
||||
|
||||
const handleStartPhase = (phaseId: string) => {
|
||||
if (!selectedData) return;
|
||||
|
||||
const updatedPhases = selectedData.phases.map(p =>
|
||||
p.id === phaseId
|
||||
? { ...p, statut: 'EN_COURS' as const, dateDebutReelle: new Date().toISOString().split('T')[0] }
|
||||
: p
|
||||
);
|
||||
|
||||
const updatedData = { ...selectedData, phases: updatedPhases };
|
||||
setSelectedData(updatedData);
|
||||
|
||||
setTestData(prev => prev.map(item =>
|
||||
item.chantier.id === updatedData.chantier.id ? updatedData : item
|
||||
));
|
||||
|
||||
toast.current?.show({
|
||||
severity: 'info',
|
||||
summary: 'Phase démarrée',
|
||||
detail: `La phase a été mise en cours`,
|
||||
life: 3000
|
||||
});
|
||||
|
||||
setValidationDialogVisible(false);
|
||||
};
|
||||
|
||||
// Templates pour l'affichage du tableau
|
||||
const statusBodyTemplate = (rowData: PhaseChantier) => {
|
||||
const severity = rowData.statut === 'TERMINEE' ? 'success' :
|
||||
rowData.statut === 'EN_COURS' ? 'info' : 'secondary';
|
||||
|
||||
return <Tag value={rowData.statut} severity={severity} />;
|
||||
};
|
||||
|
||||
const progressBodyTemplate = (rowData: PhaseChantier) => {
|
||||
return (
|
||||
<div className="flex align-items-center gap-2">
|
||||
<span>{rowData.pourcentageAvancement || 0}%</span>
|
||||
<div className="w-4rem h-0.5rem bg-gray-200 border-round overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-primary border-round"
|
||||
style={{ width: `${rowData.pourcentageAvancement || 0}%` }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const validationBodyTemplate = (rowData: PhaseChantier) => {
|
||||
if (!selectedData) return null;
|
||||
|
||||
const validation = phaseValidationService.validatePhaseStart(rowData, selectedData.phases);
|
||||
|
||||
const severity = validation.readyToStart ? 'success' :
|
||||
validation.canStart ? 'warning' : 'danger';
|
||||
|
||||
const icon = validation.readyToStart ? 'pi pi-check-circle' :
|
||||
validation.canStart ? 'pi pi-exclamation-triangle' : 'pi pi-times-circle';
|
||||
|
||||
return (
|
||||
<div className="flex align-items-center gap-2">
|
||||
<i className={`${icon} text-${severity === 'danger' ? 'red' : severity === 'warning' ? 'yellow' : 'green'}-500`}></i>
|
||||
{validation.errors.length > 0 && (
|
||||
<Badge value={validation.errors.length} severity="danger" />
|
||||
)}
|
||||
{validation.warnings.length > 0 && (
|
||||
<Badge value={validation.warnings.length} severity="warning" />
|
||||
)}
|
||||
<Button
|
||||
icon="pi pi-eye"
|
||||
className="p-button-text p-button-sm"
|
||||
onClick={() => handlePhaseValidation(rowData)}
|
||||
tooltip="Voir la validation"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const nameBodyTemplate = (rowData: PhaseChantier) => {
|
||||
const isSubPhase = !!rowData.phaseParent;
|
||||
|
||||
return (
|
||||
<div className={`flex align-items-center gap-2 ${isSubPhase ? 'ml-4' : ''}`}>
|
||||
{isSubPhase && <i className="pi pi-arrow-right text-gray-400 text-xs"></i>}
|
||||
<span className={isSubPhase ? 'text-600' : 'font-semibold'}>
|
||||
{rowData.nom}
|
||||
</span>
|
||||
{rowData.critique && (
|
||||
<Tag value="Critique" severity="danger" className="text-xs" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const actionsBodyTemplate = (rowData: PhaseChantier) => {
|
||||
if (!selectedData) return null;
|
||||
|
||||
const validation = phaseValidationService.validatePhaseStart(rowData, selectedData.phases);
|
||||
|
||||
return (
|
||||
<div className="flex gap-1">
|
||||
<Button
|
||||
icon="pi pi-play"
|
||||
className="p-button-success p-button-sm"
|
||||
disabled={!validation.canStart || rowData.statut === 'TERMINEE'}
|
||||
onClick={() => handleStartPhase(rowData.id!)}
|
||||
tooltip="Démarrer"
|
||||
/>
|
||||
<Button
|
||||
icon="pi pi-eye"
|
||||
className="p-button-outlined p-button-sm"
|
||||
onClick={() => handlePhaseValidation(rowData)}
|
||||
tooltip="Détails"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="grid">
|
||||
<Toast ref={toast} />
|
||||
|
||||
<div className="col-12">
|
||||
<Panel header="Test du système de gestion des phases BTP" toggleable>
|
||||
<Message
|
||||
severity="info"
|
||||
text="Cette page permet de tester le système complet de gestion des phases avec des données réalistes."
|
||||
className="w-full mb-4"
|
||||
/>
|
||||
|
||||
<TestResults className="mb-4" />
|
||||
|
||||
<WorkflowTests className="mb-4" />
|
||||
|
||||
<SystemIntegrationTest className="mb-4" />
|
||||
|
||||
<TestDataGenerator
|
||||
onDataGenerated={handleDataGenerated}
|
||||
className="mb-4"
|
||||
/>
|
||||
</Panel>
|
||||
</div>
|
||||
|
||||
{testData.length > 0 && (
|
||||
<>
|
||||
<div className="col-12 md:col-4">
|
||||
<Panel header="Projets de test" toggleable>
|
||||
{testData.map((data, index) => (
|
||||
<div
|
||||
key={data.chantier.id}
|
||||
className={`p-3 border-1 border-round cursor-pointer mb-2 ${
|
||||
selectedData?.chantier.id === data.chantier.id
|
||||
? 'border-primary bg-primary-50'
|
||||
: 'surface-border hover:surface-100'
|
||||
}`}
|
||||
onClick={() => setSelectedData(data)}
|
||||
>
|
||||
<div className="font-semibold">{data.chantier.nom}</div>
|
||||
<div className="text-600 text-sm">{data.client.nomComplet}</div>
|
||||
<div className="text-600 text-sm">
|
||||
{data.phases.length} phases • {data.chantier.typeChantier}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</Panel>
|
||||
</div>
|
||||
|
||||
<div className="col-12 md:col-8">
|
||||
{selectedData && (
|
||||
<>
|
||||
<AtlantisAccessibilityControls className="mb-4" />
|
||||
|
||||
<PhasesQuickPreview
|
||||
phases={selectedData.phases}
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
<AtlantisResponsivePhasesTable
|
||||
phases={selectedData.phases}
|
||||
onPhaseSelect={setSelectedPhase}
|
||||
onPhaseStart={handleStartPhase}
|
||||
onPhaseValidate={handlePhaseValidation}
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
<Panel header={`Détails - ${selectedData.chantier.nom}`} toggleable collapsed>
|
||||
<DataTable
|
||||
value={selectedData.phases}
|
||||
size="small"
|
||||
className="p-datatable-sm"
|
||||
emptyMessage="Aucune phase trouvée"
|
||||
>
|
||||
<Column
|
||||
field="nom"
|
||||
header="Phase"
|
||||
body={nameBodyTemplate}
|
||||
style={{ width: '25%' }}
|
||||
/>
|
||||
<Column
|
||||
field="statut"
|
||||
header="Statut"
|
||||
body={statusBodyTemplate}
|
||||
style={{ width: '10%' }}
|
||||
/>
|
||||
<Column
|
||||
field="pourcentageAvancement"
|
||||
header="Avancement"
|
||||
body={progressBodyTemplate}
|
||||
style={{ width: '15%' }}
|
||||
/>
|
||||
<Column
|
||||
field="dateDebutPrevue"
|
||||
header="Début prévu"
|
||||
body={(rowData) => rowData.dateDebutPrevue ?
|
||||
new Date(rowData.dateDebutPrevue).toLocaleDateString('fr-FR') : '-'
|
||||
}
|
||||
style={{ width: '12%' }}
|
||||
/>
|
||||
<Column
|
||||
field="dateFinPrevue"
|
||||
header="Fin prévue"
|
||||
body={(rowData) => rowData.dateFinPrevue ?
|
||||
new Date(rowData.dateFinPrevue).toLocaleDateString('fr-FR') : '-'
|
||||
}
|
||||
style={{ width: '12%' }}
|
||||
/>
|
||||
<Column
|
||||
header="Validation"
|
||||
body={validationBodyTemplate}
|
||||
style={{ width: '15%' }}
|
||||
/>
|
||||
<Column
|
||||
header="Actions"
|
||||
body={actionsBodyTemplate}
|
||||
style={{ width: '11%' }}
|
||||
/>
|
||||
</DataTable>
|
||||
</Panel>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Dialog
|
||||
header="Validation des prérequis"
|
||||
visible={validationDialogVisible}
|
||||
onHide={() => setValidationDialogVisible(false)}
|
||||
style={{ width: '90vw', maxWidth: '800px' }}
|
||||
modal
|
||||
>
|
||||
{selectedPhase && selectedData && (
|
||||
<PhaseValidationPanel
|
||||
phase={selectedPhase}
|
||||
allPhases={selectedData.phases}
|
||||
onStartPhase={handleStartPhase}
|
||||
onViewPrerequisite={(prereqId) => {
|
||||
const prereq = selectedData.phases.find(p => p.id === prereqId);
|
||||
if (prereq) {
|
||||
setSelectedPhase(prereq);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TestPhasesPage;
|
||||
Reference in New Issue
Block a user