upd
This commit is contained in:
@ -86,6 +86,13 @@ async def get_anon_user(
|
|||||||
return anon_user
|
return anon_user
|
||||||
|
|
||||||
|
|
||||||
|
@router.patch("/anon")
|
||||||
|
async def get_anon_user(
|
||||||
|
anon_user: Annotated[schemas.AnonUser, Depends(services.patch_anon_name)]
|
||||||
|
) -> schemas.AnonUser:
|
||||||
|
return anon_user
|
||||||
|
|
||||||
|
|
||||||
@router.get(
|
@router.get(
|
||||||
"/captcha/{captcha_id}",
|
"/captcha/{captcha_id}",
|
||||||
responses={200: {"content": {"image/png": {}}}},
|
responses={200: {"content": {"image/png": {}}}},
|
||||||
|
|||||||
@ -48,3 +48,7 @@ class AnonUser(BaseModel):
|
|||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|
||||||
|
|
||||||
|
class AnonUserPatch(BaseModel):
|
||||||
|
name: str
|
||||||
|
|||||||
@ -147,6 +147,27 @@ def get_anon_user(
|
|||||||
return create_anon_user(db)
|
return create_anon_user(db)
|
||||||
|
|
||||||
|
|
||||||
|
def patch_anon_name(
|
||||||
|
data: schemas.AnonUserPatch,
|
||||||
|
db: Annotated[Session, Depends(get_db)],
|
||||||
|
x_client_id: Annotated[Union[str, None], Header()] = None,
|
||||||
|
) -> schemas.AnonUser:
|
||||||
|
if x_client_id:
|
||||||
|
anon = (
|
||||||
|
db.query(models.AnonymousUser)
|
||||||
|
.filter(models.AnonymousUser.id == x_client_id)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
if anon:
|
||||||
|
setattr(anon, "name", data.name)
|
||||||
|
db.commit()
|
||||||
|
return anon
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_418_IM_A_TEAPOT,
|
||||||
|
)
|
||||||
|
return create_anon_user(db)
|
||||||
|
|
||||||
|
|
||||||
def get_captcha(
|
def get_captcha(
|
||||||
captcha_id: uuid.UUID, db: Annotated[Session, Depends(get_db)]
|
captcha_id: uuid.UUID, db: Annotated[Session, Depends(get_db)]
|
||||||
) -> BytesIO:
|
) -> BytesIO:
|
||||||
|
|||||||
18
frontend/app/package-lock.json
generated
18
frontend/app/package-lock.json
generated
@ -1259,12 +1259,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/braces": {
|
"node_modules/braces": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fill-range": "^7.0.1"
|
"fill-range": "^7.1.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
@ -2045,10 +2046,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fill-range": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.0.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"to-regex-range": "^5.0.1"
|
"to-regex-range": "^5.0.1"
|
||||||
},
|
},
|
||||||
@ -2661,6 +2663,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.12.0"
|
"node": ">=0.12.0"
|
||||||
}
|
}
|
||||||
@ -4527,6 +4530,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-number": "^7.0.0"
|
"is-number": "^7.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import React, { useContext } from "react";
|
import React, { useContext, useState } from "react";
|
||||||
import "../styles.css";
|
import "../styles.css";
|
||||||
import { Button, Spin } from "antd";
|
import { Button, Input, Spin } from "antd";
|
||||||
import {
|
import {
|
||||||
ArrowLeftOutlined,
|
ArrowLeftOutlined,
|
||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
@ -15,6 +15,7 @@ import {
|
|||||||
useJoinQueueMutation,
|
useJoinQueueMutation,
|
||||||
} from "../../slice/QueueApi";
|
} from "../../slice/QueueApi";
|
||||||
import { MessageContext } from "../../App";
|
import { MessageContext } from "../../App";
|
||||||
|
import { usePatchAnonMutation } from "../../slice/AuthApi";
|
||||||
|
|
||||||
const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
|
const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -27,6 +28,8 @@ const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
const [joinQueue, { isLoading }] = useJoinQueueMutation();
|
const [joinQueue, { isLoading }] = useJoinQueueMutation();
|
||||||
|
const [patchAnon] = usePatchAnonMutation();
|
||||||
|
const [newName, setNewName] = useState("");
|
||||||
|
|
||||||
const onJoinButtonClick = () => {
|
const onJoinButtonClick = () => {
|
||||||
joinQueue(props.id)
|
joinQueue(props.id)
|
||||||
@ -37,6 +40,13 @@ const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
|
|||||||
.catch((e) => messageApi.error(tr(e.data.detail)));
|
.catch((e) => messageApi.error(tr(e.data.detail)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const patchName = () => {
|
||||||
|
patchAnon({ name: newName })
|
||||||
|
.unwrap()
|
||||||
|
.then(() => messageApi.success(tr("Successfully changed name")))
|
||||||
|
.catch(() => messageApi.error(tr("Error changing name")));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<Spin spinning={isFetching}>
|
<Spin spinning={isFetching}>
|
||||||
@ -67,7 +77,23 @@ const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
|
|||||||
{data?.participants?.remaining} / {data?.participants?.total}
|
{data?.participants?.remaining} / {data?.participants?.total}
|
||||||
</p>
|
</p>
|
||||||
<Spin spinning={isLoading}>
|
<Spin spinning={isLoading}>
|
||||||
<Button icon={<PlusOutlined />} onClick={onJoinButtonClick}>
|
<Title level={4}>{tr("Update your name")}</Title>
|
||||||
|
<div style={{ display: "flex", flexFlow: "row", width: "30vw" }}>
|
||||||
|
<Input
|
||||||
|
value={newName}
|
||||||
|
onChange={(e) => setNewName(e.target.value)}
|
||||||
|
placeholder={tr("Enter new name")}
|
||||||
|
/>
|
||||||
|
<Button style={{ marginLeft: "1rem" }} onClick={patchName}>
|
||||||
|
{tr("Update")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
style={{ width: "100%", marginTop: "2rem" }}
|
||||||
|
type="primary"
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
onClick={onJoinButtonClick}
|
||||||
|
>
|
||||||
{tr("Join")}
|
{tr("Join")}
|
||||||
</Button>
|
</Button>
|
||||||
</Spin>
|
</Spin>
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import React, { useContext } from "react";
|
import React, { useContext, useState } from "react";
|
||||||
import {
|
import {
|
||||||
useGetQueueDetailQuery,
|
useGetQueueDetailQuery,
|
||||||
useKickFirstActionMutation,
|
useKickFirstActionMutation,
|
||||||
useStartQueueActionMutation,
|
useStartQueueActionMutation,
|
||||||
} from "../../slice/QueueApi";
|
} from "../../slice/QueueApi";
|
||||||
import "../styles.css";
|
import "../styles.css";
|
||||||
import { Button, Spin } from "antd";
|
import { Button, QRCode, Spin } from "antd";
|
||||||
import {
|
import {
|
||||||
FieldTimeOutlined,
|
FieldTimeOutlined,
|
||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
@ -15,6 +15,8 @@ import {
|
|||||||
PlusCircleOutlined,
|
PlusCircleOutlined,
|
||||||
QuestionCircleOutlined,
|
QuestionCircleOutlined,
|
||||||
UserOutlined,
|
UserOutlined,
|
||||||
|
ZoomInOutlined,
|
||||||
|
ZoomOutOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import Title from "antd/es/typography/Title";
|
import Title from "antd/es/typography/Title";
|
||||||
import tr from "../../config/translation";
|
import tr from "../../config/translation";
|
||||||
@ -23,6 +25,7 @@ import AnonUserCard from "../user/AnonUserCard";
|
|||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { StorePrototype } from "../../config/store";
|
import { StorePrototype } from "../../config/store";
|
||||||
import { MessageContext } from "../../App";
|
import { MessageContext } from "../../App";
|
||||||
|
import { baseClientUrl } from "../../config/baseUrl";
|
||||||
|
|
||||||
const getStatusText = (status: string) => {
|
const getStatusText = (status: string) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@ -68,13 +71,16 @@ const QueueCard = (): JSX.Element => {
|
|||||||
const messageApi = useContext(MessageContext);
|
const messageApi = useContext(MessageContext);
|
||||||
|
|
||||||
const { queueId } = useParams();
|
const { queueId } = useParams();
|
||||||
const { data, isFetching, refetch } = useGetQueueDetailQuery(queueId, {
|
const { data, isFetching, refetch, error } = useGetQueueDetailQuery(queueId, {
|
||||||
skip: !queueId,
|
skip: !queueId,
|
||||||
});
|
});
|
||||||
const user = useSelector((state: StorePrototype) => state.auth.user);
|
const user = useSelector((state: StorePrototype) => state.auth.user);
|
||||||
const [kickFirstAction] = useKickFirstActionMutation();
|
const [kickFirstAction] = useKickFirstActionMutation();
|
||||||
const [startQueueAction] = useStartQueueActionMutation();
|
const [startQueueAction] = useStartQueueActionMutation();
|
||||||
|
|
||||||
|
const [qrShown, setQrShown] = useState(false);
|
||||||
|
const [largeQr, setLargeQr] = useState(false);
|
||||||
|
|
||||||
const kickFirst = () => {
|
const kickFirst = () => {
|
||||||
if (queueId) {
|
if (queueId) {
|
||||||
kickFirstAction(queueId)
|
kickFirstAction(queueId)
|
||||||
@ -95,6 +101,25 @@ const QueueCard = (): JSX.Element => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getJoinLink = () => {
|
||||||
|
if (data) {
|
||||||
|
return baseClientUrl + `/queue/join/${data.id}`;
|
||||||
|
}
|
||||||
|
return baseClientUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
const copyJoinLink = async () => {
|
||||||
|
if (data) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(getJoinLink());
|
||||||
|
messageApi.success(tr("Copied!"));
|
||||||
|
} catch (error) {
|
||||||
|
messageApi.error(tr("Error occured!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
return (
|
return (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<Spin
|
<Spin
|
||||||
@ -116,15 +141,42 @@ const QueueCard = (): JSX.Element => {
|
|||||||
{data?.participants?.remaining} / {data?.participants?.total}
|
{data?.participants?.remaining} / {data?.participants?.total}
|
||||||
</p>
|
</p>
|
||||||
{data && getStatusText(data.status)}
|
{data && getStatusText(data.status)}
|
||||||
{user && user.id && (
|
{data && user && user.id === data.owner_id && (
|
||||||
<div style={{ display: "flex", flexFlow: "row wrap" }}>
|
<div style={{ display: "flex", flexFlow: "row wrap" }}>
|
||||||
<Button onClick={kickFirst}>{tr("Kick first")}</Button>
|
<Button onClick={kickFirst}>{tr("Kick first")}</Button>
|
||||||
{data?.status === "created" && (
|
{data?.status === "created" && (
|
||||||
<Button onClick={startQueue}>{tr("Start queue")}</Button>
|
<Button onClick={startQueue}>{tr("Start queue")}</Button>
|
||||||
)}
|
)}
|
||||||
|
<Button onClick={copyJoinLink}>{tr("Copy join link")}</Button>
|
||||||
|
{qrShown ? (
|
||||||
|
<Button onClick={() => setQrShown(false)}>
|
||||||
|
{tr("Hide QR-code")}
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button onClick={() => setQrShown(true)}>
|
||||||
|
{tr("Show QR-code")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{data && qrShown && (
|
||||||
|
<div style={{ display: "flex", flexFlow: "row nowrap" }}>
|
||||||
|
<QRCode
|
||||||
|
errorLevel="H"
|
||||||
|
value={getJoinLink()}
|
||||||
|
icon={
|
||||||
|
baseClientUrl + "/static/image/android-chrome-512x512.png"
|
||||||
|
}
|
||||||
|
size={largeQr ? 320 : 160}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
icon={largeQr ? <ZoomOutOutlined /> : <ZoomInOutlined />}
|
||||||
|
onClick={() => setLargeQr((v) => !v)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Title level={3} style={{ textAlign: "left" }}>
|
<Title level={3} style={{ textAlign: "left" }}>
|
||||||
{tr("Queue participants")}
|
{tr("Queue participants")}
|
||||||
@ -136,5 +188,16 @@ const QueueCard = (): JSX.Element => {
|
|||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div style={{ width: "100%", marginTop: "3rem" }}>
|
||||||
|
<QuestionCircleOutlined style={{ fontSize: "5rem" }} />
|
||||||
|
</div>
|
||||||
|
<Title>{tr("Queue not found")}</Title>
|
||||||
|
<Title level={3}>404</Title>
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
export default QueueCard;
|
export default QueueCard;
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import tr from "../../config/translation";
|
|||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { StorePrototype } from "../../config/store";
|
import { StorePrototype } from "../../config/store";
|
||||||
import { Button } from "antd";
|
import { Button } from "antd";
|
||||||
import { Queue, usePassQueueActionMutation } from "../../slice/QueueApi";
|
import { QueueDetail, usePassQueueActionMutation } from "../../slice/QueueApi";
|
||||||
import { MessageContext } from "../../App";
|
import { MessageContext } from "../../App";
|
||||||
|
|
||||||
const UUIDToColor = (uuid: string): string => {
|
const UUIDToColor = (uuid: string): string => {
|
||||||
@ -24,7 +24,7 @@ const getProfileText = (name: string): string => {
|
|||||||
|
|
||||||
const AnonUserCard = (props: {
|
const AnonUserCard = (props: {
|
||||||
queueUser: QueueUser;
|
queueUser: QueueUser;
|
||||||
queue: Queue | undefined;
|
queue: QueueDetail | undefined;
|
||||||
}): JSX.Element => {
|
}): JSX.Element => {
|
||||||
const messageApi = useContext(MessageContext);
|
const messageApi = useContext(MessageContext);
|
||||||
|
|
||||||
@ -72,7 +72,8 @@ const AnonUserCard = (props: {
|
|||||||
)}
|
)}
|
||||||
{props.queueUser &&
|
{props.queueUser &&
|
||||||
clientId === props.queueUser.user.id &&
|
clientId === props.queueUser.user.id &&
|
||||||
props.queueUser.position === 0 && (
|
props.queueUser.position === 0 &&
|
||||||
|
props.queue?.status === "active" && (
|
||||||
<span
|
<span
|
||||||
style={{
|
style={{
|
||||||
marginLeft: "1rem",
|
marginLeft: "1rem",
|
||||||
@ -87,8 +88,11 @@ const AnonUserCard = (props: {
|
|||||||
)}
|
)}
|
||||||
{props.queueUser &&
|
{props.queueUser &&
|
||||||
clientId === props.queueUser.user.id &&
|
clientId === props.queueUser.user.id &&
|
||||||
props.queueUser.position === 0 && (
|
props.queueUser.position === 0 &&
|
||||||
|
props.queue?.status === "active" ? (
|
||||||
<Button onClick={() => passQueue()}>{tr("Pass")}</Button>
|
<Button onClick={() => passQueue()}>{tr("Pass")}</Button>
|
||||||
|
) : (
|
||||||
|
<Button onClick={() => passQueue()}>{tr("Leave")}</Button>
|
||||||
)}
|
)}
|
||||||
<p></p>
|
<p></p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1 +1,2 @@
|
|||||||
export const baseUrl = `${window.location.protocol}//${window.location.host}/api`;
|
export const baseUrl = `${window.location.protocol}//${window.location.host}/api`;
|
||||||
|
export const baseClientUrl = `${window.location.protocol}//${window.location.host}`;
|
||||||
|
|||||||
@ -114,8 +114,9 @@ export const store = configureStore({
|
|||||||
if (theme) {
|
if (theme) {
|
||||||
state.theme = theme;
|
state.theme = theme;
|
||||||
} else {
|
} else {
|
||||||
const darkThemeMq = window.matchMedia("(prefers-color-scheme: dark)");
|
// const darkThemeMq = window.matchMedia("(prefers-color-scheme: dark)"); // TODO
|
||||||
state.theme = darkThemeMq.matches ? "dark" : "light";
|
// state.theme = darkThemeMq.matches ? "dark" : "light";
|
||||||
|
state.theme = "dark";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -15,6 +15,7 @@ export const darkTheme: ThemeConfig = {
|
|||||||
components: {
|
components: {
|
||||||
Input: {
|
Input: {
|
||||||
activeBorderColor: "#001529",
|
activeBorderColor: "#001529",
|
||||||
|
colorTextPlaceholder: "grey",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -164,7 +164,46 @@
|
|||||||
"It is your turn!": {
|
"It is your turn!": {
|
||||||
"ru": "Сейчас ваша очередь!"
|
"ru": "Сейчас ваша очередь!"
|
||||||
},
|
},
|
||||||
|
"Start queue": {
|
||||||
|
"ru": "Начать очередь"
|
||||||
|
},
|
||||||
|
"Copy join link": {
|
||||||
|
"ru": "Скопировать ссылку для вступления"
|
||||||
|
},
|
||||||
|
"Show QR-code": {
|
||||||
|
"ru": "Показать QR-код"
|
||||||
|
},
|
||||||
|
"Hide QR-code": {
|
||||||
|
"ru": "Спрятать QR-код"
|
||||||
|
},
|
||||||
|
"Copied!": {
|
||||||
|
"ru": "Скопировано!"
|
||||||
|
},
|
||||||
"Pass": {
|
"Pass": {
|
||||||
"ru": "Пройти"
|
"ru": "Пройти очередь"
|
||||||
|
},
|
||||||
|
"Leave": {
|
||||||
|
"ru": "Покинуть очередь"
|
||||||
|
},
|
||||||
|
"Queue not found": {
|
||||||
|
"ru": "Очередь не найдена"
|
||||||
|
},
|
||||||
|
"Update your name": {
|
||||||
|
"ru": "Обновите свое имя"
|
||||||
|
},
|
||||||
|
"Enter new name": {
|
||||||
|
"ru": "Введите новое имя"
|
||||||
|
},
|
||||||
|
"Update": {
|
||||||
|
"ru": "Обновить"
|
||||||
|
},
|
||||||
|
"Successfully joined queue": {
|
||||||
|
"ru": "Успешное присоединение к очереди"
|
||||||
|
},
|
||||||
|
"Successfully changed name": {
|
||||||
|
"ru": "Успешное изменение имени"
|
||||||
|
},
|
||||||
|
"Already joined": {
|
||||||
|
"ru": "Вы уже присоединились к этой очереди"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,10 @@ export type AnonUser = {
|
|||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type AnonUserPatch = {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
export const AuthApi = createApi({
|
export const AuthApi = createApi({
|
||||||
reducerPath: "AuthApi",
|
reducerPath: "AuthApi",
|
||||||
baseQuery: fetchBaseQuery({
|
baseQuery: fetchBaseQuery({
|
||||||
@ -76,6 +80,13 @@ export const AuthApi = createApi({
|
|||||||
body: data,
|
body: data,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
patchAnon: builder.mutation({
|
||||||
|
query: (data: AnonUserPatch) => ({
|
||||||
|
url: "/anon",
|
||||||
|
method: "PATCH",
|
||||||
|
body: data,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -84,4 +95,5 @@ export const {
|
|||||||
useGetClientQuery,
|
useGetClientQuery,
|
||||||
useLoginMutation,
|
useLoginMutation,
|
||||||
useRegisterMutation,
|
useRegisterMutation,
|
||||||
|
usePatchAnonMutation,
|
||||||
} = AuthApi;
|
} = AuthApi;
|
||||||
|
|||||||
@ -19,6 +19,7 @@ export type QueueDetail = {
|
|||||||
name: string;
|
name: string;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
status: string;
|
status: string;
|
||||||
|
owner_id: string;
|
||||||
participants: {
|
participants: {
|
||||||
total: number;
|
total: number;
|
||||||
remaining: number;
|
remaining: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user