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

Add test redeem button

This commit is contained in:
Ash Keel 2021-05-02 18:57:55 +02:00
parent c77d7c7a74
commit 61212f249c
No known key found for this signature in database
GPG key ID: CF2CC050478BD7E5
6 changed files with 75 additions and 13 deletions

View file

@ -27,8 +27,8 @@
], ],
"devDependencies": { "devDependencies": {
"@parcel/transformer-sass": "^2.0.0-beta.2", "@parcel/transformer-sass": "^2.0.0-beta.2",
"@typescript-eslint/eslint-plugin": "^4.6.1", "@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.6.1", "@typescript-eslint/parser": "^4.22.0",
"eslint": "^7.12.1", "eslint": "^7.12.1",
"eslint-config-airbnb-base": "^14.2.0", "eslint-config-airbnb-base": "^14.2.0",
"eslint-config-prettier": "^6.15.0", "eslint-config-prettier": "^6.15.0",

View file

@ -1,7 +1,5 @@
export type SubscriptionHandler = (newValue: string) => void; export type SubscriptionHandler = (newValue: string) => void;
export type wsMessage = wsError | wsPush | wsResponse;
interface wsError { interface wsError {
ok: false; ok: false;
error: string; error: string;
@ -21,6 +19,8 @@ interface wsResponse {
data?: string; data?: string;
} }
export type wsMessage = wsError | wsPush | wsResponse;
export default class StrimertulWS { export default class StrimertulWS {
socket: WebSocket; socket: WebSocket;

View file

@ -245,6 +245,39 @@ export const modules = {
), ),
}; };
export const setUserPoints = createAsyncThunk(
'api/setUserPoints',
async (
{
user,
points,
relative,
}: { user: string; points: number; relative: boolean },
{ getState, dispatch },
) => {
const { api } = getState() as { api: APIState };
const newAmount = relative
? (api.loyalty.users[user] ?? 0) + points
: points;
return dispatch(
modules.loyaltyStorage.setter({
...api.loyalty.users,
[user]: newAmount,
}),
);
},
);
export const createRedeem = createAsyncThunk(
'api/createRedeem',
async (redeem: LoyaltyRedeem, { getState, dispatch }) => {
const { api } = getState() as { api: APIState };
return dispatch(
modules.loyaltyRedeemQueue.setter([...api.loyalty.redeemQueue, redeem]),
);
},
);
const apiReducer = createSlice({ const apiReducer = createSlice({
name: 'api', name: 'api',
initialState, initialState,

View file

@ -2,7 +2,11 @@ import React, { useState } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { RouteComponentProps } from '@reach/router'; import { RouteComponentProps } from '@reach/router';
import { useModule } from '../../../lib/react-utils'; import { useModule } from '../../../lib/react-utils';
import { LoyaltyRedeem, modules } from '../../../store/api/reducer'; import {
LoyaltyRedeem,
modules,
setUserPoints,
} from '../../../store/api/reducer';
import PageList from '../../components/PageList'; import PageList from '../../components/PageList';
interface SortingOrder { interface SortingOrder {
@ -15,7 +19,6 @@ export default function LoyaltyRedeemQueuePage(
props: RouteComponentProps<unknown>, props: RouteComponentProps<unknown>,
): React.ReactElement { ): React.ReactElement {
const [redemptions, setRedeemQueue] = useModule(modules.loyaltyRedeemQueue); const [redemptions, setRedeemQueue] = useModule(modules.loyaltyRedeemQueue);
const [points, setPoints] = useModule(modules.loyaltyStorage);
const [sorting, setSorting] = useState<SortingOrder>({ const [sorting, setSorting] = useState<SortingOrder>({
key: 'when', key: 'when',
@ -86,9 +89,10 @@ export default function LoyaltyRedeemQueuePage(
const refundRedeem = (redeem: LoyaltyRedeem) => { const refundRedeem = (redeem: LoyaltyRedeem) => {
// Give points back to the viewer // Give points back to the viewer
dispatch( dispatch(
setPoints({ setUserPoints({
...points, user: redeem.username,
[redeem.username]: (points[redeem.username] ?? 0) + redeem.reward.price, points: redeem.reward.price,
relative: true,
}), }),
); );
// Take the redeem off the list // Take the redeem off the list
@ -157,8 +161,12 @@ export default function LoyaltyRedeemQueuePage(
<td>{redemption.reward.name}</td> <td>{redemption.reward.name}</td>
<td style={{ textAlign: 'right' }}> <td style={{ textAlign: 'right' }}>
<a onClick={() => acceptRedeem(redemption)}>Accept</a> <a onClick={() => acceptRedeem(redemption)}>Accept</a>
{redemption.username !== '@PLATFORM' ? (
<>
{' 🞄 '} {' 🞄 '}
<a onClick={() => refundRedeem(redemption)}>Refund</a> <a onClick={() => refundRedeem(redemption)}>Refund</a>
</>
) : null}
</td> </td>
</tr> </tr>
))} ))}

View file

@ -3,7 +3,11 @@ import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { useModule } from '../../../lib/react-utils'; import { useModule } from '../../../lib/react-utils';
import { RootState } from '../../../store'; import { RootState } from '../../../store';
import { LoyaltyReward, modules } from '../../../store/api/reducer'; import {
createRedeem,
LoyaltyReward,
modules,
} from '../../../store/api/reducer';
import Modal from '../../components/Modal'; import Modal from '../../components/Modal';
interface RewardItemProps { interface RewardItemProps {
@ -11,12 +15,14 @@ interface RewardItemProps {
onToggleState: () => void; onToggleState: () => void;
onEdit: () => void; onEdit: () => void;
onDelete: () => void; onDelete: () => void;
onTest: () => void;
} }
function RewardItem({ function RewardItem({
item, item,
onToggleState, onToggleState,
onEdit, onEdit,
onDelete, onDelete,
onTest,
}: RewardItemProps) { }: RewardItemProps) {
const currency = useSelector( const currency = useSelector(
(state: RootState) => (state: RootState) =>
@ -71,6 +77,9 @@ function RewardItem({
</> </>
) : null} ) : null}
<div style={{ marginTop: '1rem' }}> <div style={{ marginTop: '1rem' }}>
<a className="button is-small" onClick={onTest}>
Test
</a>{' '}
<a className="button is-small" onClick={onToggleState}> <a className="button is-small" onClick={onToggleState}>
{item.enabled ? 'Disable' : 'Enable'} {item.enabled ? 'Disable' : 'Enable'}
</a>{' '} </a>{' '}
@ -358,6 +367,17 @@ export default function LoyaltyRewardsPage(
dispatch(setRewards(rewards.filter((entry) => entry.id !== rewardID))); dispatch(setRewards(rewards.filter((entry) => entry.id !== rewardID)));
}; };
const testRedeem = (reward: LoyaltyReward) => {
dispatch(
createRedeem({
username: '@PLATFORM',
display_name: 'me :3',
when: new Date(),
reward,
}),
);
};
return ( return (
<> <>
<h1 className="title is-4">Loyalty rewards</h1> <h1 className="title is-4">Loyalty rewards</h1>
@ -413,6 +433,7 @@ export default function LoyaltyRewardsPage(
onDelete={() => deleteReward(reward.id)} onDelete={() => deleteReward(reward.id)}
onEdit={() => setShowModifyReward(reward)} onEdit={() => setShowModifyReward(reward)}
onToggleState={() => toggleReward(reward.id)} onToggleState={() => toggleReward(reward.id)}
onTest={() => testRedeem(reward)}
/> />
))} ))}
</div> </div>

View file

@ -218,6 +218,7 @@ func main() {
}) })
if moduleConfig.EnableStaticServer { if moduleConfig.EnableStaticServer {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(httpConfig.Path)))) http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(httpConfig.Path))))
httpLogger(logger.MTNotice, "serving %s", httpConfig.Path)
} }
go func() { go func() {
@ -226,7 +227,6 @@ func main() {
}() }()
// Start HTTP server // Start HTTP server
httpLogger(logger.MTNotice, "serving %s", httpConfig.Path)
fatalError(http.ListenAndServe(httpConfig.Bind, nil), "HTTP server died unexepectedly") fatalError(http.ListenAndServe(httpConfig.Bind, nil), "HTTP server died unexepectedly")
} }