feat: add useNotify hook for unified notifications

- Created useNotify hook (src/platform/hooks/useNotify.ts):
  - In Telegram Mini App: uses native showPopup
  - In browser: uses beautiful Toast component
  - Methods: notify(), success(), error(), warning(), info()

- AdminTariffs: improved deletion UX
  - Uses useNotify.warning when tariff has subscriptions
  - Uses useDestructiveConfirm for delete confirmation
  - Shows success toast after deletion
  - Removed custom modal dialog

- AdminEmailTemplates: unified notification style
  - Replaced dialog.alert with useNotify.warning
  - Now shows beautiful Toast on mobile browser

- Added deleteSuccess i18n translations (ru, en, zh, fa)
This commit is contained in:
c0mrade
2026-02-02 02:17:19 +03:00
parent 5b30f24e7e
commit 6f4d1ef085
8 changed files with 125 additions and 49 deletions

View File

@@ -0,0 +1,92 @@
import { useCallback } from 'react';
import { usePlatform } from '@/platform/hooks/usePlatform';
import { useToast } from '@/components/Toast';
type NotifyType = 'success' | 'error' | 'warning' | 'info';
interface NotifyOptions {
type?: NotifyType;
title?: string;
message: string;
duration?: number;
}
/**
* Universal notification hook.
* - In Telegram Mini App: uses native showPopup
* - In browser: uses Toast component
*
* @example
* ```tsx
* const notify = useNotify();
*
* // Warning notification
* notify.warning('Cannot delete: has active subscriptions');
*
* // Success notification
* notify.success('Tariff created successfully');
*
* // With title
* notify({ type: 'error', title: 'Error', message: 'Something went wrong' });
* ```
*/
export function useNotify() {
const { dialog, capabilities } = usePlatform();
const { showToast } = useToast();
const notify = useCallback(
(options: NotifyOptions | string) => {
const opts: NotifyOptions = typeof options === 'string' ? { message: options } : options;
const { type = 'info', title, message, duration } = opts;
// In Telegram - use native popup for important messages
if (capabilities.hasNativeDialogs) {
dialog.popup({
title: title,
message: message,
buttons: [{ id: 'ok', type: 'ok', text: 'OK' }],
});
return;
}
// In browser - use Toast
showToast({
type,
title,
message,
duration: duration ?? (type === 'error' ? 7000 : 5000),
});
},
[capabilities.hasNativeDialogs, dialog, showToast],
);
// Shorthand methods
const success = useCallback(
(message: string, title?: string) => notify({ type: 'success', message, title }),
[notify],
);
const error = useCallback(
(message: string, title?: string) => notify({ type: 'error', message, title }),
[notify],
);
const warning = useCallback(
(message: string, title?: string) => notify({ type: 'warning', message, title }),
[notify],
);
const info = useCallback(
(message: string, title?: string) => notify({ type: 'info', message, title }),
[notify],
);
return {
notify,
success,
error,
warning,
info,
};
}

View File

@@ -31,3 +31,4 @@ export { useBackButton, useConditionalBackButton } from './hooks/useBackButton';
export { useMainButton, useSimpleMainButton } from './hooks/useMainButton';
export { useHaptic, useHapticClick, useHapticFeedback } from './hooks/useHaptic';
export { useNativeDialog, useDestructiveConfirm, PopupButtons } from './hooks/useNativeDialog';
export { useNotify } from './hooks/useNotify';