Skip to content

Commit

Permalink
Merge pull request #974 from SirhmVFX/feat/implement-view-current-pro…
Browse files Browse the repository at this point in the history
…file-information-and-picture-in-input-fields

Feat/implement view current profile information and picture in input fields
  • Loading branch information
incredible-phoenix246 authored Aug 15, 2024
2 parents 54d364e + 5e71ca0 commit 85ee908
Show file tree
Hide file tree
Showing 13 changed files with 664 additions and 80 deletions.
Binary file added public/images/pfp.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/app/(auth-routes)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const Login = () => {

if (data.status === 200) {
setUserOrg(data.organisations);
if (!currentOrgId) {
if (!currentOrgId && data.organisations.length > 0) {
setCurrentOrgId(data.organisations[0].organisation_id);
}
await signIn(
Expand Down
10 changes: 1 addition & 9 deletions src/app/(auth-routes)/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Eye, EyeOff } from "lucide-react";
import { signIn, useSession } from "next-auth/react";
import { useRouter } from "next-nprogress-bar";
import Link from "next/link";
import { useEffect, useState, useTransition } from "react";
import { useState, useTransition } from "react";
import { useForm } from "react-hook-form";
import * as z from "zod";

Expand Down Expand Up @@ -48,14 +48,6 @@ const Register = () => {
const [timeLeft, setTimeLeft] = useState<number>(15 * 60);
const [value, setValue] = useState("");

useEffect(() => {
if (timeLeft <= 0) return;
const timerId = setInterval(() => {
setTimeLeft((previousTime) => previousTime - 1);
}, 1000);
return () => clearInterval(timerId);
}, [timeLeft, showOtp]);

if (status === "authenticated") {
router.push("/dashboard");
}
Expand Down
27 changes: 5 additions & 22 deletions src/app/dashboard/(admin)/admin/(settings)/settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export default function SettingsPage() {
},
});
if (response.data?.data) {
//console.log("Fetched profile data:", response.data.data);
const { avatar_url, profile_pic_url } = response.data.data;
setPronoun(response.data.data.pronouns);
setSocialLinks({
Expand All @@ -106,10 +107,10 @@ export default function SettingsPage() {
setIsSuccess(true);
}
} catch {
setError("An error occurred while retreiving your informatio");
setError("An error occurred while retrieving your information");
}
})();
}, [data?.access_token, data?.user.id, error]);
}, [data?.access_token, data?.user.id]);

const handleImageUpload = async (event: ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
Expand Down Expand Up @@ -174,14 +175,8 @@ export default function SettingsPage() {
profile_pic_url: profilePicture,
};
setIsPending(true);
const baseUrl = await getApiUrl();
const API_URL = `${baseUrl}/api/v1/profile/${data?.user.id}`;

await axios.patch(API_URL, payload, {
headers: {
Authorization: `Bearer ${data?.access_token}`,
},
});
// const baseUrl = await getApiUrl();
// const API_URL = `${baseUrl}/api/v1/profile/${data?.user.id}`;

const updatedUser = {
...data?.user,
Expand Down Expand Up @@ -209,17 +204,6 @@ export default function SettingsPage() {
}
};

const isFormDisabled = !(
formData.bio &&
formData.department &&
formData.jobTitle &&
formData.username &&
socialLinks.instagram &&
socialLinks.linkedin &&
socialLinks.x &&
pronoun
);

return (
<div className="min-h-screen w-full max-w-[826px] bg-white p-[32px]">
<header className="mb-[24px]">
Expand Down Expand Up @@ -384,7 +368,6 @@ export default function SettingsPage() {
</CustomButton>
<CustomButton
isLoading={isPending}
isDisabled={isFormDisabled}
onClick={submit}
size="lg"
className="bg-primary"
Expand Down
10 changes: 8 additions & 2 deletions src/app/dashboard/(user-dashboard)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Suspense } from "react";

import Providers from "~/components/providers";
import SettingsSidebar from "../(admin)/admin/(settings)/settings/_components/layout/sidebar";
import UserNavbar from "./_components/layout/navbar";

export default function AdminLayout({
Expand All @@ -12,8 +13,13 @@ export default function AdminLayout({
<div className="grid min-h-screen w-full grid-rows-[auto_1fr]">
<Providers />
<UserNavbar />
<div className="relative mx-auto w-full bg-white px-2 max-lg:overflow-hidden xl:px-4">
<Suspense>{children}</Suspense>
<div className="relative mx-auto w-full bg-white max-lg:overflow-hidden xl:px-4">
<div className="flex">
<SettingsSidebar />
<div className="w-full p-4">
<Suspense>{children}</Suspense>
</div>
</div>{" "}
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
"use client";

import axios from "axios";
import Image from "next/image";
import { useState } from "react";

import defaultProfilePic from "~/../public/images/pfp.jpg";
import { getApiUrl } from "~/actions/getApiUrl";
import CustomButton from "~/components/common/common-button/common-button";
import { toast } from "~/components/ui/use-toast";
import { CloudinaryAsset } from "~/types";

interface ProfilePictureModalProperties {
show: boolean;
onClose: () => void;
email: string;
accessToken: string;
profilePic: string;
onUploadSuccess: (url: string | undefined) => void;
}

export default function ProfilePictureModal({
show,
onClose,
email,
accessToken,
onUploadSuccess,
profilePic,
}: ProfilePictureModalProperties) {
const [image, setImage] = useState<File | Blob | undefined>();
const [isPending, setIsPending] = useState(false);

const uploadProfilePicture = async () => {
if (!image) return;

try {
const formData = new FormData();
formData.append("file", image);
formData.append("DisplayPhoto", image);
formData.append("upload_preset", "starterhouse");
formData.append("api_key", "673723355315667");

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

const data: CloudinaryAsset = await response.json();
const profilePictureUrl = data.url;

const API_URL = `${await getApiUrl()}/api/v1/profile/${email}/picture`;

setIsPending(true);

await axios.put(
API_URL,
{ DisplayPhoto: profilePictureUrl, Email: email },
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
);

toast({
title: "Success!",
description: "Profile picture updated successfully",
});

onUploadSuccess(profilePictureUrl);
onClose();
} catch {
toast({
title: "Error",
description: "Failed to upload profile picture. Please try again.",
});
} finally {
setIsPending(false);
}
};

const deleteProfilePicture = async () => {
try {
const API_URL = `${await getApiUrl()}/api/v1/profile/${email}/picture`;

await axios.delete(API_URL, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});

toast({
title: "Success!",
description: "Profile picture deleted successfully",
});

// onUploadSuccess();
onClose();
} catch {
toast({
title: "Error",
description: "Failed to delete profile picture. Please try again.",
});
}
};

if (!show) return;

return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50">
<div className="w-full max-w-md rounded-lg bg-white p-8">
<h2 className="mb-4 text-lg font-bold">Update Profile Picture</h2>
<div className="mb-4 flex items-center justify-center">
<div className="h-[200px] w-[200px]">
{image ? (
<Image
src={URL.createObjectURL(image)}
alt="Profile Picture Preview"
width={200}
height={200}
className="h-full w-full rounded-full object-cover"
/>
) : (
<Image
src={profilePic || defaultProfilePic.src}
alt="Default Profile Picture"
width={200}
height={200}
className="h-full w-full rounded-full object-cover"
/>
)}
</div>
</div>
<input
type="file"
name="DisplayPhoto"
onChange={(entries) =>
setImage(entries.target.files ? entries.target.files[0] : undefined)
}
className="mb-4"
/>
<div className="flex justify-between">
<CustomButton onClick={deleteProfilePicture} variant="outline">
Delete Picture
</CustomButton>
<div className="flex gap-4">
<CustomButton onClick={onClose} variant="outline">
Cancel
</CustomButton>
<CustomButton
onClick={uploadProfilePicture}
isLoading={isPending}
className="bg-primary"
>
Upload Picture
</CustomButton>
</div>
</div>
</div>
</div>
);
}
59 changes: 59 additions & 0 deletions src/app/dashboard/(user-dashboard)/settings/general/icons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export const XIcon = ({ className }: { className?: string }) => {
return (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
width="14"
height="14"
viewBox="0 0 16 16"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.04202 0H0L5.97809 8.70097L0.38242 16H2.96778L7.19998 10.4795L10.958 15.9493H16L9.84822 6.99546L9.85911 7.01091L15.1559 0.101644H12.5705L8.63704 5.23256L5.04202 0ZM2.78311 1.52382H4.35275L13.2169 14.4254H11.6472L2.78311 1.52382Z"
fill="black"
/>
</svg>
);
};

export const InstagramIcon = ({ className }: { className?: string }) => {
return (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 20 20"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10 0C7.284 0 6.944 0.0119999 5.877 0.0599999C4.813 0.109 4.086 0.278 3.45 0.525C2.78247 0.775816 2.17773 1.16931 1.678 1.678C1.16931 2.17773 0.775816 2.78247 0.525 3.45C0.278 4.086 0.109 4.813 0.0599999 5.877C0.0109999 6.944 0 7.284 0 10C0 12.716 0.0109999 13.056 0.0599999 14.123C0.109 15.187 0.278 15.914 0.525 16.55C0.775816 17.2175 1.16931 17.8223 1.678 18.322C2.17773 18.8307 2.78247 19.2242 3.45 19.475C4.086 19.722 4.813 19.891 5.877 19.94C6.944 19.988 7.284 20 10 20C12.716 20 13.056 19.988 14.123 19.94C15.187 19.891 15.914 19.722 16.55 19.475C17.2175 19.2242 17.8223 18.8307 18.322 18.322C18.8307 17.8223 19.2242 17.2175 19.475 16.55C19.722 15.914 19.891 15.187 19.94 14.123C19.988 13.056 20 12.716 20 10C20 7.284 19.988 6.944 19.94 5.877C19.891 4.813 19.722 4.086 19.475 3.45C19.2242 2.78247 18.8307 2.17773 18.322 1.678C17.8223 1.16931 17.2175 0.775816 16.55 0.525C15.914 0.278 15.187 0.109 14.123 0.0599999C13.056 0.0119999 12.716 0 10 0ZM10 1.802C12.67 1.802 12.986 1.812 14.04 1.86C15.016 1.905 15.545 2.067 15.898 2.204C16.364 2.386 16.698 2.603 17.048 2.952C17.398 3.302 17.614 3.636 17.796 4.102C17.932 4.455 18.096 4.984 18.14 5.959C18.188 7.014 18.198 7.329 18.198 10C18.198 12.67 18.188 12.986 18.14 14.04C18.095 15.016 17.932 15.545 17.796 15.898C17.6357 16.3324 17.3801 16.7253 17.048 17.048C16.698 17.398 16.364 17.614 15.898 17.796C15.545 17.932 15.016 18.096 14.041 18.14C12.987 18.188 12.671 18.198 10 18.198C7.33 18.198 7.013 18.188 5.96 18.14C4.984 18.095 4.455 17.932 4.102 17.796C3.66762 17.6357 3.27466 17.3801 2.952 17.048C2.61991 16.7253 2.36432 16.3324 2.204 15.898C2.067 15.545 1.904 15.016 1.86 14.041C1.812 12.986 1.802 12.671 1.802 10C1.802 7.33 1.812 7.014 1.86 5.96C1.905 4.984 2.067 4.455 2.204 4.102C2.386 3.636 2.603 3.302 2.952 2.952C3.302 2.602 3.636 2.386 4.102 2.204C4.455 2.067 4.984 1.904 5.959 1.86C7.014 1.812 7.329 1.802 10 1.802ZM10 13.333C9.11603 13.333 8.26827 12.9818 7.64321 12.3568C7.01815 11.7317 6.667 10.884 6.667 10C6.667 9.11603 7.01815 8.26827 7.64321 7.64321C8.26827 7.01815 9.11603 6.667 10 6.667C10.884 6.667 11.7317 7.01815 12.3568 7.64321C12.9818 8.26827 13.333 9.11603 13.333 10C13.333 10.884 12.9818 11.7317 12.3568 12.3568C11.7317 12.9818 10.884 13.333 10 13.333ZM10 4.865C9.32566 4.865 8.65793 4.99782 8.03492 5.25588C7.41191 5.51394 6.84584 5.89218 6.36901 6.36901C5.89218 6.84584 5.51394 7.41191 5.25588 8.03492C4.99782 8.65793 4.865 9.32566 4.865 10C4.865 10.6743 4.99782 11.3421 5.25588 11.9651C5.51394 12.5881 5.89218 13.1542 6.36901 13.631C6.84584 14.1078 7.41191 14.4861 8.03492 14.7441C8.65793 15.0022 9.32566 15.135 10 15.135C11.3619 15.135 12.668 14.594 13.631 13.631C14.594 12.668 15.135 11.3619 15.135 10C15.135 8.63811 14.594 7.33201 13.631 6.36901C12.668 5.40601 11.3619 4.865 10 4.865ZM16.538 4.662C16.538 4.81959 16.507 4.97563 16.4467 5.12122C16.3863 5.26681 16.298 5.3991 16.1865 5.51053C16.0751 5.62196 15.9428 5.71035 15.7972 5.77066C15.6516 5.83096 15.4956 5.862 15.338 5.862C15.1804 5.862 15.0244 5.83096 14.8788 5.77066C14.7332 5.71035 14.6009 5.62196 14.4895 5.51053C14.378 5.3991 14.2897 5.26681 14.2293 5.12122C14.169 4.97563 14.138 4.81959 14.138 4.662C14.138 4.34374 14.2644 4.03852 14.4895 3.81347C14.7145 3.58843 15.0197 3.462 15.338 3.462C15.6563 3.462 15.9615 3.58843 16.1865 3.81347C16.4116 4.03852 16.538 4.34374 16.538 4.662Z"
fill="black"
/>
</svg>
);
};

export const LinkedinIcon = ({ className }: { className?: string }) => {
return (
<svg
className={className}
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 21 21"
fill="none"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M3 0.25C2.27065 0.25 1.57118 0.539731 1.05546 1.05546C0.539731 1.57118 0.25 2.27065 0.25 3C0.25 3.72935 0.539731 4.42882 1.05546 4.94454C1.57118 5.46027 2.27065 5.75 3 5.75C3.72935 5.75 4.42882 5.46027 4.94454 4.94454C5.46027 4.42882 5.75 3.72935 5.75 3C5.75 2.27065 5.46027 1.57118 4.94454 1.05546C4.42882 0.539731 3.72935 0.25 3 0.25ZM1.75 3C1.75 2.66848 1.8817 2.35054 2.11612 2.11612C2.35054 1.8817 2.66848 1.75 3 1.75C3.33152 1.75 3.64946 1.8817 3.88388 2.11612C4.1183 2.35054 4.25 2.66848 4.25 3C4.25 3.33152 4.1183 3.64946 3.88388 3.88388C3.64946 4.1183 3.33152 4.25 3 4.25C2.66848 4.25 2.35054 4.1183 2.11612 3.88388C1.8817 3.64946 1.75 3.33152 1.75 3ZM0.25 7C0.25 6.80109 0.329018 6.61032 0.46967 6.46967C0.610322 6.32902 0.801088 6.25 1 6.25H5C5.19891 6.25 5.38968 6.32902 5.53033 6.46967C5.67098 6.61032 5.75 6.80109 5.75 7V20C5.75 20.1989 5.67098 20.3897 5.53033 20.5303C5.38968 20.671 5.19891 20.75 5 20.75H1C0.801088 20.75 0.610322 20.671 0.46967 20.5303C0.329018 20.3897 0.25 20.1989 0.25 20V7ZM1.75 7.75V19.25H4.25V7.75H1.75ZM7.25 7C7.25 6.80109 7.32902 6.61032 7.46967 6.46967C7.61032 6.32902 7.80109 6.25 8 6.25H12C12.1989 6.25 12.3897 6.32902 12.5303 6.46967C12.671 6.61032 12.75 6.80109 12.75 7V7.434L13.185 7.247C13.9351 6.9266 14.7307 6.72583 15.543 6.652C18.318 6.4 20.75 8.58 20.75 11.38V20C20.75 20.1989 20.671 20.3897 20.5303 20.5303C20.3897 20.671 20.1989 20.75 20 20.75H16C15.8011 20.75 15.6103 20.671 15.4697 20.5303C15.329 20.3897 15.25 20.1989 15.25 20V13C15.25 12.6685 15.1183 12.3505 14.8839 12.1161C14.6495 11.8817 14.3315 11.75 14 11.75C13.6685 11.75 13.3505 11.8817 13.1161 12.1161C12.8817 12.3505 12.75 12.6685 12.75 13V20C12.75 20.1989 12.671 20.3897 12.5303 20.5303C12.3897 20.671 12.1989 20.75 12 20.75H8C7.80109 20.75 7.61032 20.671 7.46967 20.5303C7.32902 20.3897 7.25 20.1989 7.25 20V7ZM8.75 7.75V19.25H11.25V13C11.25 12.2707 11.5397 11.5712 12.0555 11.0555C12.5712 10.5397 13.2707 10.25 14 10.25C14.7293 10.25 15.4288 10.5397 15.9445 11.0555C16.4603 11.5712 16.75 12.2707 16.75 13V19.25H19.25V11.38C19.25 9.476 17.589 7.972 15.68 8.146C15.0241 8.2055 14.3817 8.36747 13.776 8.626L12.296 9.261C12.1818 9.31003 12.0573 9.32994 11.9336 9.31893C11.8098 9.30793 11.6907 9.26635 11.587 9.19794C11.4833 9.12953 11.3982 9.03643 11.3394 8.927C11.2806 8.81757 11.2499 8.69524 11.25 8.571V7.75H8.75Z"
fill="black"
/>
</svg>
);
};
Loading

0 comments on commit 85ee908

Please sign in to comment.