@citiwave/im-disclaimer-modal
Version:
A customizable React disclaimer modal component with theme support
121 lines (104 loc) • 3.9 kB
text/typescript
import { useState, useEffect } from 'react';
import { useDisclaimerQueue, DISCLAIMER_PRIORITIES } from './useDisclaimerQueue';
import { renderDisclaimerContent } from '../utils/renderDisclaimerContent';
import type { DisclaimerSection } from '../components/DisclaimerModal';
interface DisclaimerGroup {
name: string;
disclaimers: string[];
priorities: { [key: string]: number };
}
interface DisclaimerConfig {
id: string;
title: string;
defaultAccentColor?: string;
}
// Default configs that can be overridden by JSON files
const DISCLAIMER_CONFIGS: DisclaimerConfig[] = [
{
id: 'privacy-policy',
title: 'Privacy Policy',
defaultAccentColor: '#4A90E2'
},
{
id: 'financial-terms',
title: 'Financial Terms and Conditions',
defaultAccentColor: '#2ECC71'
}
];
export const useDisclaimerGroup = (groupName: string, defaultTheme: 'light' | 'dark' = 'dark') => {
const [group, setGroup] = useState<DisclaimerGroup | null>(null);
const [disclaimers, setDisclaimers] = useState<Array<{
id: string;
title: string;
accentColor: string;
theme: 'light' | 'dark';
sections: DisclaimerSection[];
}>>([]);
const { isDisclaimerActive, removeFromQueue, addToQueue } = useDisclaimerQueue();
const [initialized, setInitialized] = useState(false);
// Load group and process disclaimers
useEffect(() => {
const loadGroup = async () => {
try {
// Load group data
const groupData = await import(`../../demo/src/data/disclaimers/groups/${groupName}.json`);
setGroup(groupData.default);
// Load and process all disclaimers
const loadedDisclaimers = await Promise.all(
DISCLAIMER_CONFIGS.map(async (config) => {
const contentModule = await import(`../../demo/src/data/disclaimers/${config.id}.json`);
const content = contentModule.default;
// Get config from JSON file or use defaults
const fileConfig = content.config || {};
const theme = fileConfig.theme || defaultTheme;
const accentColor = fileConfig.accentColor || config.defaultAccentColor;
// Filter out config from sections
const sections = Object.entries(content)
.filter(([key]) => key !== 'config')
.map(([key, section]: [string, any]) => ({
title: section.title,
required: section.required,
content: renderDisclaimerContent(section.content, theme)
}));
return {
id: config.id,
title: config.title,
accentColor,
theme,
sections
};
})
);
// Sort based on group priorities
const sortedDisclaimers = loadedDisclaimers.sort((a, b) => {
const priorityA = groupData.default.priorities[a.id] ?? Infinity;
const priorityB = groupData.default.priorities[b.id] ?? Infinity;
return priorityA - priorityB;
});
setDisclaimers(sortedDisclaimers);
// Initialize queue if not already done
if (!initialized) {
// Reset priorities
Object.keys(DISCLAIMER_PRIORITIES).forEach(key => {
delete DISCLAIMER_PRIORITIES[key];
});
// Add to queue in priority order
Object.entries(groupData.default.priorities).forEach(([id, priority]) => {
Object.assign(DISCLAIMER_PRIORITIES, { [id]: priority });
addToQueue(id);
});
setInitialized(true);
}
} catch (error) {
console.error(`Error loading disclaimer group: ${groupName}`, error);
}
};
loadGroup();
}, [groupName, defaultTheme, initialized, addToQueue]);
return {
group,
disclaimers,
isDisclaimerActive,
removeFromQueue
};
};