mirror of
https://github.com/TurTaskProject/TurTaskWeb.git
synced 2025-12-19 22:14:07 +01:00
Merge branch 'feature/kanban-board' of https://github.com/TurTaskProject/TurTaskWeb into feature/kanban-board
This commit is contained in:
commit
95cc140a6b
@ -46,6 +46,7 @@
|
|||||||
"react-datetime-picker": "^5.5.3",
|
"react-datetime-picker": "^5.5.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^4.11.0",
|
||||||
|
"react-ios-time-picker": "^0.2.2",
|
||||||
"react-router-dom": "^6.18.0",
|
"react-router-dom": "^6.18.0",
|
||||||
"react-tsparticles": "^2.12.2",
|
"react-tsparticles": "^2.12.2",
|
||||||
"tsparticles": "^2.12.0"
|
"tsparticles": "^2.12.0"
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
lockfileVersion: '6.0'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
|
||||||
autoInstallPeers: true
|
|
||||||
excludeLinksFromLockfile: false
|
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
'@dnd-kit/core':
|
'@dnd-kit/core':
|
||||||
specifier: ^6.1.0
|
specifier: ^6.1.0
|
||||||
@ -113,6 +109,9 @@ dependencies:
|
|||||||
react-icons:
|
react-icons:
|
||||||
specifier: ^4.11.0
|
specifier: ^4.11.0
|
||||||
version: 4.12.0(react@18.2.0)
|
version: 4.12.0(react@18.2.0)
|
||||||
|
react-ios-time-picker:
|
||||||
|
specifier: ^0.2.2
|
||||||
|
version: 0.2.2(react-dom@18.2.0)(react@18.2.0)
|
||||||
react-router-dom:
|
react-router-dom:
|
||||||
specifier: ^6.18.0
|
specifier: ^6.18.0
|
||||||
version: 6.19.0(react-dom@18.2.0)(react@18.2.0)
|
version: 6.19.0(react-dom@18.2.0)(react@18.2.0)
|
||||||
@ -3573,6 +3572,17 @@ packages:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/react-ios-time-picker@0.2.2(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-bi+K23lK6Pf2xDXmhAlz+RJuy9/onWYi7Ye+ODVhIkis9AVFECOza2ckkZl/4vUypj2+TdTsHn+VZrTNdGIwDQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^18.2.0
|
||||||
|
react-dom: ^18.2.0
|
||||||
|
dependencies:
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
react-portal: 4.2.2(react-dom@18.2.0)(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-is@16.13.1:
|
/react-is@16.13.1:
|
||||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||||
|
|
||||||
@ -3612,6 +3622,17 @@ packages:
|
|||||||
warning: 4.0.3
|
warning: 4.0.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/react-portal@4.2.2(react-dom@18.2.0)(react@18.2.0):
|
||||||
|
resolution: {integrity: sha512-vS18idTmevQxyQpnde0Td6ZcUlv+pD8GTyR42n3CHUQq9OHi1C4jDE4ZWEbEsrbrLRhSECYiao58cvocwMtP7Q==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0
|
||||||
|
react-dom: ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0
|
||||||
|
dependencies:
|
||||||
|
prop-types: 15.8.1
|
||||||
|
react: 18.2.0
|
||||||
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/react-redux@7.2.9(react-dom@18.2.0)(react@18.2.0):
|
/react-redux@7.2.9(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==}
|
resolution: {integrity: sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -4663,3 +4684,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
settings:
|
||||||
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|||||||
@ -13,11 +13,7 @@ export function DonutChartGraph() {
|
|||||||
const completedTask = response.data.total_completed_tasks || 0;
|
const completedTask = response.data.total_completed_tasks || 0;
|
||||||
|
|
||||||
const donutData = [
|
const donutData = [
|
||||||
<<<<<<< HEAD
|
|
||||||
{ name: "Completed task", count: completedTask },
|
|
||||||
=======
|
|
||||||
{ name: "Completed task", count: completedTask},
|
{ name: "Completed task", count: completedTask},
|
||||||
>>>>>>> 4a3f253e3049f97ef4479dd423642897a56e13fc
|
|
||||||
{ name: "Total task", count: totalTask },
|
{ name: "Total task", count: totalTask },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -139,23 +139,6 @@ export function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
setMouseIsOver(false);
|
setMouseIsOver(false);
|
||||||
}}>
|
}}>
|
||||||
<<<<<<< HEAD
|
|
||||||
<p
|
|
||||||
className={`p-2.5 my-auto w-full overflow-y-auto overflow-x-hidden whitespace-pre-wrap rounded-xl shadow bg-white`}
|
|
||||||
onClick={() => document.getElementById(`task_detail_modal_${task.id}`).showModal()}>
|
|
||||||
{task.content}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{mouseIsOver && (
|
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
deleteTask(task.id);
|
|
||||||
}}
|
|
||||||
className="stroke-white absolute right-0 top-1/2 rounded-full bg-white -translate-y-1/2 bg-columnBackgroundColor p-2 hover:opacity-100 ">
|
|
||||||
<BsFillTrashFill />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
=======
|
|
||||||
{/* -------- Task Content -------- */}
|
{/* -------- Task Content -------- */}
|
||||||
{/* Tags */}
|
{/* Tags */}
|
||||||
{tags}
|
{tags}
|
||||||
@ -183,7 +166,6 @@ export function TaskCard({ task, deleteTask, updateTask }) {
|
|||||||
{dueDateTag}
|
{dueDateTag}
|
||||||
{subtaskCountTag}
|
{subtaskCountTag}
|
||||||
</div>
|
</div>
|
||||||
>>>>>>> 4a3f253e3049f97ef4479dd423642897a56e13fc
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -3,9 +3,21 @@ import { FaTasks, FaRegListAlt } from "react-icons/fa";
|
|||||||
import { FaPlus } from "react-icons/fa6";
|
import { FaPlus } from "react-icons/fa6";
|
||||||
import { TbChecklist } from "react-icons/tb";
|
import { TbChecklist } from "react-icons/tb";
|
||||||
import DatePicker from "react-datepicker";
|
import DatePicker from "react-datepicker";
|
||||||
|
import { TimePicker } from "react-ios-time-picker";
|
||||||
import "react-datepicker/dist/react-datepicker.css";
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
|
import { borderColor } from "@mui/system";
|
||||||
|
|
||||||
export function TaskDetailModal({ title, description, tags, difficulty, challenge, importance, taskId, updateTask }) {
|
export function TaskDetailModal({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
tags,
|
||||||
|
difficulty,
|
||||||
|
challenge,
|
||||||
|
importance,
|
||||||
|
taskId,
|
||||||
|
updateTask,
|
||||||
|
}) {
|
||||||
|
let date = new Date();
|
||||||
const [isChallengeChecked, setChallengeChecked] = useState(challenge);
|
const [isChallengeChecked, setChallengeChecked] = useState(challenge);
|
||||||
const [isImportantChecked, setImportantChecked] = useState(importance);
|
const [isImportantChecked, setImportantChecked] = useState(importance);
|
||||||
const [currentDifficulty, setCurrentDifficulty] = useState(difficulty);
|
const [currentDifficulty, setCurrentDifficulty] = useState(difficulty);
|
||||||
@ -15,7 +27,11 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
const [startDateEnabled, setStartDateEnabled] = useState(false);
|
const [startDateEnabled, setStartDateEnabled] = useState(false);
|
||||||
const [endDateEnabled, setEndDateEnabled] = useState(false);
|
const [endDateEnabled, setEndDateEnabled] = useState(false);
|
||||||
const [isTaskComplete, setTaskComplete] = useState(false);
|
const [isTaskComplete, setTaskComplete] = useState(false);
|
||||||
|
const [value, setValue] = useState('10:00');
|
||||||
|
|
||||||
|
const onChange = (timeValue) => {
|
||||||
|
setValue(timeValue);
|
||||||
|
};
|
||||||
const handleChallengeChange = () => {
|
const handleChallengeChange = () => {
|
||||||
setChallengeChecked(!isChallengeChecked);
|
setChallengeChecked(!isChallengeChecked);
|
||||||
};
|
};
|
||||||
@ -30,7 +46,11 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
|
|
||||||
const handleTagChange = (tag) => {
|
const handleTagChange = (tag) => {
|
||||||
const isSelected = selectedTags.includes(tag);
|
const isSelected = selectedTags.includes(tag);
|
||||||
setSelectedTags(isSelected ? selectedTags.filter((selectedTag) => selectedTag !== tag) : [...selectedTags, tag]);
|
setSelectedTags(
|
||||||
|
isSelected
|
||||||
|
? selectedTags.filter((selectedTag) => selectedTag !== tag)
|
||||||
|
: [...selectedTags, tag]
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleStartDateChange = () => {
|
const handleStartDateChange = () => {
|
||||||
@ -59,7 +79,8 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
const existingTags = tags.map((tag, index) => (
|
const existingTags = tags.map((tag, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={`text-xs inline-flex items-center font-bold leading-sm uppercase px-2 py-1 bg-${tag.color}-200 text-${tag.color}-700 rounded-full`}>
|
className={`text-xs inline-flex items-center font-bold leading-sm uppercase px-2 py-1 bg-${tag.color}-200 text-${tag.color}-700 rounded-full`}
|
||||||
|
>
|
||||||
{tag.label}
|
{tag.label}
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
@ -68,7 +89,8 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
const selectedTagElements = selectedTags.map((tag, index) => (
|
const selectedTagElements = selectedTags.map((tag, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className={`text-xs inline-flex items-center font-bold leading-sm uppercase px-2 py-1 bg-${tag.color}-200 text-${tag.color}-700 rounded-full`}>
|
className={`text-xs inline-flex items-center font-bold leading-sm uppercase px-2 py-1 bg-${tag.color}-200 text-${tag.color}-700 rounded-full`}
|
||||||
|
>
|
||||||
{tag.label}
|
{tag.label}
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
@ -92,10 +114,16 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
<div className="flex flex-col py-2 pb-4">
|
<div className="flex flex-col py-2 pb-4">
|
||||||
<div className="flex flex-row space-x-5">
|
<div className="flex flex-row space-x-5">
|
||||||
<div className="dropdown">
|
<div className="dropdown">
|
||||||
<label tabIndex={0} className="btn-md border-2 rounded-xl m-1 py-1">
|
<label
|
||||||
|
tabIndex={0}
|
||||||
|
className="btn-md border-2 rounded-xl m-1 py-1"
|
||||||
|
>
|
||||||
+ Add Tags
|
+ Add Tags
|
||||||
</label>
|
</label>
|
||||||
<ul tabIndex={0} className="dropdown-content z-[10] menu p-2 shadow bg-base-100 rounded-box w-52">
|
<ul
|
||||||
|
tabIndex={0}
|
||||||
|
className="dropdown-content z-[10] menu p-2 shadow bg-base-100 rounded-box w-52"
|
||||||
|
>
|
||||||
{tags.map((tag, index) => (
|
{tags.map((tag, index) => (
|
||||||
<li key={index}>
|
<li key={index}>
|
||||||
<label className="cursor-pointer space-x-2">
|
<label className="cursor-pointer space-x-2">
|
||||||
@ -127,10 +155,14 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={startDateEnabled}
|
checked={startDateEnabled}
|
||||||
className="checkbox checkbox-xs"
|
className="checkbox checkbox-xs bg-black"
|
||||||
onChange={handleStartDateChange}
|
onChange={handleStartDateChange}
|
||||||
/>
|
/>
|
||||||
<div className={`rounded p-2 shadow border-2 ${!startDateEnabled && "opacity-50"}`}>
|
<div
|
||||||
|
className={`rounded p-2 shadow border-2 ${
|
||||||
|
!startDateEnabled && "opacity-50"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
selected={dateStart}
|
selected={dateStart}
|
||||||
onChange={(date) => setDateStart(date)}
|
onChange={(date) => setDateStart(date)}
|
||||||
@ -139,6 +171,15 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="rounded p-2 shadow border-2">
|
||||||
|
|
||||||
|
<TimePicker
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
className="rounded p-2 shadow border-2 z-[10000] relative"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{/* Complete? */}
|
{/* Complete? */}
|
||||||
<div className="mx-4">
|
<div className="mx-4">
|
||||||
<div className="flex items-center space-x-2 mt-4">
|
<div className="flex items-center space-x-2 mt-4">
|
||||||
@ -147,7 +188,7 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={isTaskComplete}
|
checked={isTaskComplete}
|
||||||
className="checkbox checkbox-xl"
|
className="checkbox checkbox-xl bg-black"
|
||||||
onChange={handleTaskCompleteChange}
|
onChange={handleTaskCompleteChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -161,11 +202,19 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={endDateEnabled}
|
checked={endDateEnabled}
|
||||||
className="checkbox checkbox-xs"
|
className="checkbox checkbox-xs bg-black"
|
||||||
onChange={handleEndDateChange}
|
onChange={handleEndDateChange}
|
||||||
/>
|
/>
|
||||||
<div className={`rounded p-2 shadow border-2 ${!endDateEnabled && "opacity-50"}`}>
|
<div
|
||||||
<DatePicker selected={dateEnd} onChange={(date) => setDateEnd(date)} disabled={!endDateEnabled} />
|
className={`rounded p-2 shadow border-2 ${
|
||||||
|
!endDateEnabled && "opacity-50"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<DatePicker
|
||||||
|
selected={dateEnd}
|
||||||
|
onChange={(date) => setDateEnd(date)}
|
||||||
|
disabled={!endDateEnabled}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -211,7 +260,7 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={isChallengeChecked}
|
checked={isChallengeChecked}
|
||||||
className="checkbox"
|
className="checkbox bg-black"
|
||||||
onChange={handleChallengeChange}
|
onChange={handleChallengeChange}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
@ -226,7 +275,7 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={isImportantChecked}
|
checked={isImportantChecked}
|
||||||
className="checkbox"
|
className="checkbox bg-black"
|
||||||
onChange={handleImportantChange}
|
onChange={handleImportantChange}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
@ -242,7 +291,11 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
</span>
|
</span>
|
||||||
</h2>
|
</h2>
|
||||||
<div className="flex space-x-3 pt-2">
|
<div className="flex space-x-3 pt-2">
|
||||||
<input type="text" placeholder="subtask topic" className="input input-bordered flex-1 w-full" />
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="subtask topic"
|
||||||
|
className="input input-bordered flex-1 w-full"
|
||||||
|
/>
|
||||||
<button className="btn">
|
<button className="btn">
|
||||||
<FaPlus />
|
<FaPlus />
|
||||||
Add Subtask
|
Add Subtask
|
||||||
@ -250,7 +303,9 @@ export function TaskDetailModal({ title, description, tags, difficulty, challeng
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form method="dialog">
|
<form method="dialog">
|
||||||
<button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">X</button>
|
<button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">
|
||||||
|
X
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|||||||
@ -39,12 +39,12 @@ export function NavBar() {
|
|||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
className="mt-3 z-[10] p-2 shadow menu menu-sm dropdown-content bg-base-100 rounded-box w-52">
|
className="mt-3 z-[10] p-2 shadow menu menu-sm dropdown-content bg-base-100 rounded-box w-52">
|
||||||
<li>
|
<li>
|
||||||
<a href={settings.Profile} className="justify-between">
|
<a onClick={() => Navigate(settings.Profile)} className="justify-between">
|
||||||
Profile
|
Profile
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href={settings.Account}>Settings</a>
|
<a onClick={() => Navigate(settings.Account)}>Settings</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a onClick={logout}>Logout</a>
|
<a onClick={logout}>Logout</a>
|
||||||
|
|||||||
@ -1,13 +1,30 @@
|
|||||||
import { useState, useRef } from "react";
|
import { useState, useRef } from "react";
|
||||||
import { ApiUpdateUserProfile } from "src/api/UserProfileApi";
|
import { ApiUpdateUserProfile } from "src/api/UserProfileApi";
|
||||||
|
import { axiosInstance } from "src/api/AxiosConfig";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export function ProfileUpdateComponent() {
|
export function ProfileUpdateComponent() {
|
||||||
const [file, setFile] = useState(null);
|
const [file, setFile] = useState(null);
|
||||||
const [username, setUsername] = useState("");
|
const [firstName, setFirstName] = useState("");
|
||||||
const [fullName, setFullName] = useState("");
|
const [about, setAbout] = useState();
|
||||||
const [about, setAbout] = useState("");
|
|
||||||
const defaultImage = "https://i1.sndcdn.com/artworks-cTz48e4f1lxn5Ozp-L3hopw-t500x500.jpg";
|
|
||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
|
const [profile_pic, setProfilePic] = useState(undefined);
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUser = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axiosInstance.get("/user/data/");
|
||||||
|
const fetchedProfilePic = response.data.profile_pic;
|
||||||
|
const fetchedName = response.data.first_name;
|
||||||
|
const fetchedAbout = response.data.about;
|
||||||
|
setProfilePic(fetchedProfilePic);
|
||||||
|
setAbout(fetchedAbout);
|
||||||
|
setFirstName(fetchedName);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching user:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchUser();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleImageUpload = () => {
|
const handleImageUpload = () => {
|
||||||
if (fileInputRef.current) {
|
if (fileInputRef.current) {
|
||||||
@ -25,7 +42,7 @@ export function ProfileUpdateComponent() {
|
|||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("profile_pic", file);
|
formData.append("profile_pic", file);
|
||||||
formData.append("first_name", username);
|
formData.append("first_name", firstName);
|
||||||
formData.append("about", about);
|
formData.append("about", about);
|
||||||
|
|
||||||
ApiUpdateUserProfile(formData);
|
ApiUpdateUserProfile(formData);
|
||||||
@ -45,12 +62,19 @@ export function ProfileUpdateComponent() {
|
|||||||
ref={fileInputRef}
|
ref={fileInputRef}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div className="avatar w-32 h-32 cursor-pointer hover:blur" onClick={handleImageUpload}>
|
<div
|
||||||
|
className="avatar w-32 h-32 cursor-pointer hover:blur"
|
||||||
|
onClick={handleImageUpload}
|
||||||
|
>
|
||||||
{file ? (
|
{file ? (
|
||||||
<img src={URL.createObjectURL(file)} alt="Profile" className="rounded-full" />
|
<img
|
||||||
|
src={URL.createObjectURL(file)}
|
||||||
|
alt="Profile"
|
||||||
|
className="rounded-full"
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<img src={defaultImage} alt="Default" className="rounded-full" />
|
<img src={profile_pic} alt="Default" className="rounded-full" />
|
||||||
<i className="fas fa-camera text-white text-2xl absolute bottom-0 right-0 mr-2 mb-2"></i>
|
<i className="fas fa-camera text-white text-2xl absolute bottom-0 right-0 mr-2 mb-2"></i>
|
||||||
<i className="fas fa-arrow-up text-white text-2xl absolute top-0 right-0 mr-2 mt-2"></i>
|
<i className="fas fa-arrow-up text-white text-2xl absolute top-0 right-0 mr-2 mt-2"></i>
|
||||||
</>
|
</>
|
||||||
@ -58,7 +82,7 @@ export function ProfileUpdateComponent() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Username Field */}
|
{/* Username Field
|
||||||
<div className="w-96">
|
<div className="w-96">
|
||||||
<label className="block mb-2 text-gray-600">Username</label>
|
<label className="block mb-2 text-gray-600">Username</label>
|
||||||
<input
|
<input
|
||||||
@ -68,16 +92,16 @@ export function ProfileUpdateComponent() {
|
|||||||
value={username}
|
value={username}
|
||||||
onChange={(e) => setUsername(e.target.value)}
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
{/* Full Name Field */}
|
{/* Full Name Field */}
|
||||||
<div className="w-96">
|
<div className="w-96">
|
||||||
<label className="block mb-2 text-gray-600">Full Name</label>
|
<label className="block mb-2 text-gray-600">First Name</label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Enter your full name"
|
placeholder="Enter your first name"
|
||||||
className="input w-full"
|
className="input w-full"
|
||||||
value={fullName}
|
value={firstName}
|
||||||
onChange={(e) => setFullName(e.target.value)}
|
onChange={(e) => setFullName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,36 +1,63 @@
|
|||||||
import { ProfileUpdateComponent } from "./ProfileUpdateComponent";
|
import { ProfileUpdateComponent } from "./ProfileUpdateComponent";
|
||||||
|
import { axiosInstance } from "src/api/AxiosConfig";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export function ProfileUpdatePage() {
|
export function ProfileUpdatePage() {
|
||||||
|
const [profile_pic, setProfilePic] = useState(undefined);
|
||||||
|
const [about, setAbout] = useState();
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUser = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axiosInstance.get("/user/data/");
|
||||||
|
const fetchedProfilePic = response.data.profile_pic;
|
||||||
|
const fetchedAbout = response.data.about;
|
||||||
|
setProfilePic(fetchedProfilePic);
|
||||||
|
setAbout(fetchedAbout);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching user:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchUser();
|
||||||
|
}, []);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="stats shadow mt-3">
|
<div className="stats shadow mt-3">
|
||||||
<div className="stat">
|
<div className="stat">
|
||||||
<div className="stat-title truncate">Username</div>
|
<div className="stat-title truncate">Firstname</div>
|
||||||
<div className="stat-value truncate">Sirin</div>
|
<div className="stat-value truncate">Sirin</div>
|
||||||
<div className="stat-desc truncate">User ID</div>
|
{/* <div className="stat-desc truncate">User ID</div> */}
|
||||||
<div className="stat-figure text-secondary">
|
<div className="stat-figure text-secondary">
|
||||||
<div className="avatar online">
|
<div className="avatar online">
|
||||||
<div className="w-20 rounded-full">
|
<div className="w-20 rounded-full">
|
||||||
<img src="https://us-tuna-sounds-images.voicemod.net/f322631f-689a-43ac-81ab-17a70f27c443-1692187175560.png" />
|
<img src={profile_pic} alt="Profile Picture" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="stat">
|
{/* <div className="stat">
|
||||||
<div className="stat-title">Health</div>
|
<div className="stat-title">Health</div>
|
||||||
<div className="stat-value flex truncate">
|
<div className="stat-value flex truncate">
|
||||||
234/3213
|
234/3213
|
||||||
<div className="stat-figure text-secondary px-2">
|
<div className="stat-figure text-secondary px-2">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="red" viewBox="0 0 24 24" className="inline-block w-8 h-8">
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="red"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
className="inline-block w-8 h-8"
|
||||||
|
>
|
||||||
<path d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0"></path>
|
<path d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="stat-desc py-2">32% Remain</div>
|
<div className="stat-desc py-2">32% Remain</div>
|
||||||
<progress className="progress progress-error w-56" value={20} max="100"></progress>
|
<progress
|
||||||
</div>
|
className="progress progress-error w-56"
|
||||||
|
value={20}
|
||||||
|
max="100"
|
||||||
|
></progress>
|
||||||
|
</div> */}
|
||||||
|
{/*
|
||||||
<div className="stat">
|
<div className="stat">
|
||||||
<div className="stat-title truncate">Level</div>
|
<div className="stat-title truncate">Level</div>
|
||||||
<div className="stat-value flex">
|
<div className="stat-value flex">
|
||||||
@ -40,13 +67,18 @@ export function ProfileUpdatePage() {
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="#3abff8"
|
fill="#3abff8"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
className="inline-block w-8 h-8">
|
className="inline-block w-8 h-8"
|
||||||
|
>
|
||||||
<path d="M13 10V3L4 14h7v7l9-11h-7z"></path>
|
<path d="M13 10V3L4 14h7v7l9-11h-7z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="stat-desc py-2">3213/321312321 points</div>
|
<div className="stat-desc py-2">3213/321312321 points</div>
|
||||||
<progress className="progress progress-info w-36" value="10" max="100"></progress>
|
<progress
|
||||||
|
className="progress progress-info w-36"
|
||||||
|
value="10"
|
||||||
|
max="100"
|
||||||
|
></progress>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="stat">
|
<div className="stat">
|
||||||
@ -58,34 +90,43 @@ export function ProfileUpdatePage() {
|
|||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="none"
|
fill="none"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
className="inline-block w-8 h-8 stroke-current">
|
className="inline-block w-8 h-8 stroke-current"
|
||||||
|
>
|
||||||
<path
|
<path
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
strokeWidth="2"
|
strokeWidth="2"
|
||||||
stroke="gold"
|
stroke="gold"
|
||||||
d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"></path>
|
d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"
|
||||||
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="stat-desc py-2">Top 12% of Global Ranking</div>
|
<div className="stat-desc py-2">Top 12% of Global Ranking</div>
|
||||||
<progress className="progress progress-warning w-56" value={20} max="100"></progress>
|
<progress
|
||||||
</div>
|
className="progress progress-warning w-56"
|
||||||
|
value={20}
|
||||||
|
max="100"
|
||||||
|
></progress>
|
||||||
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="card bg-base-100 shadow">
|
<div className="card bg-base-100 shadow">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h2 className="card-title">About me</h2>
|
<h2 className="card-title">About me</h2>
|
||||||
<div className="card-actions justify-end"></div>
|
<div className="card-actions justify-end"></div>
|
||||||
<textarea className="textarea textarea-bordered textarea-lg w-full" disabled>
|
<textarea
|
||||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum dolores recusandae, officiis consequuntur
|
className="textarea textarea-bordered textarea-lg w-full"
|
||||||
nam, non ab commodi totam mollitia iusto nemo voluptatum error aliquam similique perspiciatis, eligendi
|
disabled
|
||||||
nulla. Animi, sit?
|
placeholder="Enter your about me"
|
||||||
|
>
|
||||||
|
{about}
|
||||||
</textarea>
|
</textarea>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 grid-rows-2 gap-4 my-2">
|
{/* <div className="grid grid-cols-2 grid-rows-2 gap-4 my-2">
|
||||||
<div className="col-span-full">
|
<div className="col-span-full">
|
||||||
<div className="card bg-base-100 shadow">
|
<div className="card bg-base-100 shadow">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
@ -110,18 +151,21 @@ export function ProfileUpdatePage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="fixed bottom-4 right-4">
|
<div className="fixed bottom-4 right-4">
|
||||||
<ul className="menu menu-horizontal bg-base-200 rounded-box">
|
<ul className="menu menu-horizontal bg-base-200 rounded-box">
|
||||||
<li>
|
<li>
|
||||||
<a onClick={() => document.getElementById("my_modal_4").showModal()}>
|
<a
|
||||||
|
onClick={() => document.getElementById("my_modal_4").showModal()}
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
className="h-5 w-5"
|
className="h-5 w-5"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
viewBox="0 0 16 16"
|
viewBox="0 0 16 16"
|
||||||
stroke="currentColor">
|
stroke="currentColor"
|
||||||
|
>
|
||||||
<path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z" />
|
<path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z" />
|
||||||
</svg>
|
</svg>
|
||||||
<p className="text-xl font-bold">Edit</p>
|
<p className="text-xl font-bold">Edit</p>
|
||||||
@ -135,7 +179,9 @@ export function ProfileUpdatePage() {
|
|||||||
<div className="modal-box w-11/12 max-w-5xl flex flex-col">
|
<div className="modal-box w-11/12 max-w-5xl flex flex-col">
|
||||||
<form method="dialog">
|
<form method="dialog">
|
||||||
<ProfileUpdateComponent />
|
<ProfileUpdateComponent />
|
||||||
<button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
|
<button className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user