Add whatsapp feature

This commit is contained in:
Urtzi Alfaro
2025-11-13 16:01:08 +01:00
parent d7df2b0853
commit 9bc048d360
74 changed files with 9765 additions and 533 deletions

View File

@@ -0,0 +1,377 @@
import React from 'react';
import { Bell, MessageSquare, Mail, AlertCircle, Globe } from 'lucide-react';
import { Card, Input } from '../../../../../components/ui';
import type { NotificationSettings } from '../../../../../api/types/settings';
import { useTranslation } from 'react-i18next';
interface NotificationSettingsCardProps {
settings: NotificationSettings;
onChange: (settings: NotificationSettings) => void;
disabled?: boolean;
}
const NotificationSettingsCard: React.FC<NotificationSettingsCardProps> = ({
settings,
onChange,
disabled = false,
}) => {
const { t } = useTranslation('ajustes');
const handleChange = (field: keyof NotificationSettings) => (
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
) => {
const value = e.target.type === 'checkbox' ? (e.target as HTMLInputElement).checked :
e.target.value;
onChange({ ...settings, [field]: value });
};
const handleChannelChange = (field: 'po_notification_channels' | 'inventory_alert_channels' | 'production_alert_channels' | 'forecast_alert_channels', channel: string) => {
const currentChannels = settings[field];
const newChannels = currentChannels.includes(channel)
? currentChannels.filter(c => c !== channel)
: [...currentChannels, channel];
onChange({ ...settings, [field]: newChannels });
};
return (
<Card className="p-6">
<h3 className="text-lg font-semibold text-[var(--text-primary)] mb-6 flex items-center">
<Bell className="w-5 h-5 mr-2 text-[var(--color-primary)]" />
{t('notification.title')}
</h3>
<div className="space-y-6">
{/* WhatsApp Configuration */}
<div>
<h4 className="text-sm font-semibold text-[var(--text-secondary)] mb-4 flex items-center">
<MessageSquare className="w-4 h-4 mr-2" />
{t('notification.whatsapp_config')}
</h4>
<div className="space-y-4 pl-6">
<div className="flex items-center gap-2">
<input
type="checkbox"
id="whatsapp_enabled"
checked={settings.whatsapp_enabled}
onChange={handleChange('whatsapp_enabled')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
<label htmlFor="whatsapp_enabled" className="text-sm text-[var(--text-secondary)]">
{t('notification.whatsapp_enabled')}
</label>
</div>
{settings.whatsapp_enabled && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<Input
label={t('notification.whatsapp_phone_number_id')}
value={settings.whatsapp_phone_number_id}
onChange={handleChange('whatsapp_phone_number_id')}
disabled={disabled}
placeholder="123456789012345"
helperText={t('notification.whatsapp_phone_number_id_help')}
/>
<Input
type="password"
label={t('notification.whatsapp_access_token')}
value={settings.whatsapp_access_token}
onChange={handleChange('whatsapp_access_token')}
disabled={disabled}
placeholder="EAAxxxxxxxx"
helperText={t('notification.whatsapp_access_token_help')}
/>
<Input
label={t('notification.whatsapp_business_account_id')}
value={settings.whatsapp_business_account_id}
onChange={handleChange('whatsapp_business_account_id')}
disabled={disabled}
placeholder="987654321098765"
helperText={t('notification.whatsapp_business_account_id_help')}
/>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('notification.whatsapp_api_version')}
</label>
<select
value={settings.whatsapp_api_version}
onChange={handleChange('whatsapp_api_version')}
disabled={disabled}
className="w-full px-3 py-2 border border-[var(--border-primary)] rounded-lg text-sm bg-[var(--bg-primary)] text-[var(--text-primary)] disabled:bg-[var(--bg-secondary)] disabled:text-[var(--text-secondary)]"
>
<option value="v18.0">v18.0</option>
<option value="v19.0">v19.0</option>
<option value="v20.0">v20.0</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-[var(--text-secondary)] mb-2">
{t('notification.whatsapp_default_language')}
</label>
<select
value={settings.whatsapp_default_language}
onChange={handleChange('whatsapp_default_language')}
disabled={disabled}
className="w-full px-3 py-2 border border-[var(--border-primary)] rounded-lg text-sm bg-[var(--bg-primary)] text-[var(--text-primary)] disabled:bg-[var(--bg-secondary)] disabled:text-[var(--text-secondary)]"
>
<option value="es">Español</option>
<option value="eu">Euskara</option>
<option value="en">English</option>
</select>
</div>
</div>
)}
{settings.whatsapp_enabled && (
<div className="mt-4 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800">
<div className="flex items-start gap-2">
<AlertCircle className="w-4 h-4 text-blue-600 dark:text-blue-400 mt-0.5 flex-shrink-0" />
<div className="text-xs text-blue-700 dark:text-blue-300">
<p className="font-semibold mb-1">{t('notification.whatsapp_setup_note')}</p>
<ul className="list-disc list-inside space-y-1">
<li>{t('notification.whatsapp_setup_step1')}</li>
<li>{t('notification.whatsapp_setup_step2')}</li>
<li>{t('notification.whatsapp_setup_step3')}</li>
</ul>
</div>
</div>
</div>
)}
</div>
</div>
{/* Email Configuration */}
<div>
<h4 className="text-sm font-semibold text-[var(--text-secondary)] mb-4 flex items-center">
<Mail className="w-4 h-4 mr-2" />
{t('notification.email_config')}
</h4>
<div className="space-y-4 pl-6">
<div className="flex items-center gap-2">
<input
type="checkbox"
id="email_enabled"
checked={settings.email_enabled}
onChange={handleChange('email_enabled')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
<label htmlFor="email_enabled" className="text-sm text-[var(--text-secondary)]">
{t('notification.email_enabled')}
</label>
</div>
{settings.email_enabled && (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
<Input
type="email"
label={t('notification.email_from_address')}
value={settings.email_from_address}
onChange={handleChange('email_from_address')}
disabled={disabled}
placeholder="orders@yourbakery.com"
/>
<Input
label={t('notification.email_from_name')}
value={settings.email_from_name}
onChange={handleChange('email_from_name')}
disabled={disabled}
placeholder="Your Bakery Name"
/>
<Input
type="email"
label={t('notification.email_reply_to')}
value={settings.email_reply_to}
onChange={handleChange('email_reply_to')}
disabled={disabled}
placeholder="info@yourbakery.com"
/>
</div>
)}
</div>
</div>
{/* Notification Preferences */}
<div>
<h4 className="text-sm font-semibold text-[var(--text-secondary)] mb-4 flex items-center">
<Globe className="w-4 h-4 mr-2" />
{t('notification.preferences')}
</h4>
<div className="space-y-4 pl-6">
{/* PO Notifications */}
<div className="space-y-2">
<div className="flex items-center gap-2">
<input
type="checkbox"
id="enable_po_notifications"
checked={settings.enable_po_notifications}
onChange={handleChange('enable_po_notifications')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
<label htmlFor="enable_po_notifications" className="text-sm font-medium text-[var(--text-secondary)]">
{t('notification.enable_po_notifications')}
</label>
</div>
{settings.enable_po_notifications && (
<div className="pl-6 flex gap-4">
<label className="flex items-center gap-2 text-sm text-[var(--text-tertiary)]">
<input
type="checkbox"
checked={settings.po_notification_channels.includes('email')}
onChange={() => handleChannelChange('po_notification_channels', 'email')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
Email
</label>
<label className="flex items-center gap-2 text-sm text-[var(--text-tertiary)]">
<input
type="checkbox"
checked={settings.po_notification_channels.includes('whatsapp')}
onChange={() => handleChannelChange('po_notification_channels', 'whatsapp')}
disabled={disabled || !settings.whatsapp_enabled}
className="rounded border-[var(--border-primary)]"
/>
WhatsApp
</label>
</div>
)}
</div>
{/* Inventory Alerts */}
<div className="space-y-2">
<div className="flex items-center gap-2">
<input
type="checkbox"
id="enable_inventory_alerts"
checked={settings.enable_inventory_alerts}
onChange={handleChange('enable_inventory_alerts')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
<label htmlFor="enable_inventory_alerts" className="text-sm font-medium text-[var(--text-secondary)]">
{t('notification.enable_inventory_alerts')}
</label>
</div>
{settings.enable_inventory_alerts && (
<div className="pl-6 flex gap-4">
<label className="flex items-center gap-2 text-sm text-[var(--text-tertiary)]">
<input
type="checkbox"
checked={settings.inventory_alert_channels.includes('email')}
onChange={() => handleChannelChange('inventory_alert_channels', 'email')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
Email
</label>
<label className="flex items-center gap-2 text-sm text-[var(--text-tertiary)]">
<input
type="checkbox"
checked={settings.inventory_alert_channels.includes('whatsapp')}
onChange={() => handleChannelChange('inventory_alert_channels', 'whatsapp')}
disabled={disabled || !settings.whatsapp_enabled}
className="rounded border-[var(--border-primary)]"
/>
WhatsApp
</label>
</div>
)}
</div>
{/* Production Alerts */}
<div className="space-y-2">
<div className="flex items-center gap-2">
<input
type="checkbox"
id="enable_production_alerts"
checked={settings.enable_production_alerts}
onChange={handleChange('enable_production_alerts')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
<label htmlFor="enable_production_alerts" className="text-sm font-medium text-[var(--text-secondary)]">
{t('notification.enable_production_alerts')}
</label>
</div>
{settings.enable_production_alerts && (
<div className="pl-6 flex gap-4">
<label className="flex items-center gap-2 text-sm text-[var(--text-tertiary)]">
<input
type="checkbox"
checked={settings.production_alert_channels.includes('email')}
onChange={() => handleChannelChange('production_alert_channels', 'email')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
Email
</label>
<label className="flex items-center gap-2 text-sm text-[var(--text-tertiary)]">
<input
type="checkbox"
checked={settings.production_alert_channels.includes('whatsapp')}
onChange={() => handleChannelChange('production_alert_channels', 'whatsapp')}
disabled={disabled || !settings.whatsapp_enabled}
className="rounded border-[var(--border-primary)]"
/>
WhatsApp
</label>
</div>
)}
</div>
{/* Forecast Alerts */}
<div className="space-y-2">
<div className="flex items-center gap-2">
<input
type="checkbox"
id="enable_forecast_alerts"
checked={settings.enable_forecast_alerts}
onChange={handleChange('enable_forecast_alerts')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
<label htmlFor="enable_forecast_alerts" className="text-sm font-medium text-[var(--text-secondary)]">
{t('notification.enable_forecast_alerts')}
</label>
</div>
{settings.enable_forecast_alerts && (
<div className="pl-6 flex gap-4">
<label className="flex items-center gap-2 text-sm text-[var(--text-tertiary)]">
<input
type="checkbox"
checked={settings.forecast_alert_channels.includes('email')}
onChange={() => handleChannelChange('forecast_alert_channels', 'email')}
disabled={disabled}
className="rounded border-[var(--border-primary)]"
/>
Email
</label>
<label className="flex items-center gap-2 text-sm text-[var(--text-tertiary)]">
<input
type="checkbox"
checked={settings.forecast_alert_channels.includes('whatsapp')}
onChange={() => handleChannelChange('forecast_alert_channels', 'whatsapp')}
disabled={disabled || !settings.whatsapp_enabled}
className="rounded border-[var(--border-primary)]"
/>
WhatsApp
</label>
</div>
)}
</div>
</div>
</div>
</div>
</Card>
);
};
export default NotificationSettingsCard;