import { CheckIcon, PlusIcon } from '@radix-ui/react-icons'; import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch } from 'react-redux'; import { useModule } from '../../lib/react-utils'; import { modules } from '../../store/api/reducer'; import { LoyaltyReward } from '../../store/api/types'; import AlertContent from '../components/AlertContent'; import DialogContent from '../components/DialogContent'; import Interval from '../components/Interval'; import { Button, Checkbox, CheckboxIndicator, Dialog, DialogActions, Field, FieldNote, FlexRow, InputBox, Label, MultiButton, PageContainer, PageHeader, PageTitle, styled, TabButton, TabContainer, TabContent, TabList, Textarea, TextBlock, } from '../theme'; import { Alert, AlertTrigger } from '../theme/alert'; const RewardList = styled('div', { marginTop: '1rem' }); const RewardItemContainer = styled('article', { backgroundColor: '$gray2', margin: '0.5rem 0', padding: '0.5rem', borderLeft: '5px solid $teal8', borderRadius: '0.25rem', borderBottom: '1px solid $gray4', transition: 'all 50ms', '&:hover': { backgroundColor: '$gray3', }, variants: { status: { enabled: {}, disabled: { borderLeftColor: '$red6', backgroundColor: '$gray3', color: '$gray10', }, }, }, }); const RewardHeader = styled('header', { display: 'flex', gap: '0.5rem', alignItems: 'center', marginBottom: '0.4rem', }); const RewardName = styled('span', { color: '$teal12', flex: 1, fontWeight: 'bold', variants: { status: { enabled: {}, disabled: { color: '$gray9', }, }, }, }); const RewardDescription = styled('span', { flex: 1, fontSize: '0.9rem', color: '$gray11', }); const RewardActions = styled('div', { display: 'flex', alignItems: 'center', gap: '0.25rem', }); const RewardID = styled('code', { fontFamily: 'Space Mono', color: '$teal11', }); const RewardCost = styled('div', { fontSize: '0.9rem', marginRight: '0.5rem', }); const RewardIcon = styled('div', { width: '32px', height: '32px', backgroundColor: '$gray4', borderRadius: '0.25rem', display: 'flex', alignItems: 'center', }); interface RewardItemProps { name: string; item: LoyaltyReward; currency: string; onToggle?: () => void; onEdit?: () => void; onDelete?: () => void; } function RewardItem({ name, item, currency, onToggle, onEdit, onDelete, }: RewardItemProps): React.ReactElement { const { t } = useTranslation(); return ( {item.image && ( )} {item.name} ({name}) {item.price} {currency} (onDelete ? onDelete() : null)} /> {item.description} ); } function RewardsPage() { const { t } = useTranslation(); const dispatch = useDispatch(); const [config] = useModule(modules.loyaltyConfig); const [rewards, setRewards] = useModule(modules.loyaltyRewards); const [filter, setFilter] = useState(''); const [dialogReward, setDialogReward] = useState<{ open: boolean; new: boolean; reward: LoyaltyReward; }>({ open: false, new: false, reward: null }); const [requiredInfo, setRequiredInfo] = useState({ enabled: false, text: '', }); const deleteReward = (id: string): void => { dispatch( setRewards({ ...rewards.filter((r) => r.id !== id), }), ); }; const toggleReward = (id: string): void => { dispatch( setRewards({ ...rewards.map((r) => { if (r.id === id) { return { ...r, enabled: !r.enabled, }; } return r; }), }), ); }; return ( <> setDialogReward({ ...dialogReward, open: state }) } >
{ e.preventDefault(); if (!(e.target as HTMLFormElement).checkValidity()) { return; } const reward = dialogReward.reward; if (requiredInfo.enabled) { reward.required_info = requiredInfo.text; } const index = rewards.findIndex((t) => t.id == reward.id); if (index >= 0) { const newRewards = rewards.slice(0); newRewards[index] = reward; dispatch(setRewards(newRewards)); } else { dispatch(setRewards([...rewards, reward])); } setDialogReward({ ...dialogReward, open: false }); }} > { setDialogReward({ ...dialogReward, reward: { ...dialogReward?.reward, id: e.target.value ?.toLowerCase() .replace(/[^a-zA-Z0-9]/gi, '-') ?? '', }, }); if ( dialogReward.new && rewards.find((r) => r.id === e.target.value) ) { (e.target as HTMLInputElement).setCustomValidity( t('pages.loyalty-rewards.id-already-in-use'), ); } else { (e.target as HTMLInputElement).setCustomValidity(''); } }} /> {t('pages.loyalty-rewards.reward-id-hint')} { setDialogReward({ ...dialogReward, reward: { ...dialogReward?.reward, name: e.target.value, }, }); }} /> {t('pages.loyalty-rewards.reward-name-hint')} { setDialogReward({ ...dialogReward, reward: { ...dialogReward?.reward, image: e.target.value, }, }); }} /> { setDialogReward({ ...dialogReward, reward: { ...dialogReward?.reward, price: parseInt(e.target.value), }, }); }} /> { setDialogReward({ ...dialogReward, reward: { ...dialogReward?.reward, cooldown, }, }); }} /> { setRequiredInfo({ ...requiredInfo, enabled: !!e, }); }} > {requiredInfo.enabled && } { setRequiredInfo({ ...requiredInfo, text: e.target.value }); }} />
setFilter(e.target.value)} /> {rewards?.map((r) => ( setDialogReward({ open: true, new: false, reward: r, }) } onDelete={() => deleteReward(r.id)} onToggle={() => toggleReward(r.id)} /> ))} ); } function GoalsPage() { const { t } = useTranslation(); return <>; } export default function LoyaltyRewardsPage(): React.ReactElement { const { t } = useTranslation(); return ( {t('pages.loyalty-rewards.title')} {t('pages.loyalty-rewards.subtitle')} {t('pages.loyalty-rewards.rewards-tab')} {t('pages.loyalty-rewards.goals-tab')} ); }