Skip to content

Commit 39735d8

Browse files
committed
Adding the possibility to add contribution
1 parent 8873a90 commit 39735d8

34 files changed

+2551
-107
lines changed

.gitignore

-41
This file was deleted.

Client/src/App.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import ValidateEmail from './pages/ValidateEmail';
2525
import Stats from './pages/Stats';
2626
import MetaTags from './components/MetaTags';
2727
import Status from './pages/Status';
28+
import ContributeMenu from './pages/ContributeMenu';
29+
import Contribution from './pages/Contribution';
30+
import CreateContribution from './pages/CreateContribution';
2831

2932
console.log("test")
3033

@@ -55,6 +58,10 @@ const App: Component = () => {
5558
<Route path="/problem" element={<Problem />} />
5659
<Route path="/statistics" element={<Stats />} />
5760
<Route path="/status" element={<Status />} />
61+
<Route path="/contribute-menu" element={<ContributeMenu />} />
62+
<Route path="/contribution" element={<Contribution />} />
63+
<Route path="/create-contribution" element={<CreateContribution editContribution={false}/>} />
64+
<Route path="/edit-contribution" element={<CreateContribution editContribution={true}/>} />
5865
<Route path="/*" element={<Error />} />
5966
</Route>
6067
<Route path="/sign-up" element={localStorage.getItem('token') !== null && localStorage.getItem('token') !== undefined ? <MainLayout children={<ListProblems/>}/> : <SignUp /> } />
+18
Loading

Client/src/assets/icons/correct.svg

+1
Loading

Client/src/assets/icons/incorrect.svg

+1
Loading
Loading
-6.21 MB
Binary file not shown.
1.55 MB
Binary file not shown.
Binary file not shown.

Client/src/data/pagesFooter.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
},
1010
{
1111
"icon": "mail",
12-
"link": "mailto:[email protected]"
12+
"link": "mailto:[email protected]"
1313
},
1414
{
1515
"icon": "nouser_white",
1616
"link": "/profile"
1717
}
18-
]
18+
]

Client/src/data/pagesHeader.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,10 @@
3838
"icon": "translate",
3939
"link": "/translate",
4040
"title": "Translate"
41+
},
42+
{
43+
"icon": "contribute",
44+
"link": "/contribute-menu",
45+
"title": "Contribute"
4146
}
42-
]
47+
]

Client/src/data/version.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@
2929
"rust":" 1.64.0",
3030
"sass": "1.56.1",
3131
"scala": "0.0.0",
32-
"vyxal":"2.21.2"
33-
}
32+
"vyxal":"2.18.3"
33+
}

Client/src/hooks/createAuthFetch.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const createAuth = () => {
3434

3535
// If there is an error
3636
if (error && showError) {
37-
handleError(data.toString());
37+
handleError(data.toString().replace(/<[^>]*\>/g, ""));
3838
}
3939

4040
return {data, error, contentType};
@@ -44,4 +44,4 @@ const createAuth = () => {
4444
}
4545

4646

47-
export default createAuth;
47+
export default createAuth;

Client/src/layout/SmallNav.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const SmallNav = () => {
4444
c => <A href={c.link}>
4545
<button
4646
class={
47-
lastPath(location.pathname) === c.title.toLowerCase() ?
47+
lastPath(location.pathname).split('-')[0] === c.title.toLowerCase() ?
4848
"selected" :
4949
""
5050
}
@@ -77,4 +77,4 @@ const SmallNav = () => {
7777
}
7878

7979

80-
export default SmallNav;
80+
export default SmallNav;

Client/src/pages/ContributeMenu.tsx

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import { A } from "@solidjs/router";
2+
import { createEffect, createSignal, For, onMount } from "solid-js";
3+
import createAuth from "../hooks/createAuthFetch";
4+
import "../style/ContributeMenu.scss";
5+
6+
7+
8+
9+
interface contributionType {
10+
vote: number,
11+
id: number,
12+
title: string,
13+
description: string,
14+
author: string,
15+
state: number,
16+
}
17+
18+
19+
interface voteContributionType {
20+
id: number,
21+
up: boolean,
22+
}
23+
24+
25+
const ContributeMenu = () => {
26+
27+
const [contributions, setContributions] = createSignal<contributionType[]>([], {equals: false});
28+
const [listVoted, setListVoted] = createSignal<voteContributionType[]>([], {equals: false});
29+
const {token, authFetch} = createAuth();
30+
31+
onMount(() => {
32+
fetch("http://localhost:5000/api/v1/contributions")
33+
.then(rep => rep.json())
34+
.then(rep => setContributions(rep));
35+
36+
37+
if (token() !== undefined && token() !== "") {
38+
authFetch("http://localhost:5000/api/v1/votes-contributions")
39+
.then(
40+
(rep) => {
41+
if (!rep.error) {
42+
setListVoted(rep.data);
43+
}
44+
}
45+
)
46+
47+
}
48+
});
49+
50+
51+
const vote = (up: boolean, id: number) => {
52+
// If the user doesnt have a token, they cant vote.
53+
if (token() === undefined || token().length === 0) return;
54+
55+
// Send the request
56+
authFetch(
57+
"http://localhost:5000/api/v1/vote-contribution",
58+
{
59+
method: "POST",
60+
headers: {"Content-Type": "application/json"},
61+
body: JSON.stringify({ id, up }),
62+
}
63+
);
64+
65+
// Is it upvoted or downvoted ?
66+
const wasUpvoted = listVoted().some(v => v.id === id && v.up);
67+
const wasDownvoted = listVoted().some(v => v.id === id && !v.up);
68+
69+
// If the user clicked on the button but it was still there before
70+
if ((wasDownvoted && !up) || (wasUpvoted && up)) {
71+
72+
setListVoted((p:any) =>
73+
p.filter(e => e.id !== id)
74+
);
75+
76+
const newContributions =
77+
[...contributions().map(e => {
78+
if (e.id === id) {
79+
if (up) {
80+
e.vote -= 1;
81+
} else {
82+
e.vote += 1;
83+
}
84+
}
85+
86+
return {...e};
87+
})]
88+
89+
setContributions(p => newContributions);
90+
91+
} else {
92+
93+
// If there wasn't' a vote before
94+
if (!listVoted().some(v => v.id === id)) {
95+
setListVoted(
96+
p => [...p, {up: false, id: id}]
97+
)
98+
}
99+
100+
setListVoted((p:any) =>
101+
p.map(e => {
102+
if (e.id === id) {
103+
e.up = up;
104+
}
105+
return e;
106+
})
107+
);
108+
109+
const newContributions =
110+
[...contributions().map(e => {
111+
if (e.id === id) {
112+
if (up) {
113+
e.vote += 1 + +wasDownvoted - +wasUpvoted;
114+
} else {
115+
e.vote -= 1 + +wasUpvoted - +wasDownvoted;
116+
}
117+
}
118+
119+
return {...e};
120+
})]
121+
122+
setContributions(newContributions);
123+
124+
}
125+
}
126+
127+
128+
createEffect(() => {
129+
console.log(contributions());
130+
})
131+
132+
return <main class="contribute-menu">
133+
<h1>Contribution</h1>
134+
<p>
135+
Here, this is where WeekGolf members can create their own problems!<br/>
136+
You can propose a statement for a problem, but you can also vote and comment on the different problems ideas that users submitted!
137+
</p>
138+
139+
<A href="/create-contribution" class="create">
140+
+
141+
</A>
142+
143+
<ul>
144+
<For each={contributions()}>
145+
{
146+
c =>
147+
<li class={"contribution " + ["refused", "", "accepted"][c.state + 1]}>
148+
<div>
149+
<button
150+
class={`upvote ${listVoted().some(v => v.id === c.id && v.up) ? 'on' : ''}`}
151+
onClick={() => vote(true, c.id)}
152+
/>
153+
{
154+
c.vote
155+
}
156+
<button
157+
class={`downvote ${listVoted().some(v => v.id === c.id && !v.up) ? 'on' : ''}`}
158+
onClick={() => vote(false, c.id)}
159+
/>
160+
</div>
161+
<A href={`/contribution?id=${c.id}`}>
162+
<h2>
163+
{
164+
c.title
165+
}
166+
</h2>
167+
168+
<p>
169+
{
170+
c.description
171+
}
172+
</p>
173+
<footer>
174+
By
175+
<A href={`/profile?name=${c.author}`}>
176+
{
177+
c.author
178+
}
179+
</A>
180+
</footer>
181+
</A>
182+
</li>
183+
}
184+
</For>
185+
</ul>
186+
</main>
187+
}
188+
189+
190+
export default ContributeMenu;

0 commit comments

Comments
 (0)