Skip to content

Commit 2687091

Browse files
committed
feat(): Adding the add article support
1 parent 90a4fe6 commit 2687091

12 files changed

Lines changed: 245 additions & 41 deletions

File tree

src/components/MdPreview/css/Markdown.module.css

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@
6262
border-collapse: collapse;
6363
border-spacing: 0;
6464
margin: 1rem;
65-
padding: 1rem;
66-
border: 1px solid #39422c;
6765
border-radius: 1rem;
6866
}
6967

src/screens/articleEditor/ArticleEditor.tsx

Lines changed: 144 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,170 @@
1-
import { Box, Input, VStack } from '@chakra-ui/react';
1+
import { Box, Button, HStack, Input, Text, VStack } from '@chakra-ui/react';
22
import { MDXEditor } from '@mdxeditor/editor';
33
import { ALL_PLUGINS } from './AllPlugins';
44
import '@mdxeditor/editor/style.css';
5-
import { useCursor } from '@components';
6-
import { useLayoutEffect } from 'react';
7-
8-
const MD_Example = `
9-
# Hello world
10-
This is a paragraph
11-
12-
- This is a list
13-
- This is another list
14-
15-
\`\`\`js
16-
console.log('Hello world');
17-
\`\`\`
18-
19-
This is a code block
20-
21-
`;
5+
import { ArticleCard, MdPreview, useCursor } from '@components';
6+
import { useCallback, useLayoutEffect, useState } from 'react';
7+
import { ARTICLE_DEFAULT } from './constants';
8+
import { ArticleWithContent } from './types';
9+
import { getRequestObject, isValidArticle } from './utils';
10+
import { useAddArticle } from '@services';
2211

2312
const ArticleEditor = () => {
2413
const { setCursorType } = useCursor();
14+
const [state, setState] = useState<ArticleWithContent>(ARTICLE_DEFAULT);
15+
const { mutate } = useAddArticle();
16+
2517
useLayoutEffect(() => {
2618
setCursorType('none');
27-
return () => {
28-
setCursorType('follow');
29-
};
3019
}, [setCursorType]);
20+
21+
const onSubmit = useCallback(() => {
22+
mutate(getRequestObject(state));
23+
console.log('Submitting article', state);
24+
}, [mutate, state]);
25+
3126
return (
3227
<VStack px={10} pt={20} width={'100vw'} rowGap={4} bg={'black'}>
33-
<VStack w={'50%'} rowGap={4}>
34-
<Input placeholder="Title" />
35-
<Input placeholder="Subtitle" />
36-
</VStack>
37-
<Box
28+
<HStack width={'100%'} justifyContent={'space-between'} align={'start'}>
29+
<VStack w={'80%'} rowGap={4}>
30+
<HStack w={'100%'} justifyContent={'space-between'}>
31+
<Text
32+
fontSize={'3xl'}
33+
fontWeight={'bold'}
34+
color={'white'}
35+
textAlign={'center'}
36+
>
37+
Article editor
38+
</Text>
39+
<Button
40+
onClick={() => setState(ARTICLE_DEFAULT)}
41+
colorScheme={'red'}
42+
>
43+
Clear Article
44+
</Button>
45+
</HStack>
46+
<HStack w={'100%'} rowGap={4}>
47+
<Input
48+
placeholder="Article Key"
49+
value={state.article_key}
50+
onChange={(e) =>
51+
setState((prev) => ({
52+
...prev,
53+
article_key: e.target.value,
54+
}))
55+
}
56+
/>
57+
<Input
58+
placeholder="Article Title"
59+
value={state.title}
60+
onChange={(e) =>
61+
setState((prev) => ({
62+
...prev,
63+
title: e.target.value,
64+
}))
65+
}
66+
/>
67+
<Input
68+
placeholder="Article description"
69+
value={state.description}
70+
onChange={(e) =>
71+
setState((prev) => ({
72+
...prev,
73+
description: e.target.value,
74+
}))
75+
}
76+
/>
77+
</HStack>
78+
<HStack w={'100%'} rowGap={4}>
79+
<Input
80+
placeholder="Author"
81+
value={state.author}
82+
onChange={(e) =>
83+
setState((prev) => ({
84+
...prev,
85+
author: e.target.value,
86+
}))
87+
}
88+
/>
89+
<Input
90+
placeholder="Group Id"
91+
value={state.group_id}
92+
onChange={(e) =>
93+
setState((prev) => ({
94+
...prev,
95+
group_id: e.target.value,
96+
}))
97+
}
98+
/>
99+
<Input
100+
placeholder="Group Name"
101+
value={state.group_name}
102+
onChange={(e) =>
103+
setState((prev) => ({
104+
...prev,
105+
group_name: e.target.value,
106+
}))
107+
}
108+
/>
109+
</HStack>
110+
<Input
111+
placeholder="Image"
112+
value={state.image}
113+
onChange={(e) =>
114+
setState((prev) => ({
115+
...prev,
116+
image: e.target.value,
117+
}))
118+
}
119+
/>
120+
<Button
121+
w={'100%'}
122+
onClick={onSubmit}
123+
isDisabled={!isValidArticle(state)}
124+
>
125+
Submit Article
126+
</Button>
127+
</VStack>
128+
<ArticleCard
129+
views={0}
130+
likes={0}
131+
last_updated={new Date().toISOString()}
132+
{...state}
133+
/>
134+
</HStack>
135+
<HStack
38136
width={'100%'}
39137
border={'1px solid white'}
40138
borderRadius={'md'}
41139
p={2}
42140
className=" min-h-[100vh]"
141+
align={'start'}
43142
>
44143
<MDXEditor
45144
className="bg-white"
46-
markdown={MD_Example}
145+
markdown={state.md_data}
47146
plugins={ALL_PLUGINS}
48147
spellCheck={true}
49148
contentEditableClassName="min-h-[100vh] px-6 py-6 prose"
149+
onChange={(md) => {
150+
setState((prev) => ({
151+
...prev,
152+
md_data: md,
153+
}));
154+
}}
50155
/>
51-
</Box>
156+
<Box w={'100%'} h={'100%'} bg={'gray.900'} borderRadius={'md'}>
157+
<Text
158+
textAlign={'center'}
159+
color={'white'}
160+
fontSize={'2xl'}
161+
fontWeight={'bold'}
162+
>
163+
Preview
164+
</Text>
165+
<MdPreview mdString={state.md_data} />
166+
</Box>
167+
</HStack>
52168
</VStack>
53169
);
54170
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ArticleWithContent } from './types';
2+
3+
export const ARTICLE_DEFAULT: ArticleWithContent = {
4+
article_key: '',
5+
image: '',
6+
title: '',
7+
description: '',
8+
md_data: '',
9+
author: '',
10+
group_id: '',
11+
group_name: '',
12+
};

src/screens/articleEditor/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export type ArticleWithContent = {
2+
article_key: string;
3+
image: string;
4+
title: string;
5+
description: string;
6+
md_data: string;
7+
author: string;
8+
group_id: string;
9+
group_name: string;
10+
};

src/screens/articleEditor/utils.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { ArticleWithContent } from './types';
2+
3+
export const isValidArticle = (article: ArticleWithContent) => {
4+
return Boolean(
5+
article.article_key &&
6+
article.title &&
7+
article.description &&
8+
article.md_data &&
9+
article.author &&
10+
article.group_id &&
11+
article.group_name,
12+
);
13+
};
14+
15+
export const getRequestObject = (article: ArticleWithContent) => {
16+
return {
17+
request: {
18+
article_key: article.article_key,
19+
image: article.image,
20+
title: article.title,
21+
description: article.description,
22+
md_data: article.md_data,
23+
author: {
24+
name: article.author,
25+
},
26+
group_id: article.group_id,
27+
group_name: article.group_name,
28+
},
29+
};
30+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { PostRequest } from '../client/client';
2+
import { ADD_ARTICLE_URL } from './constants';
3+
4+
const addArticle = async (data: unknown) => PostRequest(ADD_ARTICLE_URL, data);
5+
6+
export default addArticle;

src/services/backend/articles/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const LEARNING_BACKEND_URL = 'https://amitraikwar-services.onrender.com';
2+
// export const LEARNING_BACKEND_URL = 'http://localhost:3000';
23

34
// Query
45
export const ALL_ARTICLES_URL = `/all_articles`;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export { default as getArticlesData } from './getAllArticlesData';
22
export { default as getArticleData } from './getArticleData';
33
export { default as likePageArticleData } from './likePageArticleData';
4+
5+
export { default as addArticle } from './addArticle';
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import { GetRequest } from '../client/client';
1+
import { PostRequest } from '../client/client';
22
import { LIKE_ARTICLE_URL } from './constants';
33

4-
const getArticlesData = async () => {
5-
return await GetRequest(LIKE_ARTICLE_URL);
6-
};
4+
const getArticlesData = async () => PostRequest(LIKE_ARTICLE_URL, {});
75

86
export default getArticlesData;

src/services/backend/client/client.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ export const GetRequest = async (url: string) => {
1616
};
1717

1818
export const PostRequest = async (url: string, data: unknown) => {
19-
try {
20-
const response = await instance.post(url, data);
21-
return response.data;
22-
} catch (error) {
23-
// eslint-disable-next-line no-console
24-
console.error(error);
25-
}
19+
const response = await instance.post(url, data, {
20+
headers: {
21+
'Content-Type': 'application/json',
22+
'Access-Control-Allow-Origin': '*',
23+
},
24+
});
25+
return response.data;
2626
};

0 commit comments

Comments
 (0)