- Загрузка задания... -
+Загрузка задания...
- {competition.name} + {competition.title}
Событий нет
++ Увы, очередная победа.рф +
+
Добро пожаловать!
diff --git a/services/frontend/src/pages/Review/index.tsx b/services/frontend/src/pages/Review/index.tsx
index e69de29..4d21663 100644
--- a/services/frontend/src/pages/Review/index.tsx
+++ b/services/frontend/src/pages/Review/index.tsx
@@ -0,0 +1,51 @@
+import { Loading } from "@/components/ui/Loading";
+import { getReviewer, getReviewerSubmissions } from "@/shared/api/review";
+import { useQuery } from "@tanstack/react-query";
+import { useNavigate, useParams } from "react-router";
+import { ReviewHeader } from "./modules/review-header";
+import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
+
+const ReviewPage = () => {
+ const { token } = useParams<{ token: string }>();
+ const navigate = useNavigate();
+
+ const reviewerQuery = useQuery({
+ queryKey: ["reviewer", token],
+ queryFn: async () => getReviewer(token || ""),
+ retry: 0,
+ });
+ const submissionsQuery = useQuery({
+ queryKey: ["submissions", token],
+ queryFn: async () => getReviewerSubmissions(token || ""),
+ retry: 0,
+ });
+
+ if (reviewerQuery.isLoading || submissionsQuery.isLoading) {
+ return ;
+ }
+
+ if (!token || !reviewerQuery.data || !submissionsQuery.data) {
+ navigate("/");
+ return;
+ }
+
+ return (
+
+
+
+
+
+
+ Посылки
+
+ Доступные
+ Проверенные
+
+
+
+
+
+ );
+};
+
+export default ReviewPage;
diff --git a/services/frontend/src/pages/Review/modules/review-header.tsx b/services/frontend/src/pages/Review/modules/review-header.tsx
new file mode 100644
index 0000000..42782a6
--- /dev/null
+++ b/services/frontend/src/pages/Review/modules/review-header.tsx
@@ -0,0 +1,27 @@
+import { Button, buttonVariants } from "@/components/ui/button";
+import { DataRushReview } from "@/components/ui/icons/datarush-review";
+import { Reviewer } from "@/shared/types/review";
+import { Link } from "react-router";
+
+interface ReviewHeaderProps {
+ reviewer: Reviewer;
+}
+
+export const ReviewHeader = ({ reviewer }: ReviewHeaderProps) => {
+ return (
+
+
+
+
+ {reviewer.name} {reviewer.surname}
+
+
+ Выйти
+
+
+
+ );
+};
diff --git a/services/frontend/src/shared/api/auth.ts b/services/frontend/src/shared/api/auth.ts
index 901a4e1..58e5c77 100644
--- a/services/frontend/src/shared/api/auth.ts
+++ b/services/frontend/src/shared/api/auth.ts
@@ -1,4 +1,4 @@
-import { authFetch } from ".";
+import { apiFetch } from ".";
interface AuthResponse {
token: string;
@@ -9,14 +9,14 @@ export const signup = async (body: {
username: string;
password: string;
}) => {
- return await authFetch("/sign-up", {
+ return await apiFetch("/sign-up", {
method: "POST",
body,
});
};
export const login = async (body: { email: string; password: string }) => {
- return await authFetch("/sign-in", {
+ return await apiFetch("/sign-in", {
method: "POST",
body,
});
diff --git a/services/frontend/src/shared/api/competitions.ts b/services/frontend/src/shared/api/competitions.ts
new file mode 100644
index 0000000..5a5eba0
--- /dev/null
+++ b/services/frontend/src/shared/api/competitions.ts
@@ -0,0 +1,14 @@
+import { userFetch } from ".";
+import { Competition } from "../types/competition";
+
+export const getCompetitions = async (participating?: boolean) => {
+ return await userFetch("/competitions", {
+ params: {
+ is_participating: participating,
+ },
+ });
+};
+
+export const getCompetition = async (id: string) => {
+ return await userFetch(`/competition/${id}`);
+};
diff --git a/services/frontend/src/shared/api/index.ts b/services/frontend/src/shared/api/index.ts
index 8772105..0616a21 100644
--- a/services/frontend/src/shared/api/index.ts
+++ b/services/frontend/src/shared/api/index.ts
@@ -14,17 +14,16 @@ export class ApiError extends Error {
}
}
-export const authFetch = ofetch.create({
+export const apiFetch = ofetch.create({
baseURL: BASE_URL,
async onResponseError({ response }) {
throw new ApiError(response);
},
});
-export const apiFetch = ofetch.create({
+export const userFetch = ofetch.create({
baseURL: BASE_URL,
async onRequest({ options }) {
- console.log(import.meta.env.VITE_API_ENDPOINT);
options.headers.set("Authorization", "Bearer " + getToken());
},
async onResponseError({ response }) {
diff --git a/services/frontend/src/shared/api/review.ts b/services/frontend/src/shared/api/review.ts
new file mode 100644
index 0000000..887999b
--- /dev/null
+++ b/services/frontend/src/shared/api/review.ts
@@ -0,0 +1,10 @@
+import { apiFetch } from ".";
+import { Reviewer } from "../types/review";
+
+export const getReviewer = async (token: string) => {
+ return await apiFetch(`/review/${token}`);
+};
+
+export const getReviewerSubmissions = async (token: string) => {
+ return await apiFetch(`/review/${token}/submissions`);
+};
diff --git a/services/frontend/src/shared/api/user.ts b/services/frontend/src/shared/api/user.ts
index b71c15f..84b000d 100644
--- a/services/frontend/src/shared/api/user.ts
+++ b/services/frontend/src/shared/api/user.ts
@@ -1,6 +1,6 @@
-import { apiFetch } from ".";
+import { userFetch } from ".";
import { User } from "../types/user";
export const getCurrentUser = async () => {
- return await apiFetch("/me");
+ return await userFetch("/me");
};
diff --git a/services/frontend/src/shared/types/competition.ts b/services/frontend/src/shared/types/competition.ts
new file mode 100644
index 0000000..beea20e
--- /dev/null
+++ b/services/frontend/src/shared/types/competition.ts
@@ -0,0 +1,26 @@
+export interface Competition {
+ id: string;
+ title: string;
+ description: string;
+ state: CompetitionState;
+ image_url?: string;
+ start_date?: Date;
+ end_date?: Date;
+ type: CompetitionType;
+ participation_type: CompetitionParticipationType;
+}
+
+export enum CompetitionState {
+ NOT_STARTED = "not_started",
+ STARTED = "started",
+ FINISHED = "finished",
+}
+
+export enum CompetitionType {
+ EDU = "edu",
+ COMPETITIVE = "competitive",
+}
+
+export enum CompetitionParticipationType {
+ SOLO = "solo",
+}
diff --git a/services/frontend/src/shared/types/review.ts b/services/frontend/src/shared/types/review.ts
new file mode 100644
index 0000000..f3a9094
--- /dev/null
+++ b/services/frontend/src/shared/types/review.ts
@@ -0,0 +1,5 @@
+export interface Reviewer {
+ id: string;
+ name: string;
+ surname: string;
+}
diff --git a/services/frontend/src/styles/globals.css b/services/frontend/src/styles/globals.css
index 644cc81..860667b 100644
--- a/services/frontend/src/styles/globals.css
+++ b/services/frontend/src/styles/globals.css
@@ -88,7 +88,6 @@
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(0.269 0 0);
--sidebar-ring: oklch(0.439 0 0);
-
}
@theme inline {
@@ -120,6 +119,7 @@
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
+ --radius-6: calc(var(--radius) + 6px);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
Посылки
++ {reviewer.name} {reviewer.surname} +
+ + Выйти + +