Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
259 changes: 146 additions & 113 deletions src/templates/App.tsx
Original file line number Diff line number Diff line change
@@ -1,123 +1,156 @@
import { __ } from '@wordpress/i18n';
import React, { useState, useMemo } from "react";
import { RepeatIcon } from '@chakra-ui/icons';
import {
ChakraProvider,
Box,
HStack,
Text,
Tabs,
TabList,
Tab,
Button,
Icon,
Divider,
VStack,
Heading,
} from "@chakra-ui/react";
import Main from "./components/Main";

const EVFIcon = (props) => (
<Icon viewBox="0 0 24 24" {...props}>
<path
fill="#7e3bd0"
d="M21.23,10H17.79L16.62,8h3.46ZM17.77,4l1.15,2H15.48L14.31,4Zm-15,16L12,4l5.77,10H10.85L12,12h2.31L12,8,6.23,18H20.08l1.16,2Z"
/>
</Icon>
);

const TabFilters = ({ onTabChange }) => {
const filters = useMemo(() => [__("All", "everest-forms"), __("Free", "everest-forms"), __("Premium", "everest-forms")], []);

return (
<Tabs variant="unstyled" ml="auto" onChange={onTabChange}>
<TabList>
{filters.map((label) => (
<Tab
key={label}
_selected={{
color: "purple.500",
fontWeight: "bold",
borderBottom: "2px solid",
borderColor: "purple.500",
}}
fontSize={{ base: "sm", md: "md", lg: "lg" }}
px={{ base: 1, md: 2 }} // Add horizontal padding to tabs
>
{label}
</Tab>
))}
</TabList>
</Tabs>
);
};
Box,
Button,
ChakraProvider,
Heading,
HStack,
Link,
Text,
VStack,
} from '@chakra-ui/react';
import { useIsFetching, useQueryClient } from '@tanstack/react-query';
import { __ } from '@wordpress/i18n';
import { useState } from 'react';
import Theme from '../dashboard/Theme/Theme';
import Main from './components/Main';

const App = () => {
const [selectedTab, setSelectedTab] = useState<string>(__("All", "everest-forms"));
const queryClient = useQueryClient();
const isFetching = useIsFetching(['templates']);
const [selectedTab, setSelectedTab] = useState<string>(
__('All', 'everest-forms'),
);

// Handle tab changes
const handleTabChange = (index: number) => {
const filters = [__("All", "everest-forms"), __("Free", "everest-forms"), __("Premium", "everest-forms")];
setSelectedTab(filters[index]);
};
const handleFilterChange = (filter: string) => {
setSelectedTab(filter);
};

// Handle refresh button click
const handleRefreshTemplates = () => {
const url = new URL(window.location.href);
url.searchParams.set('refresh', Date.now().toString());
window.location.href = url.toString();
};
const handleRefreshTemplates = () => {
if (!isFetching) {
queryClient.invalidateQueries(['templates']);
}
};

return (
<ChakraProvider>
<Box bg="white" margin="20px" padding="0px 24px 50px" boxShadow="0px 4px 50px rgba(0, 0, 0, 0.06)">
<HStack
spacing={{ base: 4, md: 6 }}
align="center"
mb={0}
borderBottom="1px solid #CDD0D8"
padding="20px 10px"
direction={{ base: "column", md: "row" }}
>
<EVFIcon boxSize="12" />
<Divider orientation="vertical" height="40px" borderColor="#CDD0D8" />
<Text fontSize="18px" fontWeight="semibold" lineHeight="26px" color="#383838" textAlign={{ base: "center", md: "left" }} margin="0px">
{__("Add New Form", "everest-forms")}
</Text>
<Button
colorScheme="purple"
variant="outline"
onClick={handleRefreshTemplates}
width={{ base: "full", md: "auto" }}
display={{ base: "none", md: "inline-flex" }}
fontSize= "15px"
lineHeight="20px"
padding="8px 16px"
height="auto"
borderRadius="4px"
>
{__("Refresh Templates", "everest-forms")}
</Button>
<TabFilters onTabChange={handleTabChange} />
</HStack>
return (
<ChakraProvider theme={Theme}>
<Box
bg="white"
margin="20px"
padding="0px 24px 50px"
boxShadow="0px 4px 50px rgba(0, 0, 0, 0.06)"
>
<Box bg="white">
<HStack
justify="space-between"
align="flex-start"
padding="20px 0px 32px"
gap="20px"
flexWrap="wrap"
>
<VStack align="start" gap="8px" flex="1" minW="300px">
<Heading
as="h1"
fontSize="3xl"
lineHeight="1.2"
fontWeight="600"
color="grey.400"
>
{__('Select a Template', 'everest-forms')}
</Heading>
<Text fontSize="14px" lineHeight="1.5" color="grey.300">
{__(
'Choose from our ready-made templates or start with a blank form',
'everest-forms',
)}
</Text>
</VStack>

{/* Main Content Area */}
<Box bg="white" >
<VStack align="start" padding="20px 0px 32px" gap="12px">
<Heading as="h1" fontSize="24px"lineHeight="34px" letterSpacing="0.4px" fontWeight="semibold" m={0}>
{__("Select a Template", "everest-forms")}
</Heading>
<Text fontSize="14px" lineHeight="24px" color="#4D4D4D" fontWeight="400" margin="0px" >
{__(
"To get started quickly, you can pick from our ready-made templates, begin with a blank form, or design your own.",
"everest-forms"
)}
</Text>
</VStack>
<Main filter={selectedTab} />
</Box>
</Box>
</ChakraProvider>
);
<HStack gap="12px" flexWrap="wrap">
<Button
size="md"
variant={
selectedTab === __('All', 'everest-forms')
? 'solid'
: 'outline'
}
colorScheme="primary"
onClick={() => handleFilterChange(__('All', 'everest-forms'))}
px="24px"
py="10px"
height="auto"
fontSize="15px"
fontWeight="500"
>
{__('All', 'everest-forms')}
</Button>
<Button
size="md"
variant={
selectedTab === __('Free', 'everest-forms')
? 'solid'
: 'outline'
}
colorScheme="primary"
onClick={() => handleFilterChange(__('Free', 'everest-forms'))}
px="24px"
py="10px"
height="auto"
fontSize="15px"
fontWeight="500"
>
{__('Free', 'everest-forms')}
</Button>
<Button
size="md"
variant={
selectedTab === __('Premium', 'everest-forms')
? 'solid'
: 'outline'
}
colorScheme="primary"
onClick={() =>
handleFilterChange(__('Premium', 'everest-forms'))
}
px="24px"
py="10px"
height="auto"
fontSize="15px"
fontWeight="500"
>
{__('Premium', 'everest-forms')}
</Button>
<Link
color="primary.400"
fontSize="15px"
fontWeight="500"
display="flex"
alignItems="center"
gap="6px"
onClick={handleRefreshTemplates}
cursor={isFetching ? 'not-allowed' : 'pointer'}
opacity={isFetching ? 0.6 : 1}
pointerEvents={isFetching ? 'none' : 'auto'}
_hover={{ color: isFetching ? 'primary.400' : 'primary.500' }}
>
<RepeatIcon
sx={{
animation: isFetching ? 'spin 1s linear infinite' : 'none',
'@keyframes spin': {
'0%': { transform: 'rotate(0deg)' },
'100%': { transform: 'rotate(360deg)' },
},
}}
/>
{__('Refresh Templates', 'everest-forms')}
</Link>
</HStack>
</HStack>
<Main filter={selectedTab} />
</Box>
</Box>
</ChakraProvider>
);
};

export default App;
25 changes: 14 additions & 11 deletions src/templates/components/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Box, Flex, Spinner, useBreakpointValue } from '@chakra-ui/react';
import { Box, Flex, useBreakpointValue } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import apiFetch from '@wordpress/api-fetch';
import { __ } from '@wordpress/i18n';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { templatesScriptData } from '../utils/global';
import Sidebar from './Sidebar';
import TemplateList from './TemplateList';
import TemplatesSkeleton from './TemplatesSkeleton';

const { restURL, security } = templatesScriptData;

Expand Down Expand Up @@ -40,6 +41,7 @@ const Main: React.FC<{ filter: string }> = ({ filter }) => {
const {
data: templates = [],
isLoading,
isFetching,
error,
} = useQuery(['templates'], fetchTemplates);

Expand Down Expand Up @@ -163,14 +165,10 @@ const Main: React.FC<{ filter: string }> = ({ filter }) => {

const sidebarWidth = useBreakpointValue({ base: '100%', md: '250px' });

if (isLoading)
return (
<Flex justify="center" align="center" height="100vh">
<Spinner size="xl" />
</Flex>
);
if (error) return <div>{(error as Error).message}</div>;

const showSkeleton = isLoading || isFetching;

return (
<Box>
<Flex direction={{ base: 'column', md: 'row' }}>
Expand All @@ -184,6 +182,7 @@ const Main: React.FC<{ filter: string }> = ({ filter }) => {
selectedCategory={state.selectedCategory}
onCategorySelect={handleCategorySelect}
onSearchChange={handleSearchChange}
isLoading={isLoading}
/>
</Box>
<Box
Expand All @@ -193,10 +192,14 @@ const Main: React.FC<{ filter: string }> = ({ filter }) => {
marginRight="28px"
/>
<Box flex={1}>
<TemplateList
selectedCategory={selectedCategory}
templates={filteredTemplates}
/>
{showSkeleton ? (
<TemplatesSkeleton />
) : (
<TemplateList
selectedCategory={selectedCategory}
templates={filteredTemplates}
/>
)}
</Box>
</Flex>
</Box>
Expand Down
Loading
Loading