article form creator
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import Home from "./pages/Home";
|
|||||||
import Mission from "./pages/Mission";
|
import Mission from "./pages/Mission";
|
||||||
import UploadMissionForm from "./views/mission/UploadMissionForm";
|
import UploadMissionForm from "./views/mission/UploadMissionForm";
|
||||||
import MarkdownEditor from "./views/articleeditor/Editor";
|
import MarkdownEditor from "./views/articleeditor/Editor";
|
||||||
|
import ArticleEditor from "./pages/ArticleEditor";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
@@ -16,8 +17,9 @@ function App() {
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/home/*" element={<Home />} />
|
<Route path="/home/*" element={<Home />} />
|
||||||
<Route path="/mission/:missionId" element={<Mission />} />
|
<Route path="/mission/:missionId" element={<Mission />} />
|
||||||
|
<Route path="/article/create/*" element={<ArticleEditor />} />
|
||||||
<Route path="/upload" element={<UploadMissionForm/>}/>
|
<Route path="/upload" element={<UploadMissionForm/>}/>
|
||||||
<Route path="*" element={<MarkdownEditor onChange={(value: string) => {}}/>} />
|
<Route path="*" element={<MarkdownEditor onChange={(value: string) => {console.log(value)}}/>} />
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ interface inputProps {
|
|||||||
onChange: (state: string) => void;
|
onChange: (state: string) => void;
|
||||||
defaultState?: string;
|
defaultState?: string;
|
||||||
autocomplete?: string;
|
autocomplete?: string;
|
||||||
|
onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Input: React.FC<inputProps> = ({
|
export const Input: React.FC<inputProps> = ({
|
||||||
@@ -27,12 +28,14 @@ export const Input: React.FC<inputProps> = ({
|
|||||||
onChange,
|
onChange,
|
||||||
defaultState = "",
|
defaultState = "",
|
||||||
name = "",
|
name = "",
|
||||||
autocomplete="",
|
autocomplete = "",
|
||||||
|
onKeyDown,
|
||||||
}) => {
|
}) => {
|
||||||
const [value, setValue] = React.useState<string>(defaultState);
|
const [value, setValue] = React.useState<string>(defaultState);
|
||||||
const [visible, setVIsible] = React.useState<boolean>(type != "password");
|
const [visible, setVIsible] = React.useState<boolean>(type != "password");
|
||||||
|
|
||||||
React.useEffect(() => onChange(value), [value]);
|
React.useEffect(() => onChange(value), [value]);
|
||||||
|
React.useEffect(() => setValue(defaultState), [defaultState]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -59,12 +62,18 @@ export const Input: React.FC<inputProps> = ({
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setValue(e.target.value);
|
setValue(e.target.value);
|
||||||
}} />
|
}}
|
||||||
|
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (onKeyDown)
|
||||||
|
onKeyDown(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
{
|
{
|
||||||
type == "password" &&
|
type == "password" &&
|
||||||
<img src={visible ? eyeOpen : eyeClosed} className="w-[24px] h-[24px] cursor-pointer right-[16px] top-[8px] absolute" onClick={() => {
|
<img src={visible ? eyeOpen : eyeClosed} className="w-[24px] h-[24px] cursor-pointer right-[16px] top-[8px] absolute" onClick={() => {
|
||||||
setVIsible(!visible);
|
setVIsible(!visible);
|
||||||
}}/>
|
}} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
import { Route, Routes, useNavigate } from "react-router-dom";
|
||||||
|
import Header from '../views/articleeditor/Header';
|
||||||
|
import MarkdownEditor from "../views/articleeditor/Editor";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { PrimaryButton } from "../components/button/PrimaryButton";
|
||||||
|
import MarkdownPreview from "../views/articleeditor/MarckDownPreview";
|
||||||
|
import { Input } from "../components/input/Input";
|
||||||
|
|
||||||
|
|
||||||
|
const ArticleEditor = () => {
|
||||||
|
const [code, setCode] = useState<string>("");
|
||||||
|
const [name, setName] = useState<string>("");
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
||||||
|
const [tagInput, setTagInput] = useState<string>("");
|
||||||
|
const [tags, setTags] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const addTag = () => {
|
||||||
|
const newTag = tagInput.trim();
|
||||||
|
if (newTag && !tags.includes(newTag)) {
|
||||||
|
setTags([...tags, newTag]);
|
||||||
|
setTagInput("");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeTag = (tagToRemove: string) => {
|
||||||
|
setTags(tags.filter(tag => tag !== tagToRemove));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="h-screen grid grid-rows-[60px,1fr]">
|
||||||
|
|
||||||
|
<Routes>
|
||||||
|
<Route path="editor" element={<Header backUrl="/article/create" />} />
|
||||||
|
<Route path="*" element={<Header backUrl="/home/articles" />} />
|
||||||
|
</Routes>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Routes>
|
||||||
|
<Route path="editor" element={<MarkdownEditor onChange={setCode} />} />
|
||||||
|
<Route path="*" element={
|
||||||
|
<div className="text-liquid-white">
|
||||||
|
<div className="text-[40px] font-bold">Создание статьи</div>
|
||||||
|
|
||||||
|
|
||||||
|
<PrimaryButton onClick={() => {
|
||||||
|
console.log({
|
||||||
|
name: name,
|
||||||
|
tags: tags,
|
||||||
|
text: code,
|
||||||
|
})
|
||||||
|
|
||||||
|
}} text="Опубликовать" className="mt-[20px]" />
|
||||||
|
|
||||||
|
|
||||||
|
<Input name="articleName" autocomplete="articleName" className="mt-[20px] max-w-[600px]" type="text" label="Название" onChange={(v) => { setName(v) }} placeholder="Новая статья" />
|
||||||
|
|
||||||
|
|
||||||
|
{/* Блок для тегов */}
|
||||||
|
<div className="mt-[20px] max-w-[600px]">
|
||||||
|
|
||||||
|
<div className="grid grid-cols-[1fr,140px] items-end gap-2">
|
||||||
|
<Input
|
||||||
|
name="articleTag"
|
||||||
|
autocomplete="articleTag"
|
||||||
|
className="mt-[20px] max-w-[600px]"
|
||||||
|
type="text"
|
||||||
|
label="Теги"
|
||||||
|
onChange={(v) => { setTagInput(v) }}
|
||||||
|
defaultState={tagInput}
|
||||||
|
placeholder="arrays"
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
console.log(e.key);
|
||||||
|
if (e.key == "Enter")
|
||||||
|
addTag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<PrimaryButton onClick={addTag} text="Добавить" className="h-[40px] w-[140px]" />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap gap-[10px] mt-2">
|
||||||
|
{tags.map(tag => (
|
||||||
|
<div
|
||||||
|
key={tag}
|
||||||
|
className="flex items-center gap-1 bg-liquid-lighter px-3 py-1 rounded-full"
|
||||||
|
>
|
||||||
|
<span>{tag}</span>
|
||||||
|
<button onClick={() => removeTag(tag)} className="text-liquid-red font-bold ml-[5px]">×</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PrimaryButton onClick={() => navigate("editor")} text="Редактировать текст" className="mt-[20px]" />
|
||||||
|
<MarkdownPreview content={code} className="bg-transparent border-liquid-lighter border-[3px] rounder-[20px] mt-[20px]" />
|
||||||
|
</div>
|
||||||
|
} />
|
||||||
|
</Routes>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ArticleEditor;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useParams, Navigate } from 'react-router-dom';
|
import { useParams, Navigate } from 'react-router-dom';
|
||||||
import CodeEditor from '../views/mission/codeeditor/CodeEditor';
|
import CodeEditor from '../views/mission/codeeditor/CodeEditor';
|
||||||
import Statement, { StatementData } from '../views/mission/statement/Statement';
|
import Statement from '../views/mission/statement/Statement';
|
||||||
import { PrimaryButton } from '../components/button/PrimaryButton';
|
import { PrimaryButton } from '../components/button/PrimaryButton';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { useAppDispatch, useAppSelector } from '../redux/hooks';
|
import { useAppDispatch, useAppSelector } from '../redux/hooks';
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export const fetchWhoAmI = createAsyncThunk(
|
|||||||
// AsyncThunk: Загрузка токенов из localStorage
|
// AsyncThunk: Загрузка токенов из localStorage
|
||||||
export const loadTokensFromLocalStorage = createAsyncThunk(
|
export const loadTokensFromLocalStorage = createAsyncThunk(
|
||||||
"auth/loadTokens",
|
"auth/loadTokens",
|
||||||
async (_, { dispatch }) => {
|
async (_, { }) => {
|
||||||
const jwt = localStorage.getItem("jwt");
|
const jwt = localStorage.getItem("jwt");
|
||||||
const refreshToken = localStorage.getItem("refreshToken");
|
const refreshToken = localStorage.getItem("refreshToken");
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,8 @@
|
|||||||
import { FC, useEffect, useState } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
import ReactMarkdown from "react-markdown";
|
|
||||||
import remarkGfm from "remark-gfm";
|
|
||||||
import rehypeHighlight from "rehype-highlight";
|
|
||||||
import rehypeRaw from "rehype-raw";
|
|
||||||
import rehypeSanitize from "rehype-sanitize";
|
|
||||||
import axios from "../../axios";
|
import axios from "../../axios";
|
||||||
import "highlight.js/styles/github-dark.css";
|
import "highlight.js/styles/github-dark.css";
|
||||||
import Header from "../mission/statement/Header";
|
|
||||||
|
|
||||||
import { defaultSchema } from "hast-util-sanitize";
|
import MarkdownPreview from "./MarckDownPreview";
|
||||||
|
|
||||||
const schema = {
|
|
||||||
...defaultSchema,
|
|
||||||
attributes: {
|
|
||||||
...defaultSchema.attributes,
|
|
||||||
div: [
|
|
||||||
...(defaultSchema.attributes?.div || []),
|
|
||||||
["style"] // разрешаем атрибут style на div
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
interface MarkdownEditorProps {
|
interface MarkdownEditorProps {
|
||||||
@@ -264,26 +247,12 @@ print(greet("Мир"))
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen grid grid-rows-[60px,1fr]">
|
|
||||||
<div>
|
|
||||||
<Header missionId={1} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 h-full min-h-0">
|
<div className="grid grid-cols-2 h-full min-h-0">
|
||||||
{/* Предпросмотр */}
|
{/* Предпросмотр */}
|
||||||
<div className="overflow-y-auto min-h-0 overflow-hidden">
|
<div className="overflow-y-auto min-h-0 overflow-hidden">
|
||||||
<div className="p-4 border-r border-gray-700 flex flex-col h-full">
|
<div className="p-4 border-r border-gray-700 flex flex-col h-full">
|
||||||
<h2 className="text-lg font-semibold mb-3 text-gray-100">👀 Предпросмотр</h2>
|
<h2 className="text-lg font-semibold mb-3 text-gray-100">👀 Предпросмотр</h2>
|
||||||
<div className="flex-1 bg-[#161b22] rounded-lg shadow-lg p-6 h-[calc(100%-40px)]">
|
<MarkdownPreview content={markdown} className="h-[calc(100%-40px)]"/>
|
||||||
<div className="prose prose-invert max-w-none h-full overflow-auto pr-4 medium-scrollbar">
|
|
||||||
<ReactMarkdown
|
|
||||||
remarkPlugins={[remarkGfm]}
|
|
||||||
rehypePlugins={[rehypeRaw, [rehypeSanitize, schema], rehypeHighlight]}
|
|
||||||
>
|
|
||||||
{markdown}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -303,7 +272,6 @@ print(greet("Мир"))
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
31
src/views/articleeditor/Header.tsx
Normal file
31
src/views/articleeditor/Header.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { arrowLeft } from "../../assets/icons/header";
|
||||||
|
import { Logo } from "../../assets/logos";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
interface HeaderProps {
|
||||||
|
backUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Header: React.FC<HeaderProps> = ({
|
||||||
|
backUrl="/home/articles",
|
||||||
|
}) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
return (
|
||||||
|
<header className="w-full h-[60px] flex items-center px-4 gap-[20px]">
|
||||||
|
<img src={Logo} alt="Logo" className="h-[28px] w-auto cursor-pointer" onClick={() => { navigate("/home") }} />
|
||||||
|
|
||||||
|
<img src={arrowLeft} alt="back" className="h-[24px] w-[24px] cursor-pointer" onClick={() => { navigate(backUrl) }} />
|
||||||
|
|
||||||
|
{/* <div className="flex gap-[10px]">
|
||||||
|
<img src={chevroneLeft} alt="back" className="h-[24px] w-[24px] cursor-pointer" onClick={() => { navigate(`/mission/${missionId - 1}`) }} />
|
||||||
|
<span>{missionId}</span>
|
||||||
|
<img src={chevroneRight} alt="back" className="h-[24px] w-[24px] cursor-pointer" onClick={() => { navigate(`/mission/${missionId + 1}`) }} />
|
||||||
|
</div> */}
|
||||||
|
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
||||||
43
src/views/articleeditor/MarckDownPreview.tsx
Normal file
43
src/views/articleeditor/MarckDownPreview.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import ReactMarkdown from "react-markdown";
|
||||||
|
import remarkGfm from "remark-gfm";
|
||||||
|
import rehypeHighlight from "rehype-highlight";
|
||||||
|
import rehypeRaw from "rehype-raw";
|
||||||
|
import rehypeSanitize from "rehype-sanitize";
|
||||||
|
import "highlight.js/styles/github-dark.css";
|
||||||
|
|
||||||
|
import { defaultSchema } from "hast-util-sanitize";
|
||||||
|
import { cn } from "../../lib/cn";
|
||||||
|
|
||||||
|
const schema = {
|
||||||
|
...defaultSchema,
|
||||||
|
attributes: {
|
||||||
|
...defaultSchema.attributes,
|
||||||
|
div: [
|
||||||
|
...(defaultSchema.attributes?.div || []),
|
||||||
|
["style"] // разрешаем атрибут style на div
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MarkdownPreviewProps {
|
||||||
|
content: string;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MarkdownPreview: FC<MarkdownPreviewProps> = ({ content, className="" }) => {
|
||||||
|
return (
|
||||||
|
<div className={cn("flex-1 bg-[#161b22] rounded-lg shadow-lg p-6", className)}>
|
||||||
|
<div className="prose prose-invert max-w-none h-full overflow-auto pr-4 medium-scrollbar">
|
||||||
|
<ReactMarkdown
|
||||||
|
remarkPlugins={[remarkGfm]}
|
||||||
|
rehypePlugins={[rehypeRaw, [rehypeSanitize, schema], rehypeHighlight]}
|
||||||
|
>
|
||||||
|
{content}
|
||||||
|
</ReactMarkdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MarkdownPreview;
|
||||||
@@ -3,6 +3,7 @@ import { SecondaryButton } from "../../../components/button/SecondaryButton";
|
|||||||
import { useAppDispatch } from "../../../redux/hooks";
|
import { useAppDispatch } from "../../../redux/hooks";
|
||||||
import ArticleItem from "./ArticleItem";
|
import ArticleItem from "./ArticleItem";
|
||||||
import { setMenuActivePage } from "../../../redux/slices/store";
|
import { setMenuActivePage } from "../../../redux/slices/store";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
export interface Article {
|
export interface Article {
|
||||||
@@ -15,6 +16,7 @@ export interface Article {
|
|||||||
const Articles = () => {
|
const Articles = () => {
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const articles: Article[] = [
|
const articles: Article[] = [
|
||||||
{
|
{
|
||||||
@@ -142,7 +144,7 @@ const Articles = () => {
|
|||||||
Статьи
|
Статьи
|
||||||
</div>
|
</div>
|
||||||
<SecondaryButton
|
<SecondaryButton
|
||||||
onClick={() => { }}
|
onClick={() => {navigate("/article/create")}}
|
||||||
text="Создать статью"
|
text="Создать статью"
|
||||||
className="absolute right-0"
|
className="absolute right-0"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ const Login = () => {
|
|||||||
// После успешного логина
|
// После успешного логина
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(setMenuActivePage("account"))
|
dispatch(setMenuActivePage("account"))
|
||||||
|
console.log(submitClicked);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const Register = () => {
|
|||||||
if (jwt) {
|
if (jwt) {
|
||||||
navigate("/home");
|
navigate("/home");
|
||||||
}
|
}
|
||||||
|
console.log(submitClicked);
|
||||||
}, [jwt]);
|
}, [jwt]);
|
||||||
|
|
||||||
const handleRegister = () => {
|
const handleRegister = () => {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { cn } from "../../../lib/cn";
|
import { cn } from "../../../lib/cn";
|
||||||
import { Account } from "../../../assets/icons/auth";
|
import { Account } from "../../../assets/icons/auth";
|
||||||
import { registerUser } from "../../../redux/slices/auth";
|
|
||||||
import { PrimaryButton } from "../../../components/button/PrimaryButton";
|
import { PrimaryButton } from "../../../components/button/PrimaryButton";
|
||||||
import { ReverseButton } from "../../../components/button/ReverseButton";
|
import { ReverseButton } from "../../../components/button/ReverseButton";
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { PrimaryButton } from "../../../components/button/PrimaryButton";
|
|||||||
import { SecondaryButton } from "../../../components/button/SecondaryButton";
|
import { SecondaryButton } from "../../../components/button/SecondaryButton";
|
||||||
import { Input } from "../../../components/input/Input";
|
import { Input } from "../../../components/input/Input";
|
||||||
import { useAppDispatch, useAppSelector } from "../../../redux/hooks";
|
import { useAppDispatch, useAppSelector } from "../../../redux/hooks";
|
||||||
import { createGroup, deleteGroup, updateGroup } from "../../../redux/slices/groups";
|
import { deleteGroup, updateGroup } from "../../../redux/slices/groups";
|
||||||
|
|
||||||
interface ModalUpdateProps {
|
interface ModalUpdateProps {
|
||||||
active: boolean;
|
active: boolean;
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import SubmissionItem from "./SubmissionItem";
|
import SubmissionItem from "./SubmissionItem";
|
||||||
import { SecondaryButton } from "../../../components/button/SecondaryButton";
|
import { useAppSelector } from "../../../redux/hooks";
|
||||||
import { useAppDispatch, useAppSelector } from "../../../redux/hooks";
|
|
||||||
import { FC, useEffect } from "react";
|
import { FC, useEffect } from "react";
|
||||||
import { setMenuActivePage } from "../../../redux/slices/store";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
import { fetchMissions } from "../../../redux/slices/missions";
|
|
||||||
|
|
||||||
|
|
||||||
export interface Mission {
|
export interface Mission {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { cn } from "../../../lib/cn";
|
import { cn } from "../../../lib/cn";
|
||||||
import { IconError, IconSuccess } from "../../../assets/icons/missions";
|
// import { IconError, IconSuccess } from "../../../assets/icons/missions";
|
||||||
import { useNavigate } from "react-router-dom";
|
// import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
export interface SubmissionItemProps {
|
export interface SubmissionItemProps {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -43,7 +43,7 @@ const SubmissionItem: React.FC<SubmissionItemProps> = ({
|
|||||||
type,
|
type,
|
||||||
status,
|
status,
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
// const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn(" w-full relative rounded-[10px] text-liquid-white",
|
<div className={cn(" w-full relative rounded-[10px] text-liquid-white",
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/button/primarybutton.tsx","./src/components/button/secondarybutton.tsx","./src/components/checkbox/checkbox.tsx","./src/components/input/input.tsx","./src/components/switch/switch.tsx","./src/config/colors.ts","./src/lib/cn.ts","./src/redux/store.ts"],"version":"5.6.2"}
|
{"root":["./src/app.tsx","./src/axios.ts","./src/main.tsx","./src/vite-env.d.ts","./src/assets/icons/auth/index.ts","./src/assets/icons/groups/index.ts","./src/assets/icons/header/index.ts","./src/assets/icons/input/index.ts","./src/assets/icons/menu/index.ts","./src/assets/icons/missions/index.ts","./src/assets/logos/index.ts","./src/components/button/primarybutton.tsx","./src/components/button/reversebutton.tsx","./src/components/button/secondarybutton.tsx","./src/components/checkbox/checkbox.tsx","./src/components/drop-down-list/dropdownlist.tsx","./src/components/input/input.tsx","./src/components/modal/modal.tsx","./src/components/switch/switch.tsx","./src/config/colors.ts","./src/hooks/useclickoutside.ts","./src/lib/cn.ts","./src/pages/articleeditor.tsx","./src/pages/home.tsx","./src/pages/mission.tsx","./src/redux/hooks.ts","./src/redux/store.ts","./src/redux/slices/auth.ts","./src/redux/slices/contests.ts","./src/redux/slices/groups.ts","./src/redux/slices/missions.ts","./src/redux/slices/store.ts","./src/redux/slices/submit.ts","./src/views/articleeditor/editor.tsx","./src/views/articleeditor/header.tsx","./src/views/articleeditor/marckdownpreview.tsx","./src/views/home/articles/articleitem.tsx","./src/views/home/articles/articles.tsx","./src/views/home/auth/login.tsx","./src/views/home/auth/register.tsx","./src/views/home/contests/contestitem.tsx","./src/views/home/contests/contests.tsx","./src/views/home/contests/contestsblock.tsx","./src/views/home/groups/group.tsx","./src/views/home/groups/groupitem.tsx","./src/views/home/groups/groups.tsx","./src/views/home/groups/groupsblock.tsx","./src/views/home/groups/modalcreate.tsx","./src/views/home/groups/modalupdate.tsx","./src/views/home/menu/menu.tsx","./src/views/home/menu/menuitem.tsx","./src/views/home/missions/missionitem.tsx","./src/views/home/missions/missions.tsx","./src/views/mission/uploadmissionform.tsx","./src/views/mission/codeeditor/codeeditor.tsx","./src/views/mission/statement/header.tsx","./src/views/mission/statement/latextcontainer.tsx","./src/views/mission/statement/missionsubmissions.tsx","./src/views/mission/statement/statement.tsx","./src/views/mission/statement/submissionitem.tsx"],"version":"5.6.2"}
|
||||||
Reference in New Issue
Block a user