diff --git a/backend/app/views/auth/api.py b/backend/app/views/auth/api.py
index 75da842..56bc1b9 100644
--- a/backend/app/views/auth/api.py
+++ b/backend/app/views/auth/api.py
@@ -78,7 +78,7 @@ async def read_users_me(
@router.get("/anon")
-async def get_qnon_user(
+async def get_anon_user(
anon_user: Annotated[schemas.AnonUser, Depends(services.get_anon_user)]
) -> schemas.AnonUser:
return anon_user
diff --git a/backend/app/views/queue/services.py b/backend/app/views/queue/services.py
index a51fbc8..b1471dc 100644
--- a/backend/app/views/queue/services.py
+++ b/backend/app/views/queue/services.py
@@ -5,7 +5,7 @@ from uuid import UUID
import redis
import asyncio
-from ...dependencies import get_db, get_pubsub
+from ...dependencies import get_db, get_pubsub, get_redis
from ...db import models
from ..auth import services as auth_services
@@ -43,7 +43,6 @@ def get_detailed_queue(
db: Annotated[Session, Depends(get_db)],
) -> schemas.QueueDetail:
q = db.query(models.Queue).filter(models.Queue.id == queue_id).first()
- print("\n\n", queue_id, "\n\n", flush=True)
if q:
return schemas.QueueDetail(
id=q.id,
@@ -63,10 +62,11 @@ def get_detailed_queue(
)
-def join_queue(
+async def join_queue(
queue_id: UUID,
client: Annotated[auth_schemas.AnonUser, Depends(auth_services.get_anon_user)],
db: Annotated[Session, Depends(get_db)],
+ r: Annotated[redis.client.Redis, Depends(get_redis)],
) -> schemas.QueueUser:
q = get_queue_by_id(queue_id, db)
if q:
@@ -78,6 +78,7 @@ def join_queue(
)
db.add(new_qu)
db.commit()
+ await r.publish(str(queue_id), "updated")
return new_qu
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
@@ -96,9 +97,8 @@ async def set_queue_listener(
) -> schemas.QueueDetail:
await ps.subscribe(str(queue_id))
async for m in ps.listen():
- print(m, flush=True)
if m.get("data", None) == b"updated":
- print("UPDATED", flush=True)
break
+ await ps.unsubscribe()
new_queue = get_detailed_queue(queue_id=queue_id, db=db)
return new_queue
diff --git a/frontend/app/src/components/queue/ApproveQueueJoinCard.tsx b/frontend/app/src/components/queue/ApproveQueueJoinCard.tsx
index fbb136a..95ed689 100644
--- a/frontend/app/src/components/queue/ApproveQueueJoinCard.tsx
+++ b/frontend/app/src/components/queue/ApproveQueueJoinCard.tsx
@@ -1,9 +1,8 @@
-import React, { useState } from "react";
+import React, { useContext } from "react";
import "../styles.css";
-import { Button, Divider, Input, Spin } from "antd";
+import { Button, Spin } from "antd";
import {
ArrowLeftOutlined,
- CameraOutlined,
FileTextOutlined,
PlusOutlined,
UserOutlined,
@@ -11,13 +10,34 @@ import {
import Title from "antd/es/typography/Title";
import tr from "../../config/translation";
import { useNavigate } from "react-router-dom";
-import { useGetQueueDetailQuery } from "../../slice/QueueApi";
+import {
+ useGetQueueDetailQuery,
+ useJoinQueueMutation,
+} from "../../slice/QueueApi";
+import { MessageContext } from "../../App";
const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
const navigate = useNavigate();
- const { data, isFetching, isError } = useGetQueueDetailQuery(props.id, {
- skip: !props.id,
- });
+ const messageApi = useContext(MessageContext);
+
+ const { data, refetch, isFetching, isError } = useGetQueueDetailQuery(
+ props.id,
+ {
+ skip: !props.id,
+ }
+ );
+ const [joinQueue, { isLoading }] = useJoinQueueMutation();
+
+ const onJoinButtonClick = () => {
+ joinQueue(props.id)
+ .unwrap()
+ .then(() =>
+ messageApi.success(tr("Successfully joined queue ") + data.name)
+ )
+ .then(() => navigate(`/queue/${props.id}`))
+ .then(() => refetch())
+ .catch((e) => messageApi.error(tr(e.data.detail)));
+ };
return (
@@ -48,7 +68,11 @@ const ApproveQueueJoinCard = (props: { id: string }): JSX.Element => {
{" "}
{data?.participants?.remaining} / {data?.participants?.total}
- }>{tr("Join")}
+
+ } onClick={onJoinButtonClick}>
+ {tr("Join")}
+
+
)}
diff --git a/frontend/app/src/components/queue/QueueCard.tsx b/frontend/app/src/components/queue/QueueCard.tsx
index 5526d89..a86459f 100644
--- a/frontend/app/src/components/queue/QueueCard.tsx
+++ b/frontend/app/src/components/queue/QueueCard.tsx
@@ -13,11 +13,15 @@ import tr from "../../config/translation";
import { Link, useParams } from "react-router-dom";
import { useSelector } from "react-redux";
import { StorePrototype } from "../../config/store";
+import AnonUserCard from "../user/AnonUserCard";
const QueueCard = (): JSX.Element => {
const user = useSelector((state: StorePrototype) => state.auth.user);
const { queueId } = useParams();
- const { data, isFetching } = useGetQueueDetailQuery(queueId);
+ const { data, isFetching } = useGetQueueDetailQuery(queueId, {
+ skip: !queueId,
+ });
+
return (
{
{data?.participants?.remaining} / {data?.participants?.total}
+
+
+ {tr("Queue participants")}
+
+ {data?.participants.users_list.map((v) => {
+ return
;
+ })}
+
);
diff --git a/frontend/app/src/components/styles.css b/frontend/app/src/components/styles.css
index c7769db..8e9fe4f 100644
--- a/frontend/app/src/components/styles.css
+++ b/frontend/app/src/components/styles.css
@@ -101,3 +101,25 @@
.queue-info > * {
text-align: left;
}
+
+.anon-circle {
+ width: 50px;
+ height: 50px;
+ line-height: 50px;
+ border-radius: 50%;
+ text-align: center;
+}
+
+.anon-card {
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
+ animation: 0.3s ease-out 0s 1 cardPopup;
+ background: #001d39;
+ margin-top: 0.5rem;
+ margin-right: 1rem;
+ margin-left: 1rem;
+ border-radius: 10px;
+ padding: 1rem;
+ border: 2px solid #00d8a4;
+}
diff --git a/frontend/app/src/components/user/AnonUserCard.tsx b/frontend/app/src/components/user/AnonUserCard.tsx
index 11212b0..25cd5d4 100644
--- a/frontend/app/src/components/user/AnonUserCard.tsx
+++ b/frontend/app/src/components/user/AnonUserCard.tsx
@@ -1,7 +1,45 @@
import React from "react";
+import { AnonUser } from "../../slice/AuthApi";
+import "../styles.css";
+import tr from "../../config/translation";
+import Title from "antd/es/typography/Title";
+import Paragraph from "antd/es/typography/Paragraph";
-const UUIDToColor = (uuid: string): string => {};
-
-const AnonUserCard = (): JSX.Element => {
- return;
+const UUIDToColor = (uuid: string): string => {
+ return (
+ "#" +
+ uuid.split("-").reduce((store: string, v: string) => {
+ return store + v.substring(0, 1);
+ }, "") +
+ uuid.substring(uuid.length - 1)
+ );
};
+
+const getProfileText = (name: string): string => {
+ return name.substring(0, 1);
+};
+
+const AnonUserCard = (props: {
+ user: AnonUser;
+ backlight?: "self" | "active" | undefined;
+}): JSX.Element => {
+ return (
+
+
+ {props.user.name
+ ? getProfileText(props.user.name)
+ : props.user.id.substring(0, 2)}
+
+
+ {props.user.name
+ ? props.user.name
+ : tr("Anonymous") + " #" + props.user.id.substring(0, 4)}
+
+
+ );
+};
+
+export default AnonUserCard;
diff --git a/frontend/app/src/slice/AuthApi.ts b/frontend/app/src/slice/AuthApi.ts
index d583d58..b1d5ff4 100644
--- a/frontend/app/src/slice/AuthApi.ts
+++ b/frontend/app/src/slice/AuthApi.ts
@@ -24,6 +24,11 @@ export type TokenResponse = {
token_type: string;
};
+export type AnonUser = {
+ id: string;
+ name: string;
+};
+
export const AuthApi = createApi({
reducerPath: "AuthApi",
baseQuery: fetchBaseQuery({
diff --git a/frontend/app/src/slice/QueueApi.ts b/frontend/app/src/slice/QueueApi.ts
index 5520764..462a41f 100644
--- a/frontend/app/src/slice/QueueApi.ts
+++ b/frontend/app/src/slice/QueueApi.ts
@@ -1,6 +1,7 @@
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { baseUrl } from "../config/baseUrl";
import { RootState } from "../config/store";
+import { AnonUser } from "./AuthApi";
export type CreateQueueRequest = {
name: string;
@@ -13,6 +14,17 @@ export type Queue = {
description: string | null;
};
+export type QueueDetail = {
+ id: string;
+ name: string;
+ description: string | null;
+ participants: {
+ total: number;
+ remaining: number;
+ users_list: [AnonUser];
+ };
+};
+
export const QueueApi = createApi({
reducerPath: "QueueApi",
baseQuery: fetchBaseQuery({
@@ -30,14 +42,14 @@ export const QueueApi = createApi({
},
}),
endpoints: (builder) => ({
- getQueues: builder.query({
+ getQueues: builder.query<[Queue], undefined>({
query: () => "/",
}),
- getQueueDetail: builder.query({
+ getQueueDetail: builder.query({
query: (queueId: string | undefined) => `/${queueId}`,
}),
joinQueue: builder.mutation({
- query: (queueId: string) => `/${queueId}/join`,
+ query: (queueId: string) => ({ url: `/${queueId}/join`, method: "POST" }),
}),
createQueue: builder.mutation({
query: (data: CreateQueueRequest) => ({
@@ -52,5 +64,6 @@ export const QueueApi = createApi({
export const {
useGetQueuesQuery,
useGetQueueDetailQuery,
+ useJoinQueueMutation,
useCreateQueueMutation,
} = QueueApi;