UNPKG

@oxyhq/services

Version:

OxyHQ Expo/React Native SDK — UI components, screens, and native features

126 lines (120 loc) 3.4 kB
"use strict"; import { useState, useCallback, useEffect } from 'react'; import { toast } from '../../lib/sonner'; /** * Hook for handling boolean toggle settings with optimistic updates. * Automatically reverts to the previous value if the save fails. * * @example * const { value, toggle, isSaving } = useSettingToggle({ * initialValue: user.notificationsEnabled, * onSave: (value) => api.updateNotifications(value), * errorMessage: 'Failed to update notifications', * }); * * <Switch value={value} onValueChange={toggle} disabled={isSaving} /> */ export function useSettingToggle(options) { const { initialValue, onSave, successMessage, errorMessage = 'Failed to save setting', revertOnError = true, showSuccessToast = false } = options; const [value, setValue] = useState(initialValue); const [isSaving, setIsSaving] = useState(false); // Update value when initialValue changes (e.g., from server) useEffect(() => { setValue(initialValue); }, [initialValue]); const toggle = useCallback(async () => { const previousValue = value; const newValue = !value; // Optimistic update setValue(newValue); setIsSaving(true); try { await onSave(newValue); if (showSuccessToast && successMessage) { toast.success(successMessage); } } catch (err) { // Revert on error if (revertOnError) { setValue(previousValue); } toast.error(errorMessage || err?.message || 'An error occurred'); } finally { setIsSaving(false); } }, [value, onSave, successMessage, errorMessage, revertOnError, showSuccessToast]); return { value, isSaving, toggle, setValue }; } /** * Hook for managing multiple toggle settings at once. * Useful when you have several related boolean settings. */ export function useSettingToggles(options) { const { initialValues, onSave, errorMessage = 'Failed to save setting', revertOnError = true } = options; const [values, setValues] = useState(initialValues); const [savingKeys, setSavingKeys] = useState(new Set()); // Update values when initialValues change useEffect(() => { setValues(initialValues); }, [initialValues]); const toggle = useCallback(async key => { const previousValue = values[key]; const newValue = !previousValue; // Optimistic update setValues(prev => ({ ...prev, [key]: newValue })); setSavingKeys(prev => new Set(prev).add(key)); try { await onSave(key, newValue); } catch (err) { // Revert on error if (revertOnError) { setValues(prev => ({ ...prev, [key]: previousValue })); } const message = typeof errorMessage === 'function' ? errorMessage(key) : errorMessage; toast.error(message || err?.message || 'An error occurred'); } finally { setSavingKeys(prev => { const next = new Set(prev); next.delete(key); return next; }); } }, [values, onSave, errorMessage, revertOnError]); const setValuesExternal = useCallback(newValues => { setValues(prev => ({ ...prev, ...newValues })); }, []); return { values, savingKeys, toggle, setValues: setValuesExternal }; } export default useSettingToggle; //# sourceMappingURL=useSettingToggle.js.map