ImageUploadField
This commit is contained in:
45
src/blog/components/ImageUploadField.tsx
Normal file
45
src/blog/components/ImageUploadField.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import * as React from "react";
|
||||
import { Box, Button, Avatar, CircularProgress } from "@mui/material";
|
||||
import { ImageUploadFieldProps } from "../types/props";
|
||||
|
||||
export default function ImageUploadField({
|
||||
label = "Upload Image",
|
||||
value,
|
||||
uploading = false,
|
||||
onUpload,
|
||||
size = 64,
|
||||
}: ImageUploadFieldProps) {
|
||||
|
||||
const imgSrc = value
|
||||
? import.meta.env.VITE_API_BASE_URL.replace(/\/+$/, "") +
|
||||
"/" +
|
||||
value.replace(/^\/+/, "")
|
||||
: "";
|
||||
|
||||
return (
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: 2, mb: 3 }}>
|
||||
<Avatar
|
||||
src={imgSrc}
|
||||
sx={{ width: size, height: size, borderRadius: 2 }}
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant="outlined"
|
||||
component="label"
|
||||
disabled={uploading}
|
||||
startIcon={uploading && <CircularProgress size={16} />}
|
||||
>
|
||||
{uploading ? "Uploading..." : label}
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
hidden
|
||||
onChange={(e) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (file) onUpload(file);
|
||||
}}
|
||||
/>
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -6,11 +6,11 @@ import {
|
||||
Typography,
|
||||
IconButton,
|
||||
CircularProgress,
|
||||
Avatar,
|
||||
Alert,
|
||||
} from '@mui/material';
|
||||
import ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';
|
||||
import { useAuth } from '../providers/Author';
|
||||
import ImageUploadField from './ImageUploadField';
|
||||
|
||||
interface ProfileProps {
|
||||
onBack: () => void;
|
||||
@@ -120,30 +120,13 @@ export default function Profile({ onBack }: ProfileProps) {
|
||||
Profile
|
||||
</Typography>
|
||||
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2, mb: 3 }}>
|
||||
<Avatar
|
||||
src={
|
||||
(import.meta.env.VITE_API_BASE_URL.replace(/\/+$/, "") +
|
||||
"/" +
|
||||
(formData.avatar?.replace(/^\/+/, "") || "")
|
||||
)
|
||||
}
|
||||
alt={formData.name || formData.username}
|
||||
sx={{ width: 64, height: 64 }}
|
||||
/>
|
||||
|
||||
<Button variant="outlined" component="label">
|
||||
{uploadingAvatar ? "Uploading..." : "Upload Avatar"}
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
hidden
|
||||
onChange={(e) => {
|
||||
if (e.target.files?.[0]) handleAvatarUpload(e.target.files[0]);
|
||||
}}
|
||||
/>
|
||||
</Button>
|
||||
</Box>
|
||||
<ImageUploadField
|
||||
label="Upload Avatar"
|
||||
value={formData.avatar}
|
||||
uploading={uploadingAvatar}
|
||||
onUpload={handleAvatarUpload}
|
||||
size={64}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
|
||||
@@ -38,3 +38,11 @@ export interface ArticleGridProps {
|
||||
md4?: number; // default 4 (third-width)
|
||||
nested?: 1 | 2; // number of stacked cards in a nested column
|
||||
}
|
||||
|
||||
export interface ImageUploadFieldProps {
|
||||
label?: string;
|
||||
value?: string;
|
||||
uploading?: boolean;
|
||||
onUpload: (file: File) => void;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user