# thinkrank/1.0.0/src/admin/hooks/useTabSettings.js

ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console &amp; Local SEO, version 1.0.0. 304 lines.

- Page: https://pluginprobe.com/plugins/thinkrank/1.0.0/code/src/admin/hooks/useTabSettings.js
- Raw: https://pluginprobe.com/plugins/thinkrank/1.0.0/raw/src/admin/hooks/useTabSettings.js
- Modified: 2025-08-10T07:57:44+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/thinkrank/1.0.0/code/src/admin/hooks/useTabSettings.js#L10-L20`.

```javascript
/**
 * useTabSettings Hook
 * 
 * Reusable hook extracted from Site Identity state management patterns.
 * Provides consistent state management, API integration, and optimization
 * functionality across all Essential SEO tabs.
 * 
 * @package ThinkRank
 * @since 1.0.0
 */

import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';

/**
 * useTabSettings Hook
 * 
 * @param {string} tabName Tab identifier for API endpoints (e.g., 'site-identity', 'homepage-seo')
 * @param {Object} defaultSettings Default settings object
 * @param {Object} options Hook configuration options
 * @param {boolean} options.autoLoad Auto-load settings on mount (default: true)
 * @param {boolean} options.enableOptimization Enable optimization functionality (default: true)
 * @param {boolean} options.enableValidation Enable validation functionality (default: true)
 * 
 * @return {Object} Hook state and methods
 */
const useTabSettings = (tabName, defaultSettings, options = {}) => {
    const {
        autoLoad = true,
        enableOptimization = true,
        enableValidation = true,
        tabDisplayName = null // Human-readable tab name for notices
    } = options;

    // Core state management (extracted from Site Identity pattern)
    const [isLoading, setIsLoading] = useState(true);
    const [isSaving, setIsSaving] = useState(false);
    const [settings, setSettings] = useState({});
    const [hasChanges, setHasChanges] = useState(false);
    const [notice, setNotice] = useState(null);
    
    // Optimization states (conditional based on options)
    const [isOptimizing, setIsOptimizing] = useState(false);
    const [isValidating, setIsValidating] = useState(false);
    const [optimizationResults, setOptimizationResults] = useState(null);
    const [validationResults, setValidationResults] = useState(null);
    
    const apiBasePath = `/thinkrank/v1/${tabName}`;

    /**
     * Get human-readable tab name for notices
     */
    const getTabDisplayName = () => {
        if (tabDisplayName) return tabDisplayName;

        // Generate display name from tabName
        const displayNames = {
            'site-identity': __('Site Identity', 'thinkrank'),
            'homepage-seo': __('Homepage SEO', 'thinkrank'),
            'analytics': __('Analytics', 'thinkrank'),
            'schema': __('Schema', 'thinkrank'),
            'social-media': __('Social Media', 'thinkrank'),
            'sitemap': __('Sitemap', 'thinkrank')
        };

        return displayNames[tabName] || __('Settings', 'thinkrank');
    };

    /**
     * Load settings from API
     * Extracted from Site Identity loadSettings pattern
     */
    const loadSettings = async () => {
        try {
            setIsLoading(true);
            const response = await apiFetch({
                path: `${apiBasePath}/settings`,
                method: 'GET'
            });

            if (response.success) {
                setSettings({ ...defaultSettings, ...response.data.settings });
            } else {
                setSettings(defaultSettings);
            }
        } catch (error) {
            console.error(`${tabName} settings load error:`, error);
            setSettings(defaultSettings);
        } finally {
            setIsLoading(false);
        }
    };

    /**
     * Save settings to API
     * Extracted from Site Identity saveSettings pattern
     */
    const saveSettings = async () => {
        try {
            setIsSaving(true);
            setNotice(null);

            const response = await apiFetch({
                path: `${apiBasePath}/settings`,
                method: 'POST',
                data: {
                    settings,
                    context_type: 'site'
                }
            });

            if (response.success) {
                setHasChanges(false);
                setNotice({
                    status: 'success',
                    message: __(`${getTabDisplayName()} settings saved successfully!`, 'thinkrank')
                });
            } else {
                throw new Error(response.error || 'Failed to save settings');
            }
        } catch (error) {
            console.error(`${tabName} settings save error:`, error);
            setNotice({
                status: 'error',
                message: __(`Failed to save ${getTabDisplayName()} settings. Please try again.`, 'thinkrank')
            });
        } finally {
            setIsSaving(false);
        }
    };

    /**
     * Handle setting change
     * Extracted from Site Identity handleSettingChange pattern
     */
    const handleSettingChange = (key, value) => {
        setSettings(prev => ({
            ...prev,
            [key]: value
        }));
        setHasChanges(true);
    };

    /**
     * Generic optimization handler
     * Extracted from Site Identity optimization patterns
     */
    const runOptimization = async (optimizationType, data, options = {}) => {
        if (!enableOptimization) {
            console.warn('Optimization is disabled for this tab');
            return;
        }

        try {
            setIsOptimizing(true);
            setNotice(null);

            const response = await apiFetch({
                path: `${apiBasePath}/optimize`,
                method: 'POST',
                data: {
                    type: optimizationType,
                    data,
                    options
                }
            });

            if (response.success) {
                setOptimizationResults(response.data);
                setNotice({
                    status: 'success',
                    message: __(`${getTabDisplayName()} optimization completed successfully!`, 'thinkrank')
                });
                
                // Auto-apply results if specified
                if (options.autoApply && response.data.optimized_settings) {
                    setSettings(prev => ({
                        ...prev,
                        ...response.data.optimized_settings
                    }));
                    setHasChanges(true);
                }
                
                return response.data;
            }
        } catch (error) {
            console.error(`${tabName} optimization error:`, error);
            
            // Enhanced error handling from Site Identity
            let errorMessage = __('Optimization failed.', 'thinkrank');
            if (error.message?.includes('API key')) {
                errorMessage = __('AI optimization requires an API key. Please configure your API key in ThinkRank settings.', 'thinkrank');
            } else if (error.message?.includes('rate limit')) {
                errorMessage = __('AI service rate limit reached. Please try again in a few minutes.', 'thinkrank');
            }

            setNotice({
                status: 'error',
                message: errorMessage
            });
        } finally {
            setIsOptimizing(false);
        }
    };

    /**
     * Generic validation handler
     * Extracted from Site Identity validation patterns
     */
    const runValidation = async (validationType, data) => {
        if (!enableValidation) {
            console.warn('Validation is disabled for this tab');
            return;
        }

        try {
            setIsValidating(true);
            
            const response = await apiFetch({
                path: `${apiBasePath}/validate`,
                method: 'POST',
                data: {
                    type: validationType,
                    data
                }
            });

            if (response.success) {
                setValidationResults(response.data);
                setNotice({
                    status: response.data.valid ? 'success' : 'warning',
                    message: response.data.message || __('Validation completed.', 'thinkrank')
                });
                return response.data;
            }
        } catch (error) {
            console.error(`${tabName} validation error:`, error);
            setNotice({
                status: 'error',
                message: __('Validation failed. Please try again.', 'thinkrank')
            });
        } finally {
            setIsValidating(false);
        }
    };

    /**
     * Clear notice
     */
    const clearNotice = () => {
        setNotice(null);
    };

    /**
     * Reset settings to defaults
     */
    const resetSettings = () => {
        setSettings(defaultSettings);
        setHasChanges(true);
    };

    // Load settings on mount if autoLoad is enabled
    useEffect(() => {
        if (autoLoad) {
            loadSettings();
        }
    }, []);

    // Clear notice when component unmounts or becomes inactive
    useEffect(() => {
        return () => {
            // Clear notice on cleanup
            setNotice(null);
        };
    }, []);

    return {
        // State
        isLoading,
        isSaving,
        isOptimizing,
        isValidating,
        settings,
        hasChanges,
        notice,
        optimizationResults,
        validationResults,
        
        // Methods
        loadSettings,
        saveSettings,
        handleSettingChange,
        runOptimization,
        runValidation,
        clearNotice,
        resetSettings,
        setNotice,
        setSettings
    };
};

export default useTabSettings;

```
