update and create article provider functions
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Typography, Divider, IconButton, Chip, TextField, Button } from '@mui/material';
|
||||
import { Box, Typography, Divider, IconButton, TextField, Button } from '@mui/material';
|
||||
import { styled } from '@mui/material/styles';
|
||||
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
|
||||
import { ArticleEditorProps } from '../../types/props';
|
||||
import { ArticleModel } from "../../types/models";
|
||||
import { useUpload } from "../../providers/Upload";
|
||||
import { useArticles } from "../../providers/Article";
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import ImageUploadField from "../ImageUploadField";
|
||||
import { useUpload } from "../../providers/Upload";
|
||||
|
||||
const ArticleContainer = styled(Box)(({ theme }) => ({
|
||||
maxWidth: '800px',
|
||||
@@ -31,6 +33,7 @@ export default function ArticleView({
|
||||
}: ArticleEditorProps) {
|
||||
|
||||
const { uploadFile } = useUpload();
|
||||
const { updateArticle, createArticle } = useArticles();
|
||||
|
||||
const [title, setTitle] = React.useState(article?.title ?? "");
|
||||
const [description, setDescription] = React.useState(article?.description ?? "");
|
||||
@@ -54,6 +57,18 @@ export default function ArticleView({
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveArticle = async (articleData: Partial<ArticleModel>) => {
|
||||
// If _id exists → UPDATE
|
||||
if (articleData._id) {
|
||||
console.log("Updating article with ID:", articleData._id);
|
||||
return await updateArticle(articleData as ArticleModel);
|
||||
}
|
||||
|
||||
// No _id → CREATE
|
||||
console.log("Creating new article:", articleData);
|
||||
return await createArticle(articleData as ArticleModel);
|
||||
};
|
||||
|
||||
return (
|
||||
<ArticleContainer>
|
||||
{/* BACK BUTTON */}
|
||||
@@ -159,7 +174,7 @@ export default function ArticleView({
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() =>
|
||||
console.log({
|
||||
handleSaveArticle({
|
||||
...article,
|
||||
title,
|
||||
tag,
|
||||
|
||||
@@ -12,6 +12,14 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const { token } = useAuth();
|
||||
|
||||
/** 🔹 Author IDs must be strings for API, so we normalize here */
|
||||
const normalizeArticleForApi = (article: Partial<ArticleModel>) => ({
|
||||
...article,
|
||||
authors: (article.authors ?? []).map(a =>
|
||||
a._id
|
||||
),
|
||||
});
|
||||
|
||||
/** 🔹 Fetch articles (JWT automatically attached by api.ts interceptor) */
|
||||
const fetchArticles = async () => {
|
||||
try {
|
||||
@@ -29,6 +37,50 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child
|
||||
}
|
||||
};
|
||||
|
||||
/** 🔹 Update article */
|
||||
const updateArticle = async (articleData: ArticleModel) => {
|
||||
if (!articleData._id) {
|
||||
console.error('updateArticle called without _id');
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedArticleData = normalizeArticleForApi(articleData);
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const res = await api.put<ArticleModel>(`/articles/${articleData._id}`, normalizedArticleData);
|
||||
return res.data;
|
||||
} catch (err: any) {
|
||||
console.error('Article update failed:', err);
|
||||
setError(err.response?.data?.detail || 'Failed to update article');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
/** 🔹 Create article */
|
||||
const createArticle = async (articleData: ArticleModel) => {
|
||||
if (articleData._id) {
|
||||
console.error('createArticle called with _id');
|
||||
return;
|
||||
}
|
||||
|
||||
const normalizedArticleData = normalizeArticleForApi(articleData);
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
const res = await api.post<ArticleModel>(`/articles`, normalizedArticleData);
|
||||
return res.data;
|
||||
} catch (err: any) {
|
||||
console.error('Article create failed:', err);
|
||||
setError(err.response?.data?.detail || 'Failed to create article');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
/** 🔹 Auto-fetch articles whenever user logs in/out */
|
||||
useEffect(() => {
|
||||
// Always load once on mount
|
||||
@@ -41,7 +93,14 @@ export const ArticleProvider: React.FC<{ children: React.ReactNode }> = ({ child
|
||||
}, [token]);
|
||||
|
||||
return (
|
||||
<ArticleContext.Provider value={{ articles, loading, error, refreshArticles: fetchArticles }}>
|
||||
<ArticleContext.Provider value={{
|
||||
articles,
|
||||
loading,
|
||||
error,
|
||||
refreshArticles: fetchArticles,
|
||||
updateArticle,
|
||||
createArticle,
|
||||
}}>
|
||||
{children}
|
||||
</ArticleContext.Provider>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,8 @@ export interface ArticleContextModel {
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refreshArticles: () => Promise<void>;
|
||||
updateArticle: (user: ArticleModel) => Promise<ArticleModel | void>;
|
||||
createArticle: (user: ArticleModel) => Promise<ArticleModel | void>;
|
||||
}
|
||||
|
||||
export interface AuthContextModel {
|
||||
|
||||
Reference in New Issue
Block a user