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

Fix minor UI issues after update

This commit is contained in:
Ash Keel 2021-05-17 09:32:57 +02:00
parent ec7f882beb
commit 5a455951b7
No known key found for this signature in database
GPG key ID: CF2CC050478BD7E5
4 changed files with 66 additions and 19 deletions

View file

@ -1,9 +1,16 @@
import { ActionCreatorWithOptionalPayload, AsyncThunk } from '@reduxjs/toolkit';
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { KilovoltMessage } from '@strimertul/kilovolt-client';
import {
KilovoltMessage,
SubscriptionHandler,
} from '@strimertul/kilovolt-client';
import { RootState } from '../store';
import { APIState } from '../store/api/reducer';
import apiReducer, {
APIState,
getUserPoints,
LoyaltyStorage,
} from '../store/api/reducer';
export function useModule<T>({
key,
@ -37,6 +44,27 @@ export function useModule<T>({
return [data, setter];
}
export function useUserPoints(): LoyaltyStorage {
const prefix = 'loyalty/points/';
const client = useSelector((state: RootState) => state.api.client);
const data = useSelector((state: RootState) => state.api.loyalty.users);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getUserPoints());
const subscriber: SubscriptionHandler = (newValue, key) => {
const user = key.substring(prefix.length);
const entry = JSON.parse(newValue);
dispatch(apiReducer.actions.loyaltyUserPointsChanged({ user, entry }));
};
client.subscribePrefix(prefix, subscriber);
return () => {
client.subscribePrefix(prefix, subscriber);
};
}, []);
return data;
}
export default {
useModule,
useUserPoints,
};

View file

@ -208,7 +208,6 @@ export const getUserPoints = createAsyncThunk(
async (_: void, { getState }) => {
const { api } = getState() as { api: APIState };
const keys = await api.client.getKeysByPrefix(loyaltyPointsPrefix);
console.log(keys);
const userpoints: LoyaltyStorage = {};
Object.entries(keys).forEach(([k, v]) => {
userpoints[k.substr(loyaltyPointsPrefix.length)] = JSON.parse(v);
@ -217,6 +216,25 @@ export const getUserPoints = createAsyncThunk(
},
);
export const setUserPoints = createAsyncThunk(
'api/setUserPoints',
async (
{
user,
points,
relative,
}: { user: string; points: number; relative: boolean },
{ getState },
) => {
const { api } = getState() as { api: APIState };
const entry: LoyaltyPointsEntry = { points };
if (relative) {
entry.points += api.loyalty.users[user].points ?? 0;
}
return api.client.putJSON(loyaltyPointsPrefix + user, entry);
},
);
export const modules = {
moduleConfig: makeModule<ModuleConfig>(
moduleConfigKey,
@ -333,6 +351,14 @@ const apiReducer = createSlice({
loyaltyGoalsChanged(state, { payload }: PayloadAction<LoyaltyGoal[]>) {
state.loyalty.goals = payload;
},
loyaltyUserPointsChanged(
state,
{
payload: { user, entry },
}: PayloadAction<{ user: string; entry: LoyaltyPointsEntry }>,
) {
state.loyalty.users[user] = entry;
},
},
extraReducers: (builder) => {
builder.addCase(createWSClient.fulfilled, (state, { payload }) => {

View file

@ -141,7 +141,7 @@ function GoalModal({
setID(newID.toLowerCase().replace(/[^a-zA-Z0-9]/gi, '-'));
const slug = id || name?.toLowerCase().replace(/[^a-zA-Z0-9]/gi, '-') || '';
const idExists = goals?.some((reward) => reward.id === slug) ?? false;
const idExists = goals?.some((goal) => goal.id === slug) ?? false;
const idInvalid = slug !== initialData?.id && idExists;
const validForm = idInvalid === false && name !== '' && total >= 0;
@ -175,7 +175,7 @@ function GoalModal({
>
<div className="field is-horizontal">
<div className="field-label is-normal">
<label className="label">Reward ID</label>
<label className="label">Goal ID</label>
</div>
<div className="field-body">
<div className="field">
@ -183,20 +183,20 @@ function GoalModal({
<input
className={idInvalid ? 'input is-danger' : 'input'}
type="text"
placeholder="reward_id_here"
placeholder="goal_id_here"
value={slug}
onChange={(ev) => setIDex(ev.target.value)}
/>
</p>
{idInvalid ? (
<p className="help is-danger">
There is already a reward with this ID! Please choose a
different one.
There is already a goal with this ID! Please choose a different
one.
</p>
) : (
<p className="help">
Choose a simple name that can be referenced by other software.
It will be auto-generated from the reward name if you leave it
It will be auto-generated from the goal name if you leave it
blank.
</p>
)}

View file

@ -1,9 +1,7 @@
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import React, { useState } from 'react';
import { RouteComponentProps } from '@reach/router';
import PageList from '../../components/PageList';
import { RootState } from '../../../store';
import { getUserPoints } from '../../../store/api/reducer';
import { useUserPoints } from '../../../lib/react-utils';
interface SortingOrder {
key: 'user' | 'points';
@ -13,17 +11,12 @@ export default function LoyaltyUserListPage(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
props: RouteComponentProps<unknown>,
): React.ReactElement {
const users = useSelector((state: RootState) => state.api.loyalty.users);
const dispatch = useDispatch();
const users = useUserPoints();
const [sorting, setSorting] = useState<SortingOrder>({
key: 'points',
order: 'desc',
});
useEffect(() => {
dispatch(getUserPoints());
}, []);
const [entriesPerPage, setEntriesPerPage] = useState(15);
const [page, setPage] = useState(0);
const [usernameFilter, setUsernameFilter] = useState('');