import { CheckIcon, PlusIcon } from '@radix-ui/react-icons';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useModule } from '../../lib/react-utils';
import { useAppDispatch } from '../../store';
import { modules } from '../../store/api/reducer';
import { LoyaltyGoal, LoyaltyReward } from '../../store/api/types';
import AlertContent from '../components/AlertContent';
import DialogContent from '../components/DialogContent';
import Interval from '../components/Interval';
import {
Button,
Checkbox,
CheckboxIndicator,
ControlledInputBox,
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 GoalList = 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',
});
const NoneText = styled('div', {
color: '$gray9',
fontSize: '1.2em',
textAlign: 'center',
fontStyle: 'italic',
paddingTop: '1rem',
});
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}
);
}
interface GoalItemProps {
name: string;
item: LoyaltyGoal;
currency: string;
onToggle?: () => void;
onEdit?: () => void;
onDelete?: () => void;
}
function GoalItem({
name,
item,
currency,
onToggle,
onEdit,
onDelete,
}: GoalItemProps): React.ReactElement {
const { t } = useTranslation();
return (
{item.image && (
)}
{item.name} ({name})
{item.contributed} / {item.total} {currency} (
{Math.round((item.contributed / item.total) * 100)}%)
(onDelete ? onDelete() : null)}
/>
{item.description}
);
}
function RewardsPage() {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const [cursorPosition, setCursorPosition] = useState(0);
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 filterLC = filter.toLowerCase();
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 (
<>
setFilter(e.target.value)}
/>
{rewards ? (
rewards
?.filter(
(r) =>
r.name.toLowerCase().includes(filterLC) ||
r.id.toLowerCase().includes(filterLC) ||
r.description.toLowerCase().includes(filterLC),
)
.map((r) => (
setDialogReward({
open: true,
new: false,
reward: r,
})
}
onDelete={() => deleteReward(r.id)}
onToggle={() => toggleReward(r.id)}
/>
))
) : (
{t('pages.loyalty-rewards.no-rewards')}
)}
>
);
}
function GoalsPage() {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const [config] = useModule(modules.loyaltyConfig);
const [goals, setGoals] = useModule(modules.loyaltyGoals);
const [filter, setFilter] = useState('');
const [dialogGoal, setDialogGoal] = useState<{
open: boolean;
new: boolean;
goal: LoyaltyGoal;
}>({ open: false, new: false, goal: null });
const [_requiredInfo, setRequiredInfo] = useState({
enabled: false,
text: '',
});
const filterLC = filter.toLowerCase();
const deleteGoal = (id: string): void => {
void dispatch(setGoals(goals?.filter((r) => r.id !== id) ?? []));
};
const toggleGoal = (id: string): void => {
void dispatch(
setGoals(
goals?.map((r) => {
if (r.id === id) {
return {
...r,
enabled: !r.enabled,
};
}
return r;
}) ?? [],
),
);
};
return (
<>
setFilter(e.target.value)}
/>
{goals ? (
goals
?.filter(
(r) =>
r.name.toLowerCase().includes(filterLC) ||
r.id.toLowerCase().includes(filterLC) ||
r.description.toLowerCase().includes(filterLC),
)
.map((r) => (
setDialogGoal({
open: true,
new: false,
goal: r,
})
}
onDelete={() => deleteGoal(r.id)}
onToggle={() => toggleGoal(r.id)}
/>
))
) : (
{t('pages.loyalty-rewards.no-goals')}
)}
>
);
}
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')}
);
}