Initial commit: accountbook project
- Node.js backend server - Frontend application - Backup script - Project specification Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { createContext, useCallback, useContext, useMemo, useState } from 'react';
|
||||
import { Icon } from './icons';
|
||||
|
||||
const ConfirmContext = createContext(null);
|
||||
|
||||
export function ConfirmProvider({ children }) {
|
||||
const [dialog, setDialog] = useState(null);
|
||||
|
||||
const confirm = useCallback((options) => {
|
||||
return new Promise((resolve) => {
|
||||
setDialog({
|
||||
title: options.title || '请确认操作',
|
||||
description: options.description || '',
|
||||
confirmText: options.confirmText || '确认',
|
||||
cancelText: options.cancelText || '取消',
|
||||
tone: options.tone || 'danger',
|
||||
resolve,
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
const close = useCallback((result) => {
|
||||
setDialog((current) => {
|
||||
current?.resolve(result);
|
||||
return null;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const value = useMemo(() => ({ confirm }), [confirm]);
|
||||
|
||||
return (
|
||||
<ConfirmContext.Provider value={value}>
|
||||
{children}
|
||||
{dialog ? (
|
||||
<div className="modal-overlay modal-overlay--center" onClick={() => close(false)}>
|
||||
<div className="confirm-card" onClick={(event) => event.stopPropagation()} role="dialog" aria-modal="true" aria-labelledby="confirm-title">
|
||||
<div className={`confirm-card__icon confirm-card__icon--${dialog.tone}`}>
|
||||
<Icon name={dialog.tone === 'danger' ? 'trash' : 'info'} size={18} />
|
||||
</div>
|
||||
<div className="confirm-card__body">
|
||||
<h2 id="confirm-title">{dialog.title}</h2>
|
||||
{dialog.description ? <p>{dialog.description}</p> : null}
|
||||
</div>
|
||||
<div className="confirm-card__actions">
|
||||
<button type="button" className="btn btn-secondary" onClick={() => close(false)}>{dialog.cancelText}</button>
|
||||
<button type="button" className={`btn ${dialog.tone === 'danger' ? 'btn-danger' : 'btn-primary'}`} onClick={() => close(true)}>{dialog.confirmText}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</ConfirmContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useConfirm() {
|
||||
const context = useContext(ConfirmContext);
|
||||
if (!context) {
|
||||
throw new Error('useConfirm must be used within ConfirmProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user