- Create 6 new tenant API documentation pages: - HelpApiOverview: Authentication, scopes, rate limits, errors - HelpApiAppointments: CRUD operations for appointments - HelpApiServices: Read-only service catalog access - HelpApiResources: Staff, rooms, equipment endpoints - HelpApiCustomers: Customer management endpoints - HelpApiWebhooks: Real-time event subscriptions - Create 6 new settings help pages for granular documentation - Update HelpComprehensive with API section linking to new docs - Update platform HelpApiDocs with comprehensive endpoint coverage - Fix non-clickable /api/v1/docs/ links (now opens in new tab) - Add routes for all new help pages in App.tsx - Update FloatingHelpButton with new help page mappings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
116 lines
4.0 KiB
TypeScript
116 lines
4.0 KiB
TypeScript
/**
|
|
* FloatingHelpButton Component
|
|
*
|
|
* A floating help button fixed in the top-right corner of the screen.
|
|
* Automatically determines the help path based on the current route.
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { Link, useLocation } from 'react-router-dom';
|
|
import { HelpCircle } from 'lucide-react';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
// Map route suffixes to their help page suffixes
|
|
// These get prefixed appropriately based on context (tenant dashboard or public)
|
|
const routeToHelpSuffix: Record<string, string> = {
|
|
'/': 'dashboard',
|
|
'/dashboard': 'dashboard',
|
|
'/scheduler': 'scheduler',
|
|
'/my-schedule': 'scheduler',
|
|
'/tasks': 'tasks',
|
|
'/customers': 'customers',
|
|
'/services': 'services',
|
|
'/resources': 'resources',
|
|
'/locations': 'locations',
|
|
'/staff': 'staff',
|
|
'/time-blocks': 'time-blocks',
|
|
'/my-availability': 'time-blocks',
|
|
'/messages': 'messages',
|
|
'/tickets': 'ticketing',
|
|
'/payments': 'payments',
|
|
'/contracts': 'contracts',
|
|
'/contracts/templates': 'contracts',
|
|
'/automations': 'automations',
|
|
'/automations/marketplace': 'automations',
|
|
'/automations/my-automations': 'automations',
|
|
'/automations/create': 'automations/docs',
|
|
'/site-editor': 'site-builder',
|
|
'/gallery': 'site-builder',
|
|
'/settings': 'settings/general',
|
|
'/settings/general': 'settings/general',
|
|
'/settings/resource-types': 'settings/resource-types',
|
|
'/settings/booking': 'settings/booking',
|
|
'/settings/appearance': 'settings/appearance',
|
|
'/settings/branding': 'settings/appearance',
|
|
'/settings/business-hours': 'settings/business-hours',
|
|
'/settings/email': 'settings/email',
|
|
'/settings/email-templates': 'settings/email-templates',
|
|
'/settings/embed-widget': 'settings/embed-widget',
|
|
'/settings/staff-roles': 'settings/staff-roles',
|
|
'/settings/sms-calling': 'settings/communication',
|
|
'/settings/domains': 'settings/domains',
|
|
'/settings/api': 'settings/api',
|
|
'/settings/auth': 'settings/auth',
|
|
'/settings/billing': 'settings/billing',
|
|
'/settings/quota': 'settings/quota',
|
|
};
|
|
|
|
const FloatingHelpButton: React.FC = () => {
|
|
const { t } = useTranslation();
|
|
const location = useLocation();
|
|
|
|
// Check if we're on a tenant dashboard route
|
|
const isOnDashboard = location.pathname.startsWith('/dashboard');
|
|
|
|
// Get the help path for the current route
|
|
const getHelpPath = (): string => {
|
|
// Determine the base help path based on context
|
|
const helpBase = isOnDashboard ? '/dashboard/help' : '/help';
|
|
|
|
// Get the route to look up (strip /dashboard prefix if present)
|
|
const lookupPath = isOnDashboard
|
|
? location.pathname.replace(/^\/dashboard/, '') || '/'
|
|
: location.pathname;
|
|
|
|
// Exact match first
|
|
if (routeToHelpSuffix[lookupPath]) {
|
|
return `${helpBase}/${routeToHelpSuffix[lookupPath]}`;
|
|
}
|
|
|
|
// Try matching with a prefix (for dynamic routes like /customers/:id)
|
|
const pathSegments = lookupPath.split('/').filter(Boolean);
|
|
if (pathSegments.length > 0) {
|
|
// Try progressively shorter paths
|
|
for (let i = pathSegments.length; i > 0; i--) {
|
|
const testPath = '/' + pathSegments.slice(0, i).join('/');
|
|
if (routeToHelpSuffix[testPath]) {
|
|
return `${helpBase}/${routeToHelpSuffix[testPath]}`;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Default to the main help page
|
|
return helpBase;
|
|
};
|
|
|
|
const helpPath = getHelpPath();
|
|
|
|
// Don't show on help pages themselves
|
|
if (location.pathname.includes('/help')) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Link
|
|
to={helpPath}
|
|
className="fixed top-20 right-4 z-50 inline-flex items-center justify-center w-10 h-10 bg-white dark:bg-gray-800 text-gray-500 dark:text-gray-400 hover:text-brand-600 dark:hover:text-brand-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-full shadow-lg border border-gray-200 dark:border-gray-700 transition-all duration-200 hover:scale-110"
|
|
title={t('common.help', 'Help')}
|
|
aria-label={t('common.help', 'Help')}
|
|
>
|
|
<HelpCircle size={20} />
|
|
</Link>
|
|
);
|
|
};
|
|
|
|
export default FloatingHelpButton;
|