1
0
Fork 0
mirror of https://git.sr.ht/~ashkeel/strimertul synced 2024-09-20 02:00:49 +00:00

Almost done with this dialog!

This commit is contained in:
Ash Keel 2022-01-15 11:54:09 +01:00
parent bccea52b03
commit 845a03e7f0
No known key found for this signature in database
GPG key ID: BAD8D93E7314ED3E
2 changed files with 163 additions and 9 deletions

View file

@ -210,7 +210,16 @@
"create-reward": "Create reward", "create-reward": "Create reward",
"reward-id": "Reward ID", "reward-id": "Reward ID",
"id-already-in-use": "ID already in use by another reward", "id-already-in-use": "ID already in use by another reward",
"reward-name": "Reward name" "reward-name": "Name",
"reward-icon": "Icon (as remote URL)",
"reward-desc": "Description",
"reward-cost": "Cost",
"reward-id-hint": "This is what viewers will have to write to claim, ie. \"!redeem reward-id-here\".",
"reward-name-hint": "This is what viewers will see they claimed ie. \"USER has claimed REWARDNAME",
"reward-cooldown": "Cooldown",
"reward-details-placeholder": "What extra details to ask the viewer for",
"reward-details": "Require viewer details",
"edit-reward": "Edit reward"
}, },
"strimertul": { "strimertul": {
"need-help": "Need help?", "need-help": "Need help?",

View file

@ -1,4 +1,4 @@
import { PlusIcon } from '@radix-ui/react-icons'; import { CheckIcon, PlusIcon } from '@radix-ui/react-icons';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
@ -6,11 +6,15 @@ import { useModule } from '../../lib/react-utils';
import { modules } from '../../store/api/reducer'; import { modules } from '../../store/api/reducer';
import { LoyaltyReward } from '../../store/api/types'; import { LoyaltyReward } from '../../store/api/types';
import DialogContent from '../components/DialogContent'; import DialogContent from '../components/DialogContent';
import Interval from '../components/Interval';
import { import {
Button, Button,
Checkbox,
CheckboxIndicator,
Dialog, Dialog,
DialogActions, DialogActions,
Field, Field,
FieldNote,
FlexRow, FlexRow,
InputBox, InputBox,
Label, Label,
@ -21,6 +25,7 @@ import {
TabContainer, TabContainer,
TabContent, TabContent,
TabList, TabList,
Textarea,
TextBlock, TextBlock,
} from '../theme'; } from '../theme';
@ -34,6 +39,10 @@ function RewardsPage() {
new: boolean; new: boolean;
reward: LoyaltyReward; reward: LoyaltyReward;
}>({ open: false, new: false, reward: null }); }>({ open: false, new: false, reward: null });
const [requiredInfo, setRequiredInfo] = useState({
enabled: false,
text: '',
});
return ( return (
<> <>
@ -43,7 +52,14 @@ function RewardsPage() {
setDialogReward({ ...dialogReward, open: state }) setDialogReward({ ...dialogReward, open: state })
} }
> >
<DialogContent title={t('pages.loyalty-rewards.create-reward')}> <DialogContent
title={
dialogReward.new
? t('pages.loyalty-rewards.create-reward')
: t('pages.loyalty-rewards.edit-reward')
}
closeButton={true}
>
<form <form
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
@ -51,6 +67,9 @@ function RewardsPage() {
return; return;
} }
const reward = dialogReward.reward; const reward = dialogReward.reward;
if (requiredInfo.enabled) {
reward.required_info = requiredInfo.text;
}
const index = rewards.findIndex((t) => t.id == reward.id); const index = rewards.findIndex((t) => t.id == reward.id);
if (index >= 0) { if (index >= 0) {
const newRewards = rewards.slice(0); const newRewards = rewards.slice(0);
@ -77,7 +96,10 @@ function RewardsPage() {
...dialogReward, ...dialogReward,
reward: { reward: {
...dialogReward?.reward, ...dialogReward?.reward,
id: e.target.value, id:
e.target.value
?.toLowerCase()
.replace(/[^a-zA-Z0-9]/gi, '-') ?? '',
}, },
}); });
if ( if (
@ -92,6 +114,7 @@ function RewardsPage() {
} }
}} }}
/> />
<FieldNote>{t('pages.loyalty-rewards.reward-id-hint')}</FieldNote>
</Field> </Field>
<Field size="fullWidth" spacing="narrow"> <Field size="fullWidth" spacing="narrow">
<Label htmlFor="reward-name"> <Label htmlFor="reward-name">
@ -101,7 +124,7 @@ function RewardsPage() {
id="reward-name" id="reward-name"
type="text" type="text"
required required
value={dialogReward?.reward?.name} value={dialogReward?.reward?.name ?? ''}
onChange={(e) => { onChange={(e) => {
setDialogReward({ setDialogReward({
...dialogReward, ...dialogReward,
@ -112,10 +135,128 @@ function RewardsPage() {
}); });
}} }}
/> />
<FieldNote>
{t('pages.loyalty-rewards.reward-name-hint')}
</FieldNote>
</Field>
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="reward-icon">
{t('pages.loyalty-rewards.reward-icon')}
</Label>
<InputBox
id="reward-icon"
type="text"
value={dialogReward?.reward?.image ?? ''}
onChange={(e) => {
setDialogReward({
...dialogReward,
reward: {
...dialogReward?.reward,
image: e.target.value,
},
});
}}
/>
</Field>
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="reward-desc">
{t('pages.loyalty-rewards.reward-desc')}
</Label>
<Textarea
id="reward-desc"
value={dialogReward?.reward?.description ?? ''}
onChange={(e) => {
setDialogReward({
...dialogReward,
reward: {
...dialogReward?.reward,
description: e.target.value,
},
});
}}
>
{dialogReward?.reward?.description ?? ''}
</Textarea>
</Field>
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="reward-cost">
{t('pages.loyalty-rewards.reward-cost')}
</Label>
<InputBox
id="reward-cost"
type="number"
required
value={dialogReward?.reward?.price ?? '0'}
onChange={(e) => {
setDialogReward({
...dialogReward,
reward: {
...dialogReward?.reward,
price: parseInt(e.target.value),
},
});
}}
/>
</Field>
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="reward-cooldown">
{t('pages.loyalty-rewards.reward-cooldown')}
</Label>
<FlexRow align="left">
<Interval
value={dialogReward?.reward?.cooldown ?? 0}
active={true}
onChange={(cooldown) => {
setDialogReward({
...dialogReward,
reward: {
...dialogReward?.reward,
cooldown,
},
});
}}
/>
</FlexRow>
</Field>
<Field size="fullWidth" spacing="narrow">
<FlexRow align="left" spacing="1">
<Checkbox
id="reward-details"
checked={requiredInfo.enabled}
onCheckedChange={(e) => {
setRequiredInfo({
...requiredInfo,
enabled: !!e,
});
}}
>
<CheckboxIndicator>
{requiredInfo.enabled && <CheckIcon />}
</CheckboxIndicator>
</Checkbox>
<Label htmlFor="reward-details">
{t('pages.loyalty-rewards.reward-details')}
</Label>
</FlexRow>
<InputBox
id="reward-details-text"
type="text"
disabled={!requiredInfo.enabled}
required={requiredInfo.enabled}
value={dialogReward?.reward?.required_info ?? ''}
placeholder={t(
'pages.loyalty-rewards.reward-details-placeholder',
)}
onChange={(e) => {
setRequiredInfo({ ...requiredInfo, text: e.target.value });
}}
/>
</Field> </Field>
<DialogActions> <DialogActions>
<Button variation="primary" type="submit"> <Button variation="primary" type="submit">
{t('form-actions.create')} {dialogReward.new
? t('form-actions.create')
: t('form-actions.edit')}
</Button> </Button>
<Button <Button
type="button" type="button"
@ -133,7 +274,11 @@ function RewardsPage() {
<FlexRow css={{ flex: 1, alignItems: 'stretch' }} spacing="1"> <FlexRow css={{ flex: 1, alignItems: 'stretch' }} spacing="1">
<Button <Button
variation="primary" variation="primary"
onClick={() => onClick={() => {
setRequiredInfo({
enabled: false,
text: '',
});
setDialogReward({ setDialogReward({
open: true, open: true,
new: true, new: true,
@ -146,8 +291,8 @@ function RewardsPage() {
price: 0, price: 0,
cooldown: 0, cooldown: 0,
}, },
}) });
} }}
> >
<PlusIcon /> {t('pages.loyalty-rewards.create-reward')} <PlusIcon /> {t('pages.loyalty-rewards.create-reward')}
</Button> </Button>