Skip to content

Commit

Permalink
update frontend-web for sprint
Browse files Browse the repository at this point in the history
  • Loading branch information
JannisSideras committed Oct 21, 2024
1 parent 34897fa commit 9497ad7
Show file tree
Hide file tree
Showing 14 changed files with 972 additions and 205 deletions.
165 changes: 165 additions & 0 deletions logic/frontend/web/src/app/FYP/CreateComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"use client";
import { useState } from "react";
import { Box, Button, TextField, Typography, ToggleButton, ToggleButtonGroup, Dialog, DialogTitle, DialogContent, IconButton } from "@mui/material";
import AddIcon from '@mui/icons-material/Add';
import DeleteIcon from '@mui/icons-material/Delete';
import axios from "axios";
import {useUser} from "@/provider/UserProvider";

export default function CreateComponent() {
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [betType, setBetType] = useState("TEXT");
const [pollOptions, setPollOptions] = useState([{ id: 1, title: "" }, { id: 2, title: "" }]);
const [pollDialogOpen, setPollDialogOpen] = useState(false);
const {user} = useUser()


const handleCreate = async () => {
const newBet = {
createdOn: new Date().toISOString(),
title,
definition: description,
creatorId: user?.userId, // Replace with actual creatorId
creatorName: user?.username, // Replace with actual creatorName
status: "OPEN",
type: betType,
typeInfo: betType === "POLL" ? { pollAnswers: pollOptions.map(option => ({ title: option.title })) } : undefined,
};
console.log(newBet)

try {
const url = betType === "POLL" ? "https://www.boast.social/api/posts/poll" : "https://www.boast.social/api/posts/text";
await axios.post(url, newBet);
console.log("Bet created successfully:", newBet);
} catch (error) {
console.error("Error creating bet:", error);
}
};

const handlePollOptionChange = (id: number, value: string) => {
setPollOptions(pollOptions.map(option => option.id === id ? { ...option, title: value } : option));
};

const addPollOption = () => {
setPollOptions([...pollOptions, { id: pollOptions.length + 1, title: "" }]);
};

const removePollOption = (id: number) => {
if (pollOptions.length > 2) {
setPollOptions(pollOptions.filter(option => option.id !== id));
}
};

return (
<Box p={3} bgcolor="#22264B" color="white" borderRadius="8px">
<Typography>Bet</Typography>
<TextField
label=""
placeholder=""
variant="outlined"
fullWidth
margin="normal"
value={title}
onChange={(e) => setTitle(e.target.value)}
sx={{
'& .MuiInputBase-input': {
color: 'white',
},
'& .MuiInputLabel-root': {
color: 'white',
},
}}
/>
<Typography>Description</Typography>
<TextField
label=""
variant="outlined"
fullWidth
margin="normal"
multiline
rows={4}
value={description}
onChange={(e) => setDescription(e.target.value)}
sx={{
'& .MuiInputBase-input': {
color: 'white',
},
'& .MuiInputLabel-root': {
color: 'white',
},
}}
/>
<ToggleButtonGroup
value={betType}
exclusive
onChange={(e, newType) => {
setBetType(newType);
if (newType === "POLL") {
setPollDialogOpen(true);
}
}}
aria-label="bet type"
sx={{
mt: 2,
mb: 2,
display: "flex",
justifyContent: "center",
'& .MuiToggleButton-root': {
color: 'white', // Text color
borderColor: 'white', // Border color
minWidth: '150px', // Make buttons wider
'&.Mui-selected': {
backgroundColor: '#3f51b5', // Background color when selected
color: 'white', // Text color when selected
},
'&:hover': {
backgroundColor: '#3f51b5', // Background color on hover
color: 'white', // Text color on hover
},
},
}}
>
<ToggleButton value="TEXT" aria-label="text bet">
Text
</ToggleButton>
<ToggleButton value="POLL" aria-label="poll bet">
Poll
</ToggleButton>
</ToggleButtonGroup>
<Box display="flex" justifyContent="flex-end">
<Button variant="contained" color="primary" onClick={handleCreate}>
Create
</Button>
</Box>

<Dialog open={pollDialogOpen} onClose={() => setPollDialogOpen(false)} maxWidth="sm" fullWidth>
<DialogTitle>Customize Poll Options</DialogTitle>
<DialogContent>
{pollOptions.map(option => (
<Box key={option.id} display="flex" alignItems="center" mb={2}>
<TextField
label={`Option ${option.id}`}
variant="outlined"
fullWidth
value={option.title}
onChange={(e) => handlePollOptionChange(option.id, e.target.value)}
/>
<IconButton onClick={() => removePollOption(option.id)} color="secondary">
<DeleteIcon />
</IconButton>
</Box>
))}
<Button startIcon={<AddIcon />} onClick={addPollOption} color="primary">
Add Option
</Button>
<Box display="flex" justifyContent="flex-end" mt={2}>
<Button variant="contained" color="primary" onClick={() => setPollDialogOpen(false)}>
Confirm
</Button>
</Box>
</DialogContent>
</Dialog>
</Box>
);
}
198 changes: 198 additions & 0 deletions logic/frontend/web/src/app/FYP/ForYouComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
"use client";
import { Box, Button, Dialog, DialogContent, DialogTitle, TextField, Typography } from "@mui/material";
import Grid from "@mui/material/Grid2";
import React, { useEffect, useState } from "react";
import axios from "axios";
import { getPost, getPosts } from "@/service/post";
import { PostModel } from "@/model/model";
import { useUser } from "@/provider/UserProvider";

const colors = ["#C20B4E", "#3656FF", "#4ECA31"];

function getRandomColor() {
return colors[Math.floor(Math.random() * colors.length)];
}

interface ForYouComponentProps {
setShowPostComponent: (show: boolean) => void;
setSelectedPost: (post: PostModel | null) => void;
}

export default function ForYouComponent({ setShowPostComponent, setSelectedPost }: ForYouComponentProps) {
const [posts, setPosts] = useState<PostModel[]>([]);
const [dialogOpen, setDialogOpen] = useState(false);
const [textInput, setTextInput] = useState("");
const [selectedPollAnswer, setSelectedPollAnswer] = useState("1");
const [currentPost, setCurrentPost] = useState<PostModel | null>(null);
const { user } = useUser();


const handleGridItemClick = (post: PostModel) => {
setCurrentPost(post);
setDialogOpen(true);
};

const handleClose = () => {
setDialogOpen(false);
setCurrentPost(null);
setTextInput("");
setSelectedPollAnswer("1");
};

const handleBet = async () => {
if (currentPost?.type === "TEXT") {
const requestBody = {
createdOn: new Date().toISOString(),
creatorId: user?.userId,
creatorName: user?.username,
postId: currentPost.postId,
text: textInput
};

try {
await axios.post("https://www.boast.social/api/post-details/text", requestBody);
handleClose();
} catch (error) {
console.error("Error sending bet:", error);
}
} else if (currentPost?.type === "POLL") {
const requestBody = {
creatorId: user?.userId,
creatorName: user?.username,
postId: currentPost.postId,
pollAnswerId: selectedPollAnswer
};

try {
await axios.post("https://www.boast.social/api/post-details/poll", requestBody);
handleClose();
} catch (error) {
console.error("Error sending bet:", error);
}
}
};

const handleShowMore = () => {
setSelectedPost(currentPost);
setShowPostComponent(true);
handleClose();
};

useEffect(() => {
async function fetchPosts() {
try {
const postIds = await getPosts();
const postDetails = await Promise.all(postIds.map(id => getPost(id)));
setPosts(postDetails);
} catch (error) {
console.error('Error fetching posts:', error);
}
}

fetchPosts();
}, []);

return (
<>
<Typography
variant="h6"
color="white"
sx={{
padding: "20px",
position: "sticky",
backgroundColor: "#22264B",
top: 0,
zIndex: 1,
}}
>
For you
</Typography>
<Grid container spacing={4}
sx={{
width: "100%",
margin: "auto",
}}
>
{posts.map(post => (
<Grid size={4} key={post.postId}
sx={{
display: "flex",
justifyContent: "center",
}}
>
<Box
bgcolor={getRandomColor()}
height="12rem"
width="12rem"
display="flex"
justifyContent="center"
alignItems="center"
borderRadius="13px"
padding="10px"
onClick={() => handleGridItemClick(post)}
>
<Typography color="#ffffff" fontWeight={700}>
{post.title}
</Typography>
</Box>
</Grid>
))}
</Grid>
<Dialog open={dialogOpen} onClose={handleClose} maxWidth={"sm"} fullWidth={true}>
<DialogTitle sx={{ bgcolor: "#22264B", color: "white" }}>
{currentPost?.title}
<Button variant="outlined" sx={{marginLeft: "auto", float: "right"}} color="primary" onClick={handleShowMore}>
Show More
</Button>
</DialogTitle>
<DialogContent sx={{ bgcolor: "#22264B", color: "white" }}>
<Typography>{currentPost?.definition}</Typography>
<Typography align="right">by {currentPost?.creatorName}</Typography>
<Typography align="right">{currentPost?.postDetails?.length} participants</Typography>
<Box>
{currentPost?.type === "TEXT" && (
<TextField
label="Your Response"
variant="outlined"
fullWidth
margin="normal"
value={textInput}
onChange={(e) => setTextInput(e.target.value)}
InputProps={{ style: { color: 'white' } }}
InputLabelProps={{ style: { color: 'white' } }}
/>
)}
{currentPost?.type === "POLL" && Array.isArray(currentPost.typeInfo.pollAnswers) && (
<TextField
select
label="Select an Option"
variant="outlined"
fullWidth
margin="normal"
value={selectedPollAnswer}
onChange={(e) => setSelectedPollAnswer(e.target.value)}
SelectProps={{ native: true }}
InputProps={{ style: { color: 'white' } }}
InputLabelProps={{ style: { color: 'white' } }}
>
{currentPost.typeInfo.pollAnswers.map((option) => (
<option key={option.poll_answerId} value={option.poll_answerId}>
{option.title}
</option>
))}
</TextField>
)}
<Box display="flex" justifyContent="space-between" mt={2}>
<Button variant="contained" color="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="contained" color="primary" onClick={handleBet}>
Bet
</Button>
</Box>
</Box>
</DialogContent>
</Dialog>
</>
);
}
Loading

0 comments on commit 9497ad7

Please sign in to comment.