Files
sso-portal/utils/message.tsx
zhangheng 37f10118d3 chore: initial commit of sso-mock SSO login service
Next.js + Mantine mock SSO service providing account/password, phone
verify-code, and Feishu QR login. Issues a one-time sso_code that the
external app exchanges for user info.

Includes:
- Feishu callback fix: guard against duplicate/concurrent /api/login
  submissions of the same single-use authorization code (feishuLogin
  once-guard + memoized onLoginSuccess to stop effect re-fire).
- ADAPTATION_GUIDE.md: how to switch from the in-memory code store to
  the real backend auth/index + inner_get_user_info endpoints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 18:09:30 +08:00

78 lines
1.7 KiB
TypeScript

import { IconCheck, IconX } from '@tabler/icons-react'
import { notifications } from '@mantine/notifications'
const getNotificationWidth = (text: string) => {
const length = Math.max(1, text?.length || 0)
const width = Math.min(Math.max(length * 14 + 80, 180), 520)
return `${width}px`
}
const getSharedStyles = (text: string) => {
const width = getNotificationWidth(text)
const offset = `calc((100% - ${width}) / 2)`
return {
width,
styles: {
root: {
top: 20,
left: offset,
transform: 'translateX(-75%)',
width,
},
icon: {
width: '16px',
height: '16px',
},
},
}
}
export const showSuccessMsg = (text: string, config?: object) => {
const { width, styles } = getSharedStyles(text)
notifications.show({
message: text,
position: 'top-center',
withCloseButton: false,
color: '#52c41a',
autoClose: 5000,
icon: <IconCheck />,
styles,
...config,
style: {
width,
...(config && 'style' in config && typeof config.style === 'object'
? (config.style as object)
: {}),
},
})
}
export const showErrorMsg = (text: string, config?: object) => {
const { width, styles } = getSharedStyles(text)
notifications.show({
message: text,
position: 'top-center',
withCloseButton: false,
color: '#ff4d4f',
autoClose: 5000,
icon: <IconX size={14} />,
styles: {
...styles,
root: {
...styles.root,
transform: 'translateX(-75%)',
},
},
...config,
style: {
width,
...(config && 'style' in config && typeof config.style === 'object'
? (config.style as object)
: {}),
},
})
}