54 lines
2.1 KiB
TypeScript
54 lines
2.1 KiB
TypeScript
/**
|
|
* AlertChannelBadge (#41) — 알림 채널 표시 뱃지
|
|
* 알림 규칙·서비스 상태 화면에서 채널(인앱/이메일/SMS/푸시/묵음)을 시각적으로 표시.
|
|
* react-native-svg 미사용 (View + StyleSheet only, 폐쇄망 호환).
|
|
*/
|
|
import { View, Text, StyleSheet } from 'react-native'
|
|
|
|
export type AlertChannel = 'inapp' | 'email' | 'sms' | 'push' | 'mute'
|
|
|
|
interface ChannelMeta { label: string; short: string; color: string; bg: string }
|
|
|
|
const CHANNELS: Record<string, ChannelMeta> = {
|
|
inapp: { label: '인앱', short: 'IN', color: '#00A0C8', bg: 'rgba(0,160,200,.12)' },
|
|
push: { label: '푸시', short: 'PU', color: '#4f6ef7', bg: 'rgba(79,110,247,.12)' },
|
|
email: { label: '이메일', short: '@', color: '#8b5cf6', bg: 'rgba(139,92,246,.12)' },
|
|
sms: { label: 'SMS', short: 'SMS', color: '#f59e0b', bg: 'rgba(245,158,11,.12)' },
|
|
mute: { label: '묵음', short: '🔕', color: '#94a3b8', bg: 'rgba(148,163,184,.15)' },
|
|
}
|
|
|
|
interface Props {
|
|
channel: string
|
|
size?: 'sm' | 'md'
|
|
}
|
|
|
|
export default function AlertChannelBadge({ channel, size = 'md' }: Props) {
|
|
const meta = CHANNELS[channel?.toLowerCase()] ?? CHANNELS.inapp
|
|
const sm = size === 'sm'
|
|
return (
|
|
<View style={[
|
|
s.badge,
|
|
{ backgroundColor: meta.bg, paddingVertical: sm ? 2 : 4, paddingHorizontal: sm ? 6 : 9 },
|
|
]}>
|
|
<View style={[s.dot, { backgroundColor: meta.color, width: sm ? 5 : 6, height: sm ? 5 : 6 }]} />
|
|
<Text style={[s.txt, { color: meta.color, fontSize: sm ? 10 : 11 }]}>{meta.label}</Text>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
/** 여러 채널을 한 줄로 표시 */
|
|
export function AlertChannelRow({ channels }: { channels: string[] }) {
|
|
return (
|
|
<View style={s.row}>
|
|
{channels.map((c, i) => <AlertChannelBadge key={`${c}-${i}`} channel={c} size="sm" />)}
|
|
</View>
|
|
)
|
|
}
|
|
|
|
const s = StyleSheet.create({
|
|
badge: { flexDirection: 'row', alignItems: 'center', gap: 5, borderRadius: 12, alignSelf: 'flex-start' },
|
|
dot: { borderRadius: 4 },
|
|
txt: { fontWeight: '700' },
|
|
row: { flexDirection: 'row', gap: 5, flexWrap: 'wrap' },
|
|
})
|