1
0
Fork 0
mirror of https://git.sr.ht/~ashkeel/strimertul synced 2024-09-18 01:50:50 +00:00

More missing translation, invalid styling and some progress on rewards

This commit is contained in:
Ash Keel 2022-01-15 02:07:05 +01:00
parent 2358c1cf25
commit 4d7744b4db
No known key found for this signature in database
GPG key ID: BAD8D93E7314ED3E
7 changed files with 237 additions and 26 deletions

View file

@ -115,8 +115,6 @@
"command-response-placeholder": "Hello {0}!",
"command-acl": "Access level",
"command-acl-help": "This specifies the minimum level, eg. if you choose VIPs, moderators and streamer can still use the command",
"command-action-new": "Create",
"command-action-edit": "Edit",
"acl": {
"everyone": "Everyone",
"subscribers": "Subscribers",
@ -135,8 +133,6 @@
"timer-header-edit": "Edit timer",
"timer-name": "Timer name",
"timer-name-placeholder": "my-timer",
"timer-action-new": "Create",
"timer-action-edit": "Edit",
"remove-timer-title": "Remove timer {{name}}?",
"timer-parameters": "every {{time}}, ≥ {{messages}} messages in the last {{interval}}",
"timer-interval": "Minimul interval",
@ -160,7 +156,14 @@
"subscription-enable": "Enable subscription message",
"gift_sub-enable": "Enable gifted subscription message",
"raid-enable": "Enable raid message",
"cheer-enable": "Enable cheering message"
"cheer-enable": "Enable cheering message",
"events": {
"follow": "New follow",
"subscription": "Subscription",
"gift-sub": "Gift sub",
"raid": "Raid",
"cheer": "Cheer"
}
},
"loyalty-settings": {
"title": "Loyalty system configuration",
@ -189,7 +192,9 @@
"date": "Date",
"request": "Request",
"no-redeems": "No pending redeems",
"no-users": "No viewers found"
"no-users": "No viewers found",
"refund": "Refund",
"accept": "Accept"
},
"debug": {
"dismiss-warning": "I am not afraid! ...well ok maybe a little",
@ -197,7 +202,15 @@
"disclaimer-header": "Big scary disclaimer"
},
"loyalty-rewards": {
"title": "Rewards and goals"
"title": "Rewards and goals",
"rewards-tab": "Rewards",
"goals-tab": "Goals",
"subtitle": "Set up rewards and community goals for your viewers to play with",
"reward-filter": "Search by reward name",
"create-reward": "Create reward",
"reward-id": "Reward ID",
"id-already-in-use": "ID already in use by another reward",
"reward-name": "Reward name"
},
"strimertul": {
"need-help": "Need help?",
@ -218,7 +231,8 @@
"cancel": "Cancel",
"ok": "OK",
"add": "Add",
"warning-delete": "This cannot be undone"
"warning-delete": "This cannot be undone",
"create": "Create"
},
"debug": {
"dev-build": "Development build"

View file

@ -263,7 +263,7 @@ function CommandDialog({
</Field>
<DialogActions>
<Button variation="primary">
{t(`pages.botcommands.command-action-${kind}`)}
{kind === 'new' ? t('form-actions.create') : t('form-actions.edit')}
</Button>
<DialogClose asChild>
<Button type="button">{t('form-actions.cancel')}</Button>

View file

@ -277,7 +277,7 @@ function TimerDialog({
<DialogActions>
<Button variation="primary">
{t(`pages.bottimers.timer-action-${kind}`)}
{kind === 'new' ? t('form-actions.create') : t('form-actions.edit')}
</Button>
<DialogClose asChild>
<Button type="button">{t('form-actions.cancel')}</Button>

View file

@ -42,11 +42,19 @@ export default function ChatAlertsPage(): React.ReactElement {
</PageHeader>
<TabContainer defaultValue="follow">
<TabList>
<TabButton value="follow">New follow</TabButton>
<TabButton value="sub">Subscription</TabButton>
<TabButton value="gift">Gift sub</TabButton>
<TabButton value="raid">Raid</TabButton>
<TabButton value="cheer">Cheer</TabButton>
<TabButton value="follow">
{t('pages.alerts.events.follow')}
</TabButton>
<TabButton value="sub">
{t('pages.alerts.events.subscription')}
</TabButton>
<TabButton value="gift">
{t('pages.alerts.events.gift-sub')}
</TabButton>
<TabButton value="raid">{t('pages.alerts.events.raid')}</TabButton>
<TabButton value="cheer">
{t('pages.alerts.events.cheer')}
</TabButton>
</TabList>
<TabContent value="follow">
<Field size="fullWidth">

View file

@ -4,7 +4,6 @@ import { useDispatch } from 'react-redux';
import { useModule, useUserPoints } from '../../lib/react-utils';
import { SortFunction } from '../../lib/type-utils';
import { modules, removeRedeem, setUserPoints } from '../../store/api/reducer';
import { LoyaltyRedeem } from '../../store/api/types';
import { DataTable } from '../components/DataTable';
import DialogContent from '../components/DialogContent';
import {
@ -112,7 +111,7 @@ function RewardQueue() {
dispatch(removeRedeem(entry));
}}
>
Accept
{t('pages.loyalty-queue.accept')}
</Button>
<Button
size="small"
@ -129,7 +128,7 @@ function RewardQueue() {
dispatch(removeRedeem(entry));
}}
>
Refund
{t('pages.loyalty-queue.refund')}
</Button>
</FlexRow>
</TableCell>
@ -196,7 +195,7 @@ function UserList() {
}
}}
>
<Field size="fullWidth">
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="d-username">
{t('pages.loyalty-queue.username')}
</Label>
@ -212,7 +211,7 @@ function UserList() {
}
/>
</Field>
<Field size="fullWidth">
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="d-points" css={{ textTransform: 'capitalize' }}>
{config?.currency || t('pages.loyalty-queue.points')}
</Label>
@ -259,7 +258,7 @@ function UserList() {
}
}}
>
<Field size="fullWidth">
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="d-username">
{t('pages.loyalty-queue.username')}
</Label>
@ -269,7 +268,7 @@ function UserList() {
value={currentEntry?.username ?? ''}
/>
</Field>
<Field size="fullWidth">
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="d-points" css={{ textTransform: 'capitalize' }}>
{config?.currency || t('pages.loyalty-queue.points')}
</Label>
@ -303,7 +302,7 @@ function UserList() {
setGivePointDialog({ open: true, user: '', points: 0 })
}
>
Give points
{t('pages.loyalty-queue.give-points-dialog')}
</Button>
<InputBox
css={{ flex: 1 }}
@ -352,7 +351,7 @@ function UserList() {
<TableCell>{entry.points}</TableCell>
<TableCell>
<Button onClick={() => setCurrentEntry(entry)} size="small">
Edit
{t('form-actions.edit')}
</Button>
</TableCell>
</TableRow>

View file

@ -1,6 +1,173 @@
import React from 'react';
import { PlusIcon } from '@radix-ui/react-icons';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PageContainer, PageHeader, PageTitle } from '../theme';
import { useDispatch } from 'react-redux';
import { useModule } from '../../lib/react-utils';
import { modules } from '../../store/api/reducer';
import { LoyaltyReward } from '../../store/api/types';
import DialogContent from '../components/DialogContent';
import {
Button,
Dialog,
DialogActions,
Field,
FlexRow,
InputBox,
Label,
PageContainer,
PageHeader,
PageTitle,
TabButton,
TabContainer,
TabContent,
TabList,
TextBlock,
} from '../theme';
function RewardsPage() {
const { t } = useTranslation();
const dispatch = useDispatch();
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 });
return (
<>
<Dialog
open={dialogReward.open}
onOpenChange={(state) =>
setDialogReward({ ...dialogReward, open: state })
}
>
<DialogContent title={t('pages.loyalty-rewards.create-reward')}>
<form
onSubmit={(e) => {
e.preventDefault();
if (!(e.target as HTMLFormElement).checkValidity()) {
return;
}
const reward = dialogReward.reward;
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 });
}}
>
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="reward-id">
{t('pages.loyalty-rewards.reward-id')}
</Label>
<InputBox
id="reward-id"
type="text"
required
disabled={!dialogReward.new}
value={dialogReward?.reward?.id}
onChange={(e) => {
setDialogReward({
...dialogReward,
reward: {
...dialogReward?.reward,
id: e.target.value,
},
});
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('');
}
}}
/>
</Field>
<Field size="fullWidth" spacing="narrow">
<Label htmlFor="reward-name">
{t('pages.loyalty-rewards.reward-name')}
</Label>
<InputBox
id="reward-name"
type="text"
required
value={dialogReward?.reward?.name}
onChange={(e) => {
setDialogReward({
...dialogReward,
reward: {
...dialogReward?.reward,
name: e.target.value,
},
});
}}
/>
</Field>
<DialogActions>
<Button variation="primary" type="submit">
{t('form-actions.create')}
</Button>
<Button
type="button"
onClick={() =>
setDialogReward({ ...dialogReward, open: false })
}
>
{t('form-actions.cancel')}
</Button>
</DialogActions>
</form>
</DialogContent>
</Dialog>
<Field size="fullWidth" spacing="none">
<FlexRow css={{ flex: 1, alignItems: 'stretch' }} spacing="1">
<Button
variation="primary"
onClick={() =>
setDialogReward({
open: true,
new: true,
reward: {
id: '',
enabled: true,
name: '',
description: '',
image: '',
price: 0,
cooldown: 0,
},
})
}
>
<PlusIcon /> {t('pages.loyalty-rewards.create-reward')}
</Button>
<InputBox
css={{ flex: 1 }}
placeholder={t('pages.loyalty-rewards.reward-filter')}
value={filter}
onChange={(e) => setFilter(e.target.value)}
/>
</FlexRow>
</Field>
</>
);
}
function GoalsPage() {
const { t } = useTranslation();
return <></>;
}
export default function LoyaltyRewardsPage(): React.ReactElement {
const { t } = useTranslation();
@ -9,7 +176,24 @@ export default function LoyaltyRewardsPage(): React.ReactElement {
<PageContainer>
<PageHeader>
<PageTitle>{t('pages.loyalty-rewards.title')}</PageTitle>
<TextBlock>{t('pages.loyalty-rewards.subtitle')}</TextBlock>
</PageHeader>
<TabContainer defaultValue="rewards">
<TabList>
<TabButton value="rewards">
{t('pages.loyalty-rewards.rewards-tab')}
</TabButton>
<TabButton value="goals">
{t('pages.loyalty-rewards.goals-tab')}
</TabButton>
</TabList>
<TabContent value="rewards">
<RewardsPage />
</TabContent>
<TabContent value="goals">
<GoalsPage />
</TabContent>
</TabContainer>
</PageContainer>
);
}

View file

@ -63,6 +63,9 @@ export const InputBox = styled('input', {
borderColor: '$gray5',
color: '$gray8',
},
'&:invalid': {
borderColor: '$red5',
},
variants: {
border: {
none: {
@ -91,6 +94,9 @@ export const Textarea = styled('textarea', {
borderColor: '$gray5',
color: '$gray8',
},
'&:invalid': {
borderColor: '$red5',
},
variants: {
border: {
none: {