/home/techb158/primomovers.ca/wp-content/plugins/everest-forms/src/templates/components
NameSizeModeActions
CreateFormCTA.tsx56060644editdlrm
CreateWithAI.tsx567100644editdlrm
Main.tsx174580644editdlrm
PluginStatus.tsx80290644editdlrm
Sidebar.tsx37060644editdlrm
TemplateList.tsx240850644editdlrm
TemplatesSkeleton.tsx8130644editdlrm
Edit: /home/techb158/primomovers.ca/wp-content/plugins/everest-forms/src/templates/components/Main.tsx (17458B)
import { Box, Flex, Heading, Icon, Input, InputGroup, InputLeftElement, keyframes, Tab, TabList, Tabs, Text, useToast, } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import apiFetch from '@wordpress/api-fetch'; import { __ } from '@wordpress/i18n'; import debounce from 'lodash.debounce'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { IoSearchOutline } from 'react-icons/io5'; import { FiRefreshCw } from 'react-icons/fi'; import { templatesScriptData } from '../utils/global'; import Sidebar from './Sidebar'; import TemplateList from './TemplateList'; import CreateFormCTA from './CreateFormCTA'; const { restURL, security } = templatesScriptData; const fetchTemplates = async () => { const response = (await apiFetch({ path: `${restURL}everest-forms/v1/templates`, method: 'GET', headers: { 'X-WP-Nonce': security, }, })) as { templates: { category: string; templates: Template[] }[] }; if (response && Array.isArray(response.templates)) { const allTemplates = response.templates.flatMap( (category) => category.templates, ); return allTemplates; } else { throw new Error(__('Unexpected response format.', 'everest-forms')); } }; interface CreateFormResponse { success: boolean; data?: { id: number; redirect: string; status: number }; message?: string; } const shimmer = keyframes` 0% { background-position: -600px 0; } 100% { background-position: 600px 0; } `; const spin = keyframes` from { transform: rotate(0deg); } to { transform: rotate(360deg); } `; const skimmerStyle = { background: 'linear-gradient(90deg, #f0f0f0 25%, #e8e8e8 50%, #f0f0f0 75%)', backgroundSize: '600px 100%', animation: `${shimmer} 1.6s ease-in-out infinite`, borderRadius: '4px', }; const SkelBox: React.FC<{ w?: string; h?: string; mb?: string; br?: string }> = ({ w = '100%', h = '14px', mb = '0', br = '4px' }) => ( ); // Template card skeleton — matches actual card: gradient image bg + white inner wrapper + info section const TemplateCardSkeleton = () => ( {/* Image area: gradient bg + white inner card (matching actual card structure) */} {/* Info section */} ); const TemplateSkeleton = () => ( {/* CTA cards — 2-col equal-width grid, matching CreateFormCTA layout */} {/* AI card: icon + badge row, then title/desc/link */} {/* Scratch card: standalone icon, then title/desc/link */} {/* Template section card */} {/* Top bar: search (left, w-256px) | heading + filter tabs (right) */} {/* Search input shimmer */} {/* "Choose from Templates" heading */} {/* Filter tabs pill */} {/* Sidebar + template grid */} {/* Sidebar: CATEGORIES label + rows + Can't find card */} {/* "CATEGORIES" label */} {/* Category rows */} {[78, 62, 88, 55, 72, 60, 70, 52, 65, 58].map((w, i) => ( ))} {/* "Can't find a template?" card */} {/* Template grid: 2-col (xl: 3-col) matching TemplateList */} {Array.from({ length: 6 }).map((_, i) => ( ))} ); const Main: React.FC<{ onCreateWithAI?: (formId?: number, title?: string) => void }> = ({ onCreateWithAI }) => { const toast = useToast(); const [filter, setFilter] = useState(__('All', 'everest-forms')); const [isCreatingBlank, setIsCreatingBlank] = useState(false); const [searchInputValue, setSearchInputValue] = useState(''); const [state, setState] = useState({ selectedCategory: __('All Forms', 'everest-forms'), searchTerm: '', }); const [categorySetFromURL, setCategorySetFromURL] = useState(false); const { selectedCategory, searchTerm } = state; const { data: templates = [], isLoading, isFetching, refetch, error, } = useQuery(['templates'], fetchTemplates); const categories = useMemo(() => { const categoriesSet = new Set(); templates.forEach((template) => { template.categories.forEach((category) => categoriesSet.add(category)); }); return [ { name: __('All Forms', 'everest-forms'), count: templates.length }, ...Array.from(categoriesSet).map((category) => ({ name: category, count: templates.filter((template) => template.categories.includes(category), ).length, })), ]; }, [templates]); useEffect(() => { if (categorySetFromURL) return; if (categories.length <= 1) return; const urlParams = new URLSearchParams(window.location.search); if (urlParams.has('evf_template_category')) { const categorySlug = urlParams.get('evf_template_category') || ''; const normalize = (str: string) => str .toLowerCase() .replace(/\s+/g, '') .replace(/[^a-z0-9]/g, ''); const normalizedSlug = normalize(categorySlug); let matchedCategory = categories.find((cat) => { const normalizedCatName = normalize(cat.name); if (normalizedCatName === normalizedSlug) return true; if (normalizedCatName.startsWith(normalizedSlug)) return true; if (normalizedSlug.startsWith(normalizedCatName)) return true; return false; }); if (!matchedCategory) { matchedCategory = categories.find((cat) => { const normalizedCatName = normalize(cat.name); const slugWords = categorySlug.toLowerCase().split(/[\s-]+/); const catWords = cat.name.toLowerCase().split(/[\s-]+/); const hasMatchingWord = slugWords.some((word) => catWords.some( (catWord) => catWord.includes(word) || word.includes(catWord), ), ); if (hasMatchingWord) return true; if ( normalizedCatName.includes(normalizedSlug) || normalizedSlug.includes(normalizedCatName) ) return true; return false; }); } if ( matchedCategory && matchedCategory.name !== __('All Forms', 'everest-forms') ) { setState((prevState) => ({ ...prevState, selectedCategory: matchedCategory.name, })); setCategorySetFromURL(true); } } }, [categories, categorySetFromURL]); const filteredTemplates = useMemo(() => { return templates.filter( (template) => template.slug !== 'blank' && (selectedCategory === __('All Forms', 'everest-forms') || template.categories.includes(selectedCategory)) && template.title.toLowerCase().includes(searchTerm.toLowerCase()) && (filter === __('All', 'everest-forms') || (filter === __('Free', 'everest-forms') && !template.isPro) || (filter === __('Premium', 'everest-forms') && template.isPro)), ); }, [selectedCategory, searchTerm, templates, filter]); const handleCategorySelect = useCallback((category: string) => { setState((prevState) => ({ ...prevState, selectedCategory: category })); }, []); const debouncedSetSearch = useCallback( debounce((value: string) => { setState((prevState) => ({ ...prevState, searchTerm: value })); }, 300), [], ); const handleSearchInputChange = (e: React.ChangeEvent) => { const value = e.target.value; setSearchInputValue(value); debouncedSetSearch(value); }; if (isLoading) return ; if (error) return
{(error as Error).message}
; const handleCreateWithAI = (formId?: number, title?: string) => { if (onCreateWithAI) onCreateWithAI(formId, title); }; const handleCreateBlank = async () => { setIsCreatingBlank(true); try { const response = (await apiFetch({ path: `${restURL}everest-forms/v1/templates/create`, method: 'POST', body: JSON.stringify({ title: __('Untitled', 'everest-forms'), slug: 'blank', }), headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': security, }, })) as CreateFormResponse; if (response.success && response.data) { window.location.href = response.data.redirect; } else { setIsCreatingBlank(false); toast({ title: __('Error', 'everest-forms'), description: response.message || __('Failed to create form.', 'everest-forms'), status: 'error', position: 'bottom-right', duration: 5000, isClosable: true, variant: 'subtle', }); } } catch (error) { setIsCreatingBlank(false); toast({ title: __('Error', 'everest-forms'), description: __('An error occurred while creating the form.', 'everest-forms'), status: 'error', position: 'bottom-right', duration: 5000, isClosable: true, variant: 'subtle', }); } }; const filterLabels = [ __('All', 'everest-forms'), __('Free', 'everest-forms'), __('Premium', 'everest-forms'), ]; return ( {/* CTA Cards — 2-column equal-width grid */} {/* Template Section Card */} {/* Subtle refetch indicator — thin animated bar at top */} {isFetching && !isLoading && ( )} {/* Top bar: search (left) | heading + filter tabs (right) */} {/* Search area — aligned with sidebar width */} {/* Heading + filter tabs */} {__('Choose from Templates', 'everest-forms')} {/* Refetch button + Filter tabs */} { if (!isFetching) refetch(); }} _hover={{ borderColor: '#7545BB', color: '#7545BB' }} transition="all 0.15s" title={__('Refresh templates', 'everest-forms')} > {__('Refetch', 'everest-forms')} setFilter(filterLabels[index])} > {filterLabels.map((label) => ( {label} ))} {/* Sidebar + Template Grid */} {/* Sidebar */} {/* Template grid */} ); }; export default Main;