Skip to content

Commit

Permalink
feature: upload image(create a racing moment)
Browse files Browse the repository at this point in the history
  • Loading branch information
vantage-ola committed Sep 19, 2024
1 parent 3ada125 commit 60e1bc6
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 13 deletions.
2 changes: 2 additions & 0 deletions tracknow/web/src/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface Laptime {
platform?: string;
youtube_link?: string;
comment: string;
image?: string;
};

export interface CreateLaptimeResponse {
Expand All @@ -50,6 +51,7 @@ export interface GetUserLaptimesResponse {
platform: string;
youtube_link: string;
comment: string;
image: string;
user_id: number;
id: number;
by: string;
Expand Down
116 changes: 103 additions & 13 deletions tracknow/web/src/components/User/UserAddLaptimes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ import {
Heading, Stack, Button, FormControl,
Textarea, FormHelperText, Input, Select,
HStack, useToast,
FormErrorMessage,
FormErrorMessage, Text, VStack, Icon
} from "@chakra-ui/react";
import { SimracingTitles } from "../../misc/dropDown";
import { useLaptimes } from "../../hooks/useLaptimes";
import { Laptime } from "../../Types";
import { BeatLoader } from "react-spinners";
import useMiscFunctions from "../../misc/miscFunctions";
import { FiUpload } from "react-icons/fi";
//import { LoadingSpinner } from "../Loading/LoadingSpinner";
//import { useUsers } from "../../hooks/useUsers";

const UserAddLaptimes = () => {

const { addLaptime } = useLaptimes();
const { cloudName, uploadPreset, api_key } = useMiscFunctions(); // cloudinary names & preset


const [title, setTitle] = React.useState("");
const [car, setCar] = React.useState("");
Expand All @@ -25,16 +29,68 @@ const UserAddLaptimes = () => {
const [simracing, setSimracing] = React.useState(true);
const [platform, setPlatform] = React.useState("");
const [comment, setComment] = React.useState("");

const [image, setImage] = React.useState("");

const [isLoading, setIsLoading] = React.useState(false); // for moments
const [isUploading, setIsUploading] = React.useState(false); // image uploading

const toast = useToast();
const fileInputRef = React.useRef<HTMLInputElement>(null);

/*if (loading) {
return <LoadingSpinner />;
}; */
//console.log(simracing);
const handleuploadImage = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
if (file.size > 500 * 1024) { // 500KB in bytes
toast({
title: "File too large",
description: "Please upload an image smaller than 500KB.",
status: "error",
duration: 3000,
isClosable: true,
});
return;
}

setIsUploading(true);
const formData = new FormData();
formData.append("file", file);
formData.append("upload_preset", uploadPreset);
formData.append("api_key", api_key);

try {
const response = await fetch(
`https://api.cloudinary.com/v1_1/${cloudName}/image/upload`,
{
method: "POST",
body: formData,
}
);

const data = await response.json();
setImage(data.secure_url);
toast({
title: "Image uploaded successfully",
status: "success",
duration: 3000,
isClosable: true,
});
} catch (error) {
toast({
title: "Error uploading image",
description: (error as Error).message,
status: "error",
duration: 3000,
isClosable: true,
});
} finally {
setIsUploading(false);
}
}
};

const handleSubmit = async () => {
const newLaptime: Laptime = {
Expand All @@ -46,21 +102,19 @@ const UserAddLaptimes = () => {
simracing,
platform,
comment,
image
};
//console.log(newLaptime)
setIsLoading(true);
try {
const response = await addLaptime(newLaptime);
await addLaptime(newLaptime);
toast({
title: 'Moment created successfully',
status: "success",
duration: 3000,
isClosable: true,
});
window.location.href = ('/home');

} catch (error) {

toast({
title: "Error while creating Moment",
description: (error as Error).message,
Expand All @@ -70,7 +124,6 @@ const UserAddLaptimes = () => {
});
} finally {
setIsLoading(false);

}
};

Expand Down Expand Up @@ -172,7 +225,7 @@ const UserAddLaptimes = () => {
<Input
borderColor={'#323536'}
focusBorderColor="grey"
variant='flushed' placeholder='6:59:34.035'
variant='flushed' placeholder='6:54.554'
onChange={(e) => setTime(e.target.value)}
maxLength={10} />
{time && !timeRegex.test(time) && (
Expand All @@ -183,7 +236,7 @@ const UserAddLaptimes = () => {

<Box>
<Heading size='xs' textTransform='uppercase'>
Images / Videos
Youtube
</Heading>
<FormControl isInvalid={youtube_link && !youtubeRegex.test(youtube_link) ? true : undefined}>
<Input
Expand All @@ -197,17 +250,54 @@ const UserAddLaptimes = () => {
{youtube_link && !youtubeRegex.test(youtube_link) && (
<FormErrorMessage fontSize={'11px'}>Please enter a valid YouTube video URL</FormErrorMessage>
)}
<FormHelperText fontSize={'11px'}>Only Youtube links(Videos) are supported now, bear with me :)</FormHelperText>
</FormControl>

</Box>
<FormControl>
<Heading size='xs' textTransform='uppercase' mb={2}>
Upload Image
</Heading>
<Box
borderColor={'#323536'}
borderWidth={2}
borderStyle="dashed"
borderRadius="md"
p={4}
cursor="pointer"
onClick={() => fileInputRef.current?.click()}
>
<input
type="file"
accept="image/*"
onChange={handleuploadImage}
ref={fileInputRef}
style={{ display: 'none' }}
/>
<VStack spacing={2}>
<Icon as={FiUpload} w={8} h={8} />
<Text>Click or drag image here</Text>
<Text fontSize="sm" color="gray.500">Max file size: 500KB</Text>
</VStack>
</Box>
{isUploading && (
<Text mt={2} fontSize="sm" color="yellow.500">
Uploading image...
</Text>
)}
{image && !isUploading && (
<Text mt={2} fontSize="sm" color="green.500">
Image uploaded successfully
</Text>
)}
</FormControl>
</Stack>
</CardBody>
<Flex pr={5} mb={6} justifyContent={'flex-end'}>
<Button variant={"navbarButton"}
<Button
variant={"navbarButton"}
onClick={handleSubmit}
isDisabled={!title || !comment}
cursor={title && comment ? "pointer" : "not-allowed"}
isDisabled={!title || !comment || isUploading}
cursor={(title && comment && !isUploading) ? "pointer" : "not-allowed"}
isLoading={isLoading}
spinner={<BeatLoader size={8} color='red' />}
>
Expand Down

0 comments on commit 60e1bc6

Please sign in to comment.