feat: Add in-app documentation system
Phase 1: Core Documentation
- Created docs/ folder with 8 markdown documentation files
- Getting Started, Installation, Troubleshooting, FAQ
- Configuration docs (Appearance, SPA Mode)
- Feature docs (Shop, Checkout)
- PHP registry with filter hook for addon extensibility
Phase 2: Documentation Viewer
- DocsController.php with REST API endpoints
- GET /woonoow/v1/docs - List all docs (with addon hook)
- GET /woonoow/v1/docs/{slug} - Get document content
- Admin SPA /help route with sidebar navigation
- Markdown rendering with react-markdown
- Added Help & Docs to More page for mobile access
Filter Hook: woonoow_docs_registry
Addons can register their own documentation sections.
This commit is contained in:
1472
admin-spa/package-lock.json
generated
1472
admin-spa/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -49,8 +49,10 @@
|
||||
"qrcode": "^1.5.4",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^10.1.0",
|
||||
"react-router-dom": "^7.9.4",
|
||||
"recharts": "^3.3.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"sonner": "^2.0.7",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"vaul": "^1.1.2",
|
||||
|
||||
@@ -261,6 +261,7 @@ import NewsletterSubscribers from '@/routes/Marketing/Newsletter';
|
||||
import CampaignsList from '@/routes/Marketing/Campaigns';
|
||||
import CampaignEdit from '@/routes/Marketing/Campaigns/Edit';
|
||||
import MorePage from '@/routes/More';
|
||||
import Help from '@/routes/Help';
|
||||
|
||||
// Addon Route Component - Dynamically loads addon components
|
||||
function AddonRoute({ config }: { config: any }) {
|
||||
@@ -583,6 +584,9 @@ function AppRoutes() {
|
||||
<Route path="/marketing/campaigns" element={<CampaignsList />} />
|
||||
<Route path="/marketing/campaigns/:id" element={<CampaignEdit />} />
|
||||
|
||||
{/* Help - Main menu route with no submenu */}
|
||||
<Route path="/help" element={<Help />} />
|
||||
|
||||
{/* Dynamic Addon Routes */}
|
||||
{addonRoutes.map((route: any) => (
|
||||
<Route
|
||||
|
||||
163
admin-spa/src/routes/Help/DocContent.tsx
Normal file
163
admin-spa/src/routes/Help/DocContent.tsx
Normal file
@@ -0,0 +1,163 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { AlertCircle } from 'lucide-react';
|
||||
import type { DocContent as DocContentType } from './types';
|
||||
|
||||
interface DocContentProps {
|
||||
slug: string;
|
||||
}
|
||||
|
||||
export default function DocContent({ slug }: DocContentProps) {
|
||||
const [doc, setDoc] = useState<DocContentType | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchDoc = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/wp-json/woonoow/v1/docs/${slug}`, {
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Document not found');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
setDoc(data.doc);
|
||||
} else {
|
||||
throw new Error(data.message || 'Failed to load document');
|
||||
}
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to load document');
|
||||
setDoc(null);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchDoc();
|
||||
}, [slug]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Skeleton className="h-10 w-3/4" />
|
||||
<Skeleton className="h-4 w-full" />
|
||||
<Skeleton className="h-4 w-full" />
|
||||
<Skeleton className="h-4 w-2/3" />
|
||||
<Skeleton className="h-32 w-full mt-6" />
|
||||
<Skeleton className="h-4 w-full" />
|
||||
<Skeleton className="h-4 w-5/6" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
{error}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
if (!doc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<article className="prose prose-slate dark:prose-invert max-w-none">
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm]}
|
||||
components={{
|
||||
// Custom heading with anchor links
|
||||
h1: ({ children }) => (
|
||||
<h1 className="text-3xl font-bold mb-6 pb-4 border-b">{children}</h1>
|
||||
),
|
||||
h2: ({ children }) => (
|
||||
<h2 className="text-2xl font-semibold mt-10 mb-4">{children}</h2>
|
||||
),
|
||||
h3: ({ children }) => (
|
||||
<h3 className="text-xl font-medium mt-8 mb-3">{children}</h3>
|
||||
),
|
||||
// Styled tables
|
||||
table: ({ children }) => (
|
||||
<div className="overflow-x-auto my-6">
|
||||
<table className="min-w-full border-collapse border border-border rounded-lg">
|
||||
{children}
|
||||
</table>
|
||||
</div>
|
||||
),
|
||||
th: ({ children }) => (
|
||||
<th className="border border-border bg-muted px-4 py-2 text-left font-semibold">
|
||||
{children}
|
||||
</th>
|
||||
),
|
||||
td: ({ children }) => (
|
||||
<td className="border border-border px-4 py-2">{children}</td>
|
||||
),
|
||||
// Styled code blocks
|
||||
code: ({ className, children }) => {
|
||||
const isInline = !className;
|
||||
if (isInline) {
|
||||
return (
|
||||
<code className="bg-muted px-1.5 py-0.5 rounded text-sm font-mono">
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<code className={className}>
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
},
|
||||
pre: ({ children }) => (
|
||||
<pre className="bg-muted p-4 rounded-lg overflow-x-auto my-4">
|
||||
{children}
|
||||
</pre>
|
||||
),
|
||||
// Styled blockquotes for notes
|
||||
blockquote: ({ children }) => (
|
||||
<blockquote className="border-l-4 border-primary bg-primary/5 pl-4 py-2 my-4 italic">
|
||||
{children}
|
||||
</blockquote>
|
||||
),
|
||||
// Links
|
||||
a: ({ href, children }) => (
|
||||
<a
|
||||
href={href}
|
||||
className="text-primary hover:underline"
|
||||
target={href?.startsWith('http') ? '_blank' : undefined}
|
||||
rel={href?.startsWith('http') ? 'noopener noreferrer' : undefined}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
// Lists
|
||||
ul: ({ children }) => (
|
||||
<ul className="list-disc pl-6 my-4 space-y-2">{children}</ul>
|
||||
),
|
||||
ol: ({ children }) => (
|
||||
<ol className="list-decimal pl-6 my-4 space-y-2">{children}</ol>
|
||||
),
|
||||
// Horizontal rule
|
||||
hr: () => <hr className="my-8 border-border" />,
|
||||
}}
|
||||
>
|
||||
{doc.content}
|
||||
</ReactMarkdown>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
160
admin-spa/src/routes/Help/index.tsx
Normal file
160
admin-spa/src/routes/Help/index.tsx
Normal file
@@ -0,0 +1,160 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { Book, ChevronRight, FileText, Settings, Layers, Puzzle, Menu, X } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { cn } from '@/lib/utils';
|
||||
import DocContent from './DocContent';
|
||||
import type { DocSection } from './types';
|
||||
|
||||
const iconMap: Record<string, React.ReactNode> = {
|
||||
'book-open': <Book className="w-4 h-4" />,
|
||||
'file-text': <FileText className="w-4 h-4" />,
|
||||
'settings': <Settings className="w-4 h-4" />,
|
||||
'layers': <Layers className="w-4 h-4" />,
|
||||
'puzzle': <Puzzle className="w-4 h-4" />,
|
||||
};
|
||||
|
||||
export default function Help() {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const [sections, setSections] = useState<DocSection[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [expandedSections, setExpandedSections] = useState<Record<string, boolean>>({});
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
|
||||
const currentSlug = searchParams.get('doc') || 'getting-started';
|
||||
|
||||
// Fetch documentation registry
|
||||
useEffect(() => {
|
||||
const fetchDocs = async () => {
|
||||
try {
|
||||
const response = await fetch('/wp-json/woonoow/v1/docs', {
|
||||
credentials: 'include',
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
setSections(data.sections);
|
||||
// Expand all sections by default
|
||||
const expanded: Record<string, boolean> = {};
|
||||
data.sections.forEach((section: DocSection) => {
|
||||
expanded[section.key] = true;
|
||||
});
|
||||
setExpandedSections(expanded);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch docs:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchDocs();
|
||||
}, []);
|
||||
|
||||
const toggleSection = (key: string) => {
|
||||
setExpandedSections(prev => ({
|
||||
...prev,
|
||||
[key]: !prev[key],
|
||||
}));
|
||||
};
|
||||
|
||||
const selectDoc = (slug: string) => {
|
||||
setSearchParams({ doc: slug });
|
||||
setSidebarOpen(false); // Close mobile sidebar
|
||||
};
|
||||
|
||||
const isActive = (slug: string) => slug === currentSlug;
|
||||
|
||||
return (
|
||||
<div className="flex h-[calc(100vh-64px)] bg-background">
|
||||
{/* Mobile menu button */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="lg:hidden fixed bottom-4 right-4 z-50 bg-primary text-primary-foreground shadow-lg rounded-full w-12 h-12"
|
||||
onClick={() => setSidebarOpen(!sidebarOpen)}
|
||||
>
|
||||
{sidebarOpen ? <X className="w-5 h-5" /> : <Menu className="w-5 h-5" />}
|
||||
</Button>
|
||||
|
||||
{/* Sidebar */}
|
||||
<aside
|
||||
className={cn(
|
||||
"w-72 border-r bg-muted/30 flex-shrink-0 transition-transform duration-300",
|
||||
"fixed lg:relative inset-y-0 left-0 z-40 lg:translate-x-0",
|
||||
sidebarOpen ? "translate-x-0" : "-translate-x-full"
|
||||
)}
|
||||
>
|
||||
<div className="p-4 border-b">
|
||||
<h2 className="text-lg font-semibold flex items-center gap-2">
|
||||
<Book className="w-5 h-5" />
|
||||
Documentation
|
||||
</h2>
|
||||
<p className="text-sm text-muted-foreground">Help & Guides</p>
|
||||
</div>
|
||||
|
||||
<div className="h-[calc(100vh-180px)] overflow-y-auto">
|
||||
<nav className="p-2">
|
||||
{loading ? (
|
||||
<div className="p-4 text-sm text-muted-foreground">Loading...</div>
|
||||
) : sections.length === 0 ? (
|
||||
<div className="p-4 text-sm text-muted-foreground">No documentation available</div>
|
||||
) : (
|
||||
sections.map((section) => (
|
||||
<div key={section.key} className="mb-2">
|
||||
<button
|
||||
onClick={() => toggleSection(section.key)}
|
||||
className="w-full flex items-center gap-2 px-3 py-2 text-sm font-medium text-foreground hover:bg-muted rounded-md"
|
||||
>
|
||||
{iconMap[section.icon] || <FileText className="w-4 h-4" />}
|
||||
<span className="flex-1 text-left">{section.label}</span>
|
||||
<ChevronRight
|
||||
className={cn(
|
||||
"w-4 h-4 transition-transform",
|
||||
expandedSections[section.key] && "rotate-90"
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
|
||||
{expandedSections[section.key] && (
|
||||
<div className="ml-4 mt-1 space-y-1">
|
||||
{section.items.map((item) => (
|
||||
<button
|
||||
key={item.slug}
|
||||
onClick={() => selectDoc(item.slug)}
|
||||
className={cn(
|
||||
"w-full text-left px-3 py-1.5 text-sm rounded-md transition-colors",
|
||||
isActive(item.slug)
|
||||
? "bg-primary text-primary-foreground"
|
||||
: "text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||
)}
|
||||
>
|
||||
{item.title}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</nav>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
{/* Backdrop for mobile */}
|
||||
{sidebarOpen && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/50 z-30 lg:hidden"
|
||||
onClick={() => setSidebarOpen(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Main content */}
|
||||
<main className="flex-1 overflow-y-auto">
|
||||
<div className="max-w-4xl mx-auto p-6 lg:p-10">
|
||||
<DocContent slug={currentSlug} />
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
31
admin-spa/src/routes/Help/types.ts
Normal file
31
admin-spa/src/routes/Help/types.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Documentation Types
|
||||
*/
|
||||
|
||||
export interface DocItem {
|
||||
slug: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface DocSection {
|
||||
key: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
items: DocItem[];
|
||||
}
|
||||
|
||||
export interface DocContent {
|
||||
slug: string;
|
||||
title: string;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface DocsRegistryResponse {
|
||||
success: boolean;
|
||||
sections: DocSection[];
|
||||
}
|
||||
|
||||
export interface DocContentResponse {
|
||||
success: boolean;
|
||||
doc: DocContent;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { useNavigate, Link } from 'react-router-dom';
|
||||
import { Tag, Settings as SettingsIcon, Palette, ChevronRight, Minimize2, LogOut, Sun, Moon, Monitor, ExternalLink, Mail, Megaphone } from 'lucide-react';
|
||||
import { Tag, Settings as SettingsIcon, Palette, ChevronRight, Minimize2, LogOut, Sun, Moon, Monitor, ExternalLink, Mail, Megaphone, HelpCircle } from 'lucide-react';
|
||||
import { __ } from '@/lib/i18n';
|
||||
import { usePageHeader } from '@/contexts/PageHeaderContext';
|
||||
import { useApp } from '@/contexts/AppContext';
|
||||
@@ -32,6 +32,12 @@ const menuItems: MenuItem[] = [
|
||||
label: __('Settings'),
|
||||
description: __('Configure your store settings'),
|
||||
to: '/settings'
|
||||
},
|
||||
{
|
||||
icon: <HelpCircle className="w-5 h-5" />,
|
||||
label: __('Help & Docs'),
|
||||
description: __('Documentation and guides'),
|
||||
to: '/help'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
132
docs/_registry.php
Normal file
132
docs/_registry.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* WooNooW Documentation Registry
|
||||
*
|
||||
* This file registers all core documentation.
|
||||
* Addons can extend using the 'woonoow_docs_registry' filter.
|
||||
*/
|
||||
|
||||
namespace WooNooW\Docs;
|
||||
|
||||
/**
|
||||
* Get all registered documentation
|
||||
*
|
||||
* @return array Documentation registry
|
||||
*/
|
||||
function get_docs_registry() {
|
||||
$docs_dir = dirname(__FILE__);
|
||||
|
||||
// Core WooNooW documentation
|
||||
$docs = [
|
||||
'core' => [
|
||||
'label' => 'WooNooW',
|
||||
'icon' => 'book-open',
|
||||
'items' => [
|
||||
[
|
||||
'slug' => 'getting-started',
|
||||
'title' => 'Getting Started',
|
||||
'file' => $docs_dir . '/getting-started.md',
|
||||
],
|
||||
[
|
||||
'slug' => 'installation',
|
||||
'title' => 'Installation',
|
||||
'file' => $docs_dir . '/installation.md',
|
||||
],
|
||||
[
|
||||
'slug' => 'troubleshooting',
|
||||
'title' => 'Troubleshooting',
|
||||
'file' => $docs_dir . '/troubleshooting.md',
|
||||
],
|
||||
[
|
||||
'slug' => 'faq',
|
||||
'title' => 'FAQ',
|
||||
'file' => $docs_dir . '/faq.md',
|
||||
],
|
||||
],
|
||||
],
|
||||
'configuration' => [
|
||||
'label' => 'Configuration',
|
||||
'icon' => 'settings',
|
||||
'items' => [
|
||||
[
|
||||
'slug' => 'configuration/appearance',
|
||||
'title' => 'Appearance Settings',
|
||||
'file' => $docs_dir . '/configuration/appearance.md',
|
||||
],
|
||||
[
|
||||
'slug' => 'configuration/spa-mode',
|
||||
'title' => 'SPA Mode',
|
||||
'file' => $docs_dir . '/configuration/spa-mode.md',
|
||||
],
|
||||
],
|
||||
],
|
||||
'features' => [
|
||||
'label' => 'Features',
|
||||
'icon' => 'layers',
|
||||
'items' => [
|
||||
[
|
||||
'slug' => 'features/shop',
|
||||
'title' => 'Shop Page',
|
||||
'file' => $docs_dir . '/features/shop.md',
|
||||
],
|
||||
[
|
||||
'slug' => 'features/checkout',
|
||||
'title' => 'Checkout',
|
||||
'file' => $docs_dir . '/features/checkout.md',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Filter: woonoow_docs_registry
|
||||
*
|
||||
* Allows addons to register their own documentation.
|
||||
*
|
||||
* @param array $docs Current documentation registry
|
||||
* @return array Modified documentation registry
|
||||
*
|
||||
* @example
|
||||
* add_filter('woonoow_docs_registry', function($docs) {
|
||||
* $docs['my-addon'] = [
|
||||
* 'label' => 'My Addon',
|
||||
* 'icon' => 'puzzle',
|
||||
* 'items' => [
|
||||
* [
|
||||
* 'slug' => 'my-addon/getting-started',
|
||||
* 'title' => 'Getting Started',
|
||||
* 'file' => __DIR__ . '/docs/getting-started.md',
|
||||
* ],
|
||||
* ],
|
||||
* ];
|
||||
* return $docs;
|
||||
* });
|
||||
*/
|
||||
return apply_filters('woonoow_docs_registry', $docs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single documentation item by slug
|
||||
*
|
||||
* @param string $slug Document slug
|
||||
* @return array|null Document data with content, or null if not found
|
||||
*/
|
||||
function get_doc_by_slug($slug) {
|
||||
$registry = get_docs_registry();
|
||||
|
||||
foreach ($registry as $section) {
|
||||
foreach ($section['items'] as $item) {
|
||||
if ($item['slug'] === $slug) {
|
||||
// Read file content
|
||||
if (file_exists($item['file'])) {
|
||||
$item['content'] = file_get_contents($item['file']);
|
||||
} else {
|
||||
$item['content'] = '# Document Not Found\n\nThis document is coming soon.';
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
133
docs/configuration/appearance.md
Normal file
133
docs/configuration/appearance.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Appearance Settings
|
||||
|
||||
Customize the look and feel of your WooNooW store.
|
||||
|
||||
## Accessing Appearance Settings
|
||||
|
||||
Go to **WooNooW → Appearance** in the WordPress admin.
|
||||
|
||||
---
|
||||
|
||||
## General Settings
|
||||
|
||||
### Logo
|
||||
|
||||
Upload your store logo for display in the header.
|
||||
|
||||
- **Recommended size**: 200x60 pixels (width x height)
|
||||
- **Formats**: PNG (transparent background recommended), SVG, JPG
|
||||
- **Mobile**: Automatically resized for smaller screens
|
||||
|
||||
### SPA Page
|
||||
|
||||
Select which page hosts the WooNooW SPA. Default is "Store".
|
||||
|
||||
> **Note**: This page should contain the `[woonoow_spa]` shortcode.
|
||||
|
||||
### SPA Mode
|
||||
|
||||
Choose how WooNooW handles your store pages:
|
||||
|
||||
| Mode | Description |
|
||||
|------|-------------|
|
||||
| **Full** | All WooCommerce pages redirect to SPA |
|
||||
| **Disabled** | Native WooCommerce templates are used |
|
||||
|
||||
---
|
||||
|
||||
## Colors
|
||||
|
||||
### Primary Color
|
||||
|
||||
The main brand color used for:
|
||||
- Buttons
|
||||
- Links
|
||||
- Active states
|
||||
- Primary actions
|
||||
|
||||
**Default**: `#6366f1` (Indigo)
|
||||
|
||||
### Secondary Color
|
||||
|
||||
Secondary UI elements:
|
||||
- Less prominent buttons
|
||||
- Borders
|
||||
- Subtle backgrounds
|
||||
|
||||
**Default**: `#64748b` (Slate)
|
||||
|
||||
### Accent Color
|
||||
|
||||
Highlight color for:
|
||||
- Sale badges
|
||||
- Notifications
|
||||
- Call-to-action elements
|
||||
|
||||
**Default**: `#f59e0b` (Amber)
|
||||
|
||||
---
|
||||
|
||||
## Typography
|
||||
|
||||
### Body Font
|
||||
|
||||
Font used for general text content.
|
||||
|
||||
**Options**: System fonts and Google Fonts
|
||||
- Inter
|
||||
- Open Sans
|
||||
- Roboto
|
||||
- Lato
|
||||
- Poppins
|
||||
- And more...
|
||||
|
||||
### Heading Font
|
||||
|
||||
Font used for titles and headings.
|
||||
|
||||
**Options**: Same as body fonts, plus:
|
||||
- Cormorant Garamond (Serif option)
|
||||
- Playfair Display
|
||||
- Merriweather
|
||||
|
||||
### Font Sizes
|
||||
|
||||
Font sizes are responsive and adjust automatically based on screen size.
|
||||
|
||||
---
|
||||
|
||||
## Layout
|
||||
|
||||
### Container Width
|
||||
|
||||
Maximum width of the content area.
|
||||
|
||||
| Option | Width |
|
||||
|--------|-------|
|
||||
| Narrow | 1024px |
|
||||
| Default | 1280px |
|
||||
| Wide | 1536px |
|
||||
| Full | 100% |
|
||||
|
||||
### Header Style
|
||||
|
||||
Configure the header appearance:
|
||||
- **Fixed**: Stays at top when scrolling
|
||||
- **Static**: Scrolls with page
|
||||
|
||||
### Product Grid
|
||||
|
||||
Columns in the shop page grid:
|
||||
- Mobile: 1-2 columns
|
||||
- Tablet: 2-3 columns
|
||||
- Desktop: 3-4 columns
|
||||
|
||||
---
|
||||
|
||||
## Saving Changes
|
||||
|
||||
1. Make your changes
|
||||
2. Click **Save Changes** button
|
||||
3. Refresh your store page to see updates
|
||||
|
||||
> **Tip**: Open your store in another tab to preview changes quickly.
|
||||
139
docs/configuration/spa-mode.md
Normal file
139
docs/configuration/spa-mode.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# SPA Mode
|
||||
|
||||
Understanding and configuring WooNooW's SPA (Single Page Application) mode.
|
||||
|
||||
## What is SPA Mode?
|
||||
|
||||
SPA Mode controls how WooNooW handles your WooCommerce pages. It determines whether visitors experience the modern SPA interface or traditional WooCommerce templates.
|
||||
|
||||
---
|
||||
|
||||
## Available Modes
|
||||
|
||||
### Full Mode (Recommended)
|
||||
|
||||
**All WooCommerce pages redirect to the SPA.**
|
||||
|
||||
When a visitor navigates to:
|
||||
- `/shop` → Redirects to `/store/shop`
|
||||
- `/product/example` → Redirects to `/store/product/example`
|
||||
- `/cart` → Redirects to `/store/cart`
|
||||
- `/checkout` → Redirects to `/store/checkout`
|
||||
- `/my-account` → Redirects to `/store/my-account`
|
||||
|
||||
**Benefits**:
|
||||
- Instant page transitions
|
||||
- Modern, consistent UI
|
||||
- Better mobile experience
|
||||
- Smooth animations
|
||||
|
||||
**Best for**:
|
||||
- New stores
|
||||
- Stores wanting a modern look
|
||||
- Mobile-focused businesses
|
||||
|
||||
### Disabled Mode
|
||||
|
||||
**WooCommerce uses its native templates.**
|
||||
|
||||
WooCommerce pages work normally with your theme's templates. WooNooW admin features still work, but the customer-facing SPA is turned off.
|
||||
|
||||
**Benefits**:
|
||||
- Keep existing theme customizations
|
||||
- Compatibility with WooCommerce template overrides
|
||||
- Traditional page-by-page navigation
|
||||
|
||||
**Best for**:
|
||||
- Stores with heavy theme customizations
|
||||
- Testing before full rollout
|
||||
- Troubleshooting issues
|
||||
|
||||
---
|
||||
|
||||
## Switching Modes
|
||||
|
||||
### How to Switch
|
||||
|
||||
1. Go to **WooNooW → Appearance → General**
|
||||
2. Find **SPA Mode** setting
|
||||
3. Select your preferred mode
|
||||
4. Click **Save Changes**
|
||||
|
||||
### What Happens When Switching
|
||||
|
||||
**Switching to Full**:
|
||||
- WooCommerce pages start redirecting
|
||||
- SPA loads for shop experience
|
||||
- No data is changed
|
||||
|
||||
**Switching to Disabled**:
|
||||
- Redirects stop immediately
|
||||
- WooCommerce templates take over
|
||||
- No data is changed
|
||||
|
||||
> **Note**: All your products, orders, and settings remain unchanged when switching modes.
|
||||
|
||||
---
|
||||
|
||||
## URL Structure
|
||||
|
||||
### Full Mode URLs
|
||||
|
||||
```
|
||||
https://yourstore.com/store/ → Home/Shop
|
||||
https://yourstore.com/store/shop → Shop page
|
||||
https://yourstore.com/store/product/slug → Product page
|
||||
https://yourstore.com/store/cart → Cart
|
||||
https://yourstore.com/store/checkout → Checkout
|
||||
https://yourstore.com/store/my-account → Account
|
||||
```
|
||||
|
||||
### Disabled Mode URLs
|
||||
|
||||
Standard WooCommerce URLs:
|
||||
```
|
||||
https://yourstore.com/shop/ → Shop page
|
||||
https://yourstore.com/product/slug → Product page
|
||||
https://yourstore.com/cart/ → Cart
|
||||
https://yourstore.com/checkout/ → Checkout
|
||||
https://yourstore.com/my-account/ → Account
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SEO Considerations
|
||||
|
||||
### Full Mode SEO
|
||||
|
||||
- WooCommerce URLs (`/product/slug`) remain in sitemaps
|
||||
- When users click from search results, they're redirected to SPA
|
||||
- Meta tags are generated dynamically for social sharing
|
||||
- 302 (temporary) redirects preserve link equity
|
||||
|
||||
### Disabled Mode SEO
|
||||
|
||||
- Standard WooCommerce SEO applies
|
||||
- No redirects needed
|
||||
- Works with Yoast SEO, RankMath, etc.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Redirects Not Working
|
||||
|
||||
1. **Flush Permalinks**: Go to Settings → Permalinks → Save Changes
|
||||
2. **Check Store Page**: Ensure the Store page exists and has `[woonoow_spa]`
|
||||
3. **Clear Cache**: Purge all caching layers
|
||||
|
||||
### Blank Pages After Enabling
|
||||
|
||||
1. Verify SPA Mode is set to "Full"
|
||||
2. Clear browser cache
|
||||
3. Check for JavaScript errors in browser console
|
||||
|
||||
### Want to Test Before Enabling
|
||||
|
||||
1. Keep mode as "Disabled"
|
||||
2. Visit `/store/` directly to preview SPA
|
||||
3. Switch to "Full" when satisfied
|
||||
149
docs/faq.md
Normal file
149
docs/faq.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
Quick answers to common questions about WooNooW.
|
||||
|
||||
---
|
||||
|
||||
## General
|
||||
|
||||
### What is WooNooW?
|
||||
|
||||
WooNooW is a WooCommerce plugin that transforms your store into a modern Single Page Application (SPA). It provides instant page loads, a beautiful UI, and seamless shopping experience.
|
||||
|
||||
### Do I need WooCommerce?
|
||||
|
||||
Yes. WooNooW is an enhancement layer for WooCommerce. You need WooCommerce installed and activated.
|
||||
|
||||
### Will WooNooW affect my existing products?
|
||||
|
||||
No. WooNooW reads from WooCommerce. Your products, orders, and settings remain untouched.
|
||||
|
||||
---
|
||||
|
||||
## SPA Mode
|
||||
|
||||
### What's the difference between Full and Disabled mode?
|
||||
|
||||
| Mode | Behavior |
|
||||
|------|----------|
|
||||
| **Full** | All WooCommerce pages redirect to SPA. Modern, fast experience. |
|
||||
| **Disabled** | WooCommerce pages use native templates. WooNooW admin still works. |
|
||||
|
||||
### Can I switch modes anytime?
|
||||
|
||||
Yes. Go to **WooNooW → Appearance → General** and change the SPA Mode. Changes take effect immediately.
|
||||
|
||||
### Which mode should I use?
|
||||
|
||||
- **Full**: For the best customer experience with instant loads
|
||||
- **Disabled**: If you have theme customizations you want to keep
|
||||
|
||||
---
|
||||
|
||||
## Compatibility
|
||||
|
||||
### Does WooNooW work with my theme?
|
||||
|
||||
WooNooW's SPA is independent of your WordPress theme. In Full mode, the SPA uses its own styling. Your theme affects the rest of your site normally.
|
||||
|
||||
### Does WooNooW work with page builders?
|
||||
|
||||
The SPA pages are self-contained. Page builders work on other pages of your site.
|
||||
|
||||
### Which payment gateways are supported?
|
||||
|
||||
WooNooW supports all WooCommerce-compatible payment gateways:
|
||||
- PayPal
|
||||
- Stripe
|
||||
- Bank Transfer (BACS)
|
||||
- Cash on Delivery
|
||||
- And more...
|
||||
|
||||
---
|
||||
|
||||
## SEO
|
||||
|
||||
### Is WooNooW SEO-friendly?
|
||||
|
||||
Yes. WooNooW uses:
|
||||
- Clean URLs (`/store/product/product-name`)
|
||||
- Dynamic meta tags for social sharing
|
||||
- Proper redirects (302) from WooCommerce URLs
|
||||
|
||||
### What about my existing SEO?
|
||||
|
||||
WooCommerce URLs remain the indexed source. WooNooW redirects users to the SPA but preserves SEO value.
|
||||
|
||||
### Will my product pages be indexed?
|
||||
|
||||
Yes. Search engines index the WooCommerce URLs. When users click from search results, they're redirected to the fast SPA experience.
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
### Is WooNooW faster than regular WooCommerce?
|
||||
|
||||
Yes, for navigation. After the initial load, page transitions are instant because the SPA doesn't reload the entire page.
|
||||
|
||||
### Will WooNooW slow down my site?
|
||||
|
||||
The initial load is similar to regular WooCommerce. Subsequent navigation is much faster.
|
||||
|
||||
### Does WooNooW work with caching?
|
||||
|
||||
Yes. Use page caching and object caching for best results.
|
||||
|
||||
---
|
||||
|
||||
## Customization
|
||||
|
||||
### Can I customize colors and fonts?
|
||||
|
||||
Yes. Go to **WooNooW → Appearance** to customize:
|
||||
- Primary, secondary, and accent colors
|
||||
- Body and heading fonts
|
||||
- Logo and layout options
|
||||
|
||||
### Can I add custom CSS?
|
||||
|
||||
Currently, use your theme's Additional CSS feature. A custom CSS field may be added in future versions.
|
||||
|
||||
### Can I modify the SPA templates?
|
||||
|
||||
The SPA is built with React. Advanced customizations require development knowledge.
|
||||
|
||||
---
|
||||
|
||||
## Addons
|
||||
|
||||
### What are WooNooW addons?
|
||||
|
||||
Addons extend WooNooW with additional features like loyalty points, advanced analytics, etc.
|
||||
|
||||
### How do I install addons?
|
||||
|
||||
Addons are installed as separate WordPress plugins. They integrate automatically with WooNooW.
|
||||
|
||||
### Do addons work when SPA is disabled?
|
||||
|
||||
Most addon features are for the SPA. When disabled, addon functionality may be limited.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### I see a blank page. What do I do?
|
||||
|
||||
1. Check SPA Mode is set to "Full"
|
||||
2. Flush permalinks (**Settings → Permalinks → Save**)
|
||||
3. Clear all caches
|
||||
4. See [Troubleshooting](troubleshooting) for more
|
||||
|
||||
### How do I report a bug?
|
||||
|
||||
Contact support with:
|
||||
- Steps to reproduce the issue
|
||||
- WordPress/WooCommerce/WooNooW versions
|
||||
- Any error messages
|
||||
- Screenshots if applicable
|
||||
145
docs/features/checkout.md
Normal file
145
docs/features/checkout.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Checkout
|
||||
|
||||
The WooNooW checkout provides a streamlined purchasing experience.
|
||||
|
||||
## Overview
|
||||
|
||||
The checkout process includes:
|
||||
|
||||
1. **Cart Review** - Verify items before checkout
|
||||
2. **Customer Information** - Billing and shipping details
|
||||
3. **Payment Method** - Select how to pay
|
||||
4. **Order Confirmation** - Complete the purchase
|
||||
|
||||
---
|
||||
|
||||
## Checkout Flow
|
||||
|
||||
### Step 1: Cart
|
||||
|
||||
Before checkout, customers review their cart:
|
||||
- Product list with images
|
||||
- Quantity adjustments
|
||||
- Remove items
|
||||
- Apply coupon codes
|
||||
- See subtotal, shipping, and total
|
||||
|
||||
### Step 2: Customer Details
|
||||
|
||||
Customers provide:
|
||||
- **Email address**
|
||||
- **Billing information**
|
||||
- Name
|
||||
- Address
|
||||
- Phone
|
||||
- **Shipping address** (if different from billing)
|
||||
|
||||
> **Note**: Logged-in customers have their details pre-filled.
|
||||
|
||||
### Step 3: Shipping Method
|
||||
|
||||
If physical products are in the cart:
|
||||
- Available shipping methods are shown
|
||||
- Shipping cost is calculated
|
||||
- Customer selects preferred method
|
||||
|
||||
### Step 4: Payment
|
||||
|
||||
Customers choose their payment method:
|
||||
- Credit/Debit Card (Stripe, PayPal, etc.)
|
||||
- Bank Transfer
|
||||
- Cash on Delivery
|
||||
- Other configured gateways
|
||||
|
||||
### Step 5: Place Order
|
||||
|
||||
After reviewing everything:
|
||||
- Click "Place Order"
|
||||
- Payment is processed
|
||||
- Confirmation page is shown
|
||||
- Email receipt is sent
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
### Guest Checkout
|
||||
|
||||
Allow customers to checkout without creating an account.
|
||||
|
||||
Configure in **WooCommerce → Settings → Accounts & Privacy**.
|
||||
|
||||
### Coupon Codes
|
||||
|
||||
Customers can apply discount codes:
|
||||
1. Enter code in the coupon field
|
||||
2. Click "Apply"
|
||||
3. Discount is reflected in total
|
||||
|
||||
### Order Notes
|
||||
|
||||
Optional field for customers to add special instructions.
|
||||
|
||||
---
|
||||
|
||||
## Payment Gateways
|
||||
|
||||
### Supported Gateways
|
||||
|
||||
WooNooW supports all WooCommerce payment gateways:
|
||||
|
||||
| Gateway | Type |
|
||||
|---------|------|
|
||||
| Bank Transfer (BACS) | Manual |
|
||||
| Check Payments | Manual |
|
||||
| Cash on Delivery | Manual |
|
||||
| PayPal | Card / PayPal |
|
||||
| Stripe | Card |
|
||||
| Square | Card |
|
||||
|
||||
### Configuring Gateways
|
||||
|
||||
1. Go to **WooNooW → Settings → Payments**
|
||||
2. Enable desired payment methods
|
||||
3. Configure API keys and settings
|
||||
4. Test with sandbox/test mode first
|
||||
|
||||
---
|
||||
|
||||
## After Checkout
|
||||
|
||||
### Order Confirmation Page
|
||||
|
||||
Shows:
|
||||
- Order number
|
||||
- Order summary
|
||||
- Next steps
|
||||
|
||||
### Confirmation Email
|
||||
|
||||
Automatically sent to customer with:
|
||||
- Order details
|
||||
- Payment confirmation
|
||||
- Shipping information (if applicable)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Place Order" Button Not Working
|
||||
|
||||
1. Check all required fields are filled
|
||||
2. Verify payment gateway is properly configured
|
||||
3. Check browser console for JavaScript errors
|
||||
|
||||
### Payment Declined
|
||||
|
||||
1. Customer should verify card details
|
||||
2. Check payment gateway dashboard for error details
|
||||
3. Ensure correct API keys are configured
|
||||
|
||||
### Shipping Not Showing
|
||||
|
||||
1. Verify shipping zones are configured in WooCommerce
|
||||
2. Check if products have weight/dimensions set
|
||||
3. Confirm customer's address is in a configured zone
|
||||
96
docs/features/shop.md
Normal file
96
docs/features/shop.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Shop Page
|
||||
|
||||
The shop page displays your product catalog with browsing and filtering options.
|
||||
|
||||
## Overview
|
||||
|
||||
The WooNooW shop page provides:
|
||||
|
||||
- **Product Grid** - Visual display of products
|
||||
- **Search** - Find products by name
|
||||
- **Filters** - Category and sorting options
|
||||
- **Pagination** - Navigate through products
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
### Product Cards
|
||||
|
||||
Each product displays:
|
||||
- Product image
|
||||
- Product name
|
||||
- Price (with sale price if applicable)
|
||||
- Add to Cart button
|
||||
- Wishlist button (if enabled)
|
||||
|
||||
### Search
|
||||
|
||||
Type in the search box to filter products by name. Search is instant and updates the grid as you type.
|
||||
|
||||
### Category Filter
|
||||
|
||||
Filter products by category using the dropdown. Shows:
|
||||
- All Categories
|
||||
- Individual categories with product count
|
||||
|
||||
### Sorting
|
||||
|
||||
Sort products by:
|
||||
- Default sorting
|
||||
- Popularity
|
||||
- Average rating
|
||||
- Latest
|
||||
- Price: Low to High
|
||||
- Price: High to Low
|
||||
|
||||
---
|
||||
|
||||
## Customization
|
||||
|
||||
### Grid Layout
|
||||
|
||||
Configure the product grid in **WooNooW → Appearance**:
|
||||
|
||||
| Device | Options |
|
||||
|--------|---------|
|
||||
| Mobile | 1-2 columns |
|
||||
| Tablet | 2-4 columns |
|
||||
| Desktop | 2-6 columns |
|
||||
|
||||
### Product Card Style
|
||||
|
||||
Product cards can display:
|
||||
- **Image** - Product featured image
|
||||
- **Title** - Product name
|
||||
- **Price** - Current price and sale price
|
||||
- **Rating** - Star rating (if reviews enabled)
|
||||
- **Add to Cart** - Quick add button
|
||||
|
||||
---
|
||||
|
||||
## Navigation
|
||||
|
||||
### Clicking a Product
|
||||
|
||||
Clicking a product card navigates to the full product page where customers can:
|
||||
- View all images
|
||||
- Select variations
|
||||
- Read description
|
||||
- Add to cart
|
||||
|
||||
### Back to Shop
|
||||
|
||||
From any product page, use the breadcrumb or browser back button to return to the shop.
|
||||
|
||||
---
|
||||
|
||||
## Performance
|
||||
|
||||
### Lazy Loading
|
||||
|
||||
Product images load as they come into view, improving initial page load time.
|
||||
|
||||
### Infinite Scroll vs Pagination
|
||||
|
||||
Currently uses pagination. Infinite scroll may be added in future versions.
|
||||
54
docs/getting-started.md
Normal file
54
docs/getting-started.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Getting Started with WooNooW
|
||||
|
||||
Welcome to WooNooW! This guide will help you get up and running quickly.
|
||||
|
||||
## What is WooNooW?
|
||||
|
||||
WooNooW transforms your WooCommerce store into a modern, fast Single Page Application (SPA). It provides:
|
||||
|
||||
- ⚡ **Instant Page Loads** - No page refreshes between navigation
|
||||
- 🎨 **Modern UI** - Beautiful, responsive design out of the box
|
||||
- 🛠 **Easy Customization** - Configure colors, fonts, and layout from admin
|
||||
- 📱 **Mobile-First** - Optimized for all devices
|
||||
|
||||
## Quick Setup (3 Steps)
|
||||
|
||||
### Step 1: Activate the Plugin
|
||||
|
||||
After installing WooNooW, activate it from **Plugins → Installed Plugins**.
|
||||
|
||||
The plugin will automatically:
|
||||
- Create a "Store" page for the SPA
|
||||
- Configure basic settings
|
||||
|
||||
### Step 2: Access Admin Dashboard
|
||||
|
||||
Go to **WooNooW** in your WordPress admin menu.
|
||||
|
||||
You'll see the admin dashboard with:
|
||||
- Orders management
|
||||
- Settings configuration
|
||||
- Appearance customization
|
||||
|
||||
### Step 3: Configure Your Store
|
||||
|
||||
Navigate to **Appearance** settings to:
|
||||
|
||||
1. **Upload your logo**
|
||||
2. **Set brand colors** (primary, secondary, accent)
|
||||
3. **Choose fonts** for headings and body text
|
||||
4. **Configure SPA mode** (Full or Disabled)
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Installation Guide](installation) - Detailed installation instructions
|
||||
- [Appearance Settings](configuration/appearance) - Customize your store's look
|
||||
- [SPA Mode](configuration/spa-mode) - Understand Full vs Disabled mode
|
||||
- [Troubleshooting](troubleshooting) - Common issues and solutions
|
||||
|
||||
## Need Help?
|
||||
|
||||
If you encounter any issues:
|
||||
1. Check the [Troubleshooting](troubleshooting) guide
|
||||
2. Review the [FAQ](faq)
|
||||
3. Contact support with your WordPress and WooCommerce versions
|
||||
92
docs/installation.md
Normal file
92
docs/installation.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Installation Guide
|
||||
|
||||
This guide covers installing WooNooW on your WordPress site.
|
||||
|
||||
## Requirements
|
||||
|
||||
Before installing, ensure your site meets these requirements:
|
||||
|
||||
| Requirement | Minimum | Recommended |
|
||||
|-------------|---------|-------------|
|
||||
| WordPress | 6.0+ | Latest |
|
||||
| WooCommerce | 7.0+ | Latest |
|
||||
| PHP | 7.4+ | 8.1+ |
|
||||
| MySQL | 5.7+ | 8.0+ |
|
||||
|
||||
## Installation Methods
|
||||
|
||||
### Method 1: WordPress Admin (Recommended)
|
||||
|
||||
1. Go to **Plugins → Add New**
|
||||
2. Click **Upload Plugin**
|
||||
3. Select the `woonoow.zip` file
|
||||
4. Click **Install Now**
|
||||
5. Click **Activate**
|
||||
|
||||
### Method 2: FTP Upload
|
||||
|
||||
1. Extract `woonoow.zip` to get the `woonoow` folder
|
||||
2. Upload to `/wp-content/plugins/`
|
||||
3. Go to **Plugins → Installed Plugins**
|
||||
4. Find WooNooW and click **Activate**
|
||||
|
||||
## Post-Installation
|
||||
|
||||
After activation, WooNooW automatically:
|
||||
|
||||
### 1. Creates Store Page
|
||||
A new "Store" page is created with the SPA shortcode. This is your main storefront.
|
||||
|
||||
### 2. Registers Rewrite Rules
|
||||
URL routes like `/store/shop` and `/store/product/...` are registered.
|
||||
|
||||
> **Note**: If you see 404 errors, go to **Settings → Permalinks** and click **Save Changes** to flush rewrite rules.
|
||||
|
||||
### 3. Sets Default Configuration
|
||||
Basic appearance settings are configured with sensible defaults.
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
After installation, verify everything works:
|
||||
|
||||
- [ ] Plugin activated without errors
|
||||
- [ ] WooNooW menu appears in admin sidebar
|
||||
- [ ] Store page exists (check **Pages**)
|
||||
- [ ] `/store` URL loads the SPA
|
||||
- [ ] Products display on shop page
|
||||
|
||||
## WooCommerce Compatibility
|
||||
|
||||
WooNooW works alongside WooCommerce:
|
||||
|
||||
| WooCommerce Page | WooNooW Behavior (Full Mode) |
|
||||
|------------------|------------------------------|
|
||||
| `/shop` | Redirects to `/store/shop` |
|
||||
| `/product/...` | Redirects to `/store/product/...` |
|
||||
| `/cart` | Redirects to `/store/cart` |
|
||||
| `/checkout` | Redirects to `/store/checkout` |
|
||||
| `/my-account` | Redirects to `/store/my-account` |
|
||||
|
||||
When SPA Mode is **Disabled**, WooCommerce pages work normally.
|
||||
|
||||
## Updating
|
||||
|
||||
To update WooNooW:
|
||||
|
||||
1. Download the latest version
|
||||
2. Go to **Plugins → Installed Plugins**
|
||||
3. Deactivate WooNooW (optional but recommended)
|
||||
4. Delete the old version
|
||||
5. Install and activate the new version
|
||||
|
||||
Your settings are preserved in the database.
|
||||
|
||||
## Uninstalling
|
||||
|
||||
To completely remove WooNooW:
|
||||
|
||||
1. Deactivate the plugin (restores WooCommerce page content)
|
||||
2. Delete the plugin
|
||||
3. (Optional) Delete WooNooW options from database
|
||||
|
||||
> **Note**: Deactivating restores original WooCommerce shortcodes to Cart, Checkout, and My Account pages.
|
||||
173
docs/troubleshooting.md
Normal file
173
docs/troubleshooting.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Troubleshooting
|
||||
|
||||
Common issues and their solutions.
|
||||
|
||||
## Blank Pages
|
||||
|
||||
### Symptom
|
||||
WooCommerce pages (shop, cart, checkout) show blank content.
|
||||
|
||||
### Solutions
|
||||
|
||||
**1. Check SPA Mode Setting**
|
||||
- Go to **WooNooW → Appearance → General**
|
||||
- Ensure **SPA Mode** is set to "Full"
|
||||
- If you want native WooCommerce, set to "Disabled"
|
||||
|
||||
**2. Flush Permalinks**
|
||||
- Go to **Settings → Permalinks**
|
||||
- Click **Save Changes** (no changes needed)
|
||||
- This refreshes rewrite rules
|
||||
|
||||
**3. Clear Cache**
|
||||
If using a caching plugin:
|
||||
- Clear page cache
|
||||
- Clear object cache
|
||||
- Purge CDN cache (if applicable)
|
||||
|
||||
---
|
||||
|
||||
## 404 Errors on SPA Routes
|
||||
|
||||
### Symptom
|
||||
Visiting `/store/shop` or `/store/product/...` shows a 404 error.
|
||||
|
||||
### Solutions
|
||||
|
||||
**1. Flush Permalinks**
|
||||
- Go to **Settings → Permalinks**
|
||||
- Click **Save Changes**
|
||||
|
||||
**2. Check Store Page Exists**
|
||||
- Go to **Pages**
|
||||
- Verify "Store" page exists and is published
|
||||
- The page should contain `[woonoow_spa]` shortcode
|
||||
|
||||
**3. Check SPA Page Setting**
|
||||
- Go to **WooNooW → Appearance → General**
|
||||
- Ensure **SPA Page** is set to the Store page
|
||||
|
||||
---
|
||||
|
||||
## Product Images Not Loading
|
||||
|
||||
### Symptom
|
||||
Products show placeholder images instead of actual images.
|
||||
|
||||
### Solutions
|
||||
|
||||
**1. Regenerate Thumbnails**
|
||||
- Install "Regenerate Thumbnails" plugin
|
||||
- Run regeneration for all images
|
||||
|
||||
**2. Check Image URLs**
|
||||
- Ensure images have valid URLs
|
||||
- Check for mixed content (HTTP vs HTTPS)
|
||||
|
||||
---
|
||||
|
||||
## Slow Performance
|
||||
|
||||
### Symptom
|
||||
SPA feels slow or laggy.
|
||||
|
||||
### Solutions
|
||||
|
||||
**1. Enable Caching**
|
||||
- Install a caching plugin (WP Super Cache, W3 Total Cache)
|
||||
- Enable object caching (Redis/Memcached)
|
||||
|
||||
**2. Optimize Images**
|
||||
- Use WebP format
|
||||
- Compress images before upload
|
||||
- Use lazy loading
|
||||
|
||||
**3. Check Server Resources**
|
||||
- Upgrade hosting if on shared hosting
|
||||
- Consider VPS or managed WordPress hosting
|
||||
|
||||
---
|
||||
|
||||
## Checkout Not Working
|
||||
|
||||
### Symptom
|
||||
Checkout page won't load or payment fails.
|
||||
|
||||
### Solutions
|
||||
|
||||
**1. Check Payment Gateway**
|
||||
- Go to **WooCommerce → Settings → Payments**
|
||||
- Verify payment method is enabled
|
||||
- Check API credentials
|
||||
|
||||
**2. Check SSL Certificate**
|
||||
- Checkout requires HTTPS
|
||||
- Verify SSL is properly installed
|
||||
|
||||
**3. Check for JavaScript Errors**
|
||||
- Open browser Developer Tools (F12)
|
||||
- Check Console for errors
|
||||
- Look for blocked scripts
|
||||
|
||||
---
|
||||
|
||||
## Emails Not Sending
|
||||
|
||||
### Symptom
|
||||
Order confirmation emails not being received.
|
||||
|
||||
### Solutions
|
||||
|
||||
**1. Check Email Settings**
|
||||
- Go to **WooNooW → Settings → Notifications**
|
||||
- Verify email types are enabled
|
||||
|
||||
**2. Check WordPress Email**
|
||||
- Test with a plugin like "Check & Log Email"
|
||||
- Consider using SMTP plugin (WP Mail SMTP)
|
||||
|
||||
**3. Check Spam Folder**
|
||||
- Emails may be in recipient's spam folder
|
||||
- Add sender to whitelist
|
||||
|
||||
---
|
||||
|
||||
## Plugin Conflicts
|
||||
|
||||
### Symptom
|
||||
WooNooW doesn't work after installing another plugin.
|
||||
|
||||
### Steps to Diagnose
|
||||
|
||||
1. **Deactivate other plugins** one by one
|
||||
2. **Switch to default theme** (Twenty Twenty-Three)
|
||||
3. **Check error logs** in `wp-content/debug.log`
|
||||
|
||||
### Common Conflicting Plugins
|
||||
|
||||
- Other WooCommerce template overrides
|
||||
- Page builder plugins (sometimes)
|
||||
- Heavy caching plugins (misconfigured)
|
||||
|
||||
---
|
||||
|
||||
## Getting More Help
|
||||
|
||||
If you can't resolve the issue:
|
||||
|
||||
1. **Collect Information**
|
||||
- WordPress version
|
||||
- WooCommerce version
|
||||
- WooNooW version
|
||||
- PHP version
|
||||
- Error messages (from debug.log)
|
||||
|
||||
2. **Enable Debug Mode**
|
||||
Add to `wp-config.php`:
|
||||
```php
|
||||
define('WP_DEBUG', true);
|
||||
define('WP_DEBUG_LOG', true);
|
||||
```
|
||||
|
||||
3. **Contact Support**
|
||||
Provide the collected information for faster resolution.
|
||||
129
includes/Api/DocsController.php
Normal file
129
includes/Api/DocsController.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* Documentation API Controller
|
||||
*
|
||||
* Serves documentation content to the Admin SPA.
|
||||
*/
|
||||
|
||||
namespace WooNooW\Api;
|
||||
|
||||
use WP_REST_Controller;
|
||||
use WP_REST_Response;
|
||||
use WP_REST_Request;
|
||||
use WP_Error;
|
||||
|
||||
class DocsController extends WP_REST_Controller {
|
||||
|
||||
/**
|
||||
* Namespace for REST routes
|
||||
*/
|
||||
protected $namespace = 'woonoow/v1';
|
||||
|
||||
/**
|
||||
* Base route
|
||||
*/
|
||||
protected $rest_base = 'docs';
|
||||
|
||||
/**
|
||||
* Register routes
|
||||
*/
|
||||
public function register_routes() {
|
||||
// GET /woonoow/v1/docs - List all documentation
|
||||
register_rest_route($this->namespace, '/' . $this->rest_base, [
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_docs_registry'],
|
||||
'permission_callback' => [$this, 'check_permissions'],
|
||||
],
|
||||
]);
|
||||
|
||||
// GET /woonoow/v1/docs/{slug} - Get single document
|
||||
register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<slug>.+)', [
|
||||
[
|
||||
'methods' => 'GET',
|
||||
'callback' => [$this, 'get_doc'],
|
||||
'permission_callback' => [$this, 'check_permissions'],
|
||||
'args' => [
|
||||
'slug' => [
|
||||
'required' => true,
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check permissions - any logged in admin user
|
||||
*/
|
||||
public function check_permissions($request) {
|
||||
return current_user_can('manage_options');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get documentation registry
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function get_docs_registry($request) {
|
||||
require_once WOONOOW_PLUGIN_DIR . 'docs/_registry.php';
|
||||
|
||||
$registry = \WooNooW\Docs\get_docs_registry();
|
||||
|
||||
// Transform to frontend format (without file paths)
|
||||
$result = [];
|
||||
foreach ($registry as $section_key => $section) {
|
||||
$items = [];
|
||||
foreach ($section['items'] as $item) {
|
||||
$items[] = [
|
||||
'slug' => $item['slug'],
|
||||
'title' => $item['title'],
|
||||
];
|
||||
}
|
||||
|
||||
$result[] = [
|
||||
'key' => $section_key,
|
||||
'label' => $section['label'],
|
||||
'icon' => $section['icon'] ?? 'file-text',
|
||||
'items' => $items,
|
||||
];
|
||||
}
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'sections' => $result,
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single document content
|
||||
*
|
||||
* @param WP_REST_Request $request
|
||||
* @return WP_REST_Response|WP_Error
|
||||
*/
|
||||
public function get_doc($request) {
|
||||
$slug = $request->get_param('slug');
|
||||
|
||||
require_once WOONOOW_PLUGIN_DIR . 'docs/_registry.php';
|
||||
|
||||
$doc = \WooNooW\Docs\get_doc_by_slug($slug);
|
||||
|
||||
if (!$doc) {
|
||||
return new WP_Error(
|
||||
'doc_not_found',
|
||||
'Documentation not found',
|
||||
['status' => 404]
|
||||
);
|
||||
}
|
||||
|
||||
return new WP_REST_Response([
|
||||
'success' => true,
|
||||
'doc' => [
|
||||
'slug' => $doc['slug'],
|
||||
'title' => $doc['title'],
|
||||
'content' => $doc['content'],
|
||||
],
|
||||
], 200);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ use WooNooW\Api\NewsletterController;
|
||||
use WooNooW\Api\ModulesController;
|
||||
use WooNooW\Api\ModuleSettingsController;
|
||||
use WooNooW\Api\CampaignsController;
|
||||
use WooNooW\Api\DocsController;
|
||||
use WooNooW\Frontend\ShopController;
|
||||
use WooNooW\Frontend\CartController as FrontendCartController;
|
||||
use WooNooW\Frontend\AccountController;
|
||||
@@ -165,6 +166,10 @@ class Routes {
|
||||
$module_settings_controller = new ModuleSettingsController();
|
||||
$module_settings_controller->register_routes();
|
||||
|
||||
// Documentation controller
|
||||
$docs_controller = new DocsController();
|
||||
$docs_controller->register_routes();
|
||||
|
||||
// Frontend controllers (customer-facing)
|
||||
ShopController::register_routes();
|
||||
FrontendCartController::register_routes();
|
||||
|
||||
Reference in New Issue
Block a user