Basic layout for profile card mobile

This commit is contained in:
austinkelsay 2024-12-17 17:41:14 -06:00
parent c04a42eeb7
commit 600ddadbb4
No known key found for this signature in database
GPG Key ID: 44CB4EC6D9F2FA02
7 changed files with 134 additions and 38 deletions

View File

@ -157,7 +157,7 @@ const ActivityContributionChart = ({ session }) => {
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
return (
<div className="w-full mx-2 bg-gray-800 rounded-lg border border-gray-700 shadow-md">
<div className="w-full mx-2 bg-gray-800 rounded-lg border border-gray-700 shadow-md h-[330px] max-lap:mx-0 max-lap:mt-2">
<div className="flex flex-row justify-between items-center p-4">
<h1 className="text-2xl font-bold text-gray-200">Activity</h1>
<i className="pi pi-question-circle text-2xl cursor-pointer text-gray-200"

View File

@ -181,7 +181,7 @@ const CombinedContributionChart = ({ session }) => {
}, [calendar]);
return (
<div className="w-full mx-2 bg-gray-800 rounded-lg border border-gray-700 shadow-md">
<div className="w-full mx-2 bg-gray-800 rounded-lg border border-gray-700 shadow-md h-[330px] max-lap:mx-0 max-lap:mt-2">
<div className="flex flex-row justify-between items-center p-4">
<h1 className="text-2xl font-bold text-gray-200">Activity</h1>
<i className="pi pi-question-circle text-2xl cursor-pointer text-gray-200"

View File

@ -1,12 +1,13 @@
import React from "react";
import { DataTable } from "primereact/datatable";
import { Column } from "primereact/column";
import { classNames } from "primereact/utils";
import useWindowWidth from "@/hooks/useWindowWidth";
import ProgressListItem from "@/components/content/lists/ProgressListItem";
import { formatDateTime } from "@/utils/time";
import { ProgressSpinner } from "primereact/progressspinner";
const UserProgressTable = ({ session, ndk, windowWidth }) => {
const UserProgressTable = ({ session, ndk }) => {
const windowWidth = useWindowWidth();
const prepareProgressData = () => {
if (!session?.user?.userCourses) return [];
@ -129,7 +130,8 @@ const UserProgressTable = ({ session, ndk, windowWidth }) => {
emptyMessage="No Courses or Milestones completed"
value={prepareProgressData()}
header={header}
style={{ margin: 8, width: "100%", borderRadius: "8px", border: "1px solid #333", boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.1)" }}
className="m-2 max-lap:m-0"
style={{ width: "100%", borderRadius: "8px", border: "1px solid #333", boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.1)" }}
pt={{
wrapper: {
className: "rounded-b-lg shadow-md"

View File

@ -53,7 +53,8 @@ const UserPurchaseTable = ({ session, windowWidth }) => {
emptyMessage="No purchases"
value={session.user?.purchased}
header={purchasesHeader}
style={{ margin: 8, width: "100%", borderRadius: "8px", border: "1px solid #333", boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.1)" }}
className="m-2 max-lap:m-0"
style={{ width: "100%", borderRadius: "8px", border: "1px solid #333", boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.1)" }}
pt={{
wrapper: {
className: "rounded-b-lg shadow-md"

View File

@ -37,10 +37,9 @@ const UserProfile = () => {
<h1 className="text-3xl font-bold mb-6">Profile</h1>
)
}
<div className="w-full flex flex-row">
<div className="w-full flex flex-row max-lap:flex-col">
<UserProfileCard user={user} />
<div className="w-full flex flex-col justify-center mx-auto">
{account && account?.provider === "github" ? (
<CombinedContributionChart session={session} />
) : (

View File

@ -1,15 +1,20 @@
import React, { useRef } from 'react';
import React, { useRef, useState } from 'react';
import Image from 'next/image';
import { Menu } from 'primereact/menu';
import { Tooltip } from 'primereact/tooltip';
import { nip19 } from 'nostr-tools';
import { useImageProxy } from '@/hooks/useImageProxy';
import { useToast } from '@/hooks/useToast';
import UserBadges from '@/components/profile/UserBadges';
import useWindowWidth from '@/hooks/useWindowWidth';
const UserProfileCard = ({ user }) => {
const [showBadges, setShowBadges] = useState(false);
const menu = useRef(null);
const { showToast } = useToast();
const { returnImageProxy } = useImageProxy();
const windowWidth = useWindowWidth();
const copyToClipboard = (text) => {
navigator.clipboard.writeText(text);
showToast("success", "Copied", "Copied to clipboard");
@ -40,9 +45,96 @@ const UserProfileCard = ({ user }) => {
}
];
return (
<div className="lg:w-1/4 bg-gray-800 rounded-lg p-4 border border-gray-700 shadow-md">
<div className="flex flex-row gap-4">
const MobileProfileCard = () => (
<div className="w-full bg-gray-800 rounded-lg p-2 py-1 border border-gray-700 shadow-md h-[330px] flex flex-col justify-center">
<div className="flex flex-col gap-2 pt-4 w-full relative">
<div className="absolute top-8 right-[10px]">
<i
className="pi pi-ellipsis-h text-2xl cursor-pointer"
onClick={(e) => menu.current.toggle(e)}
/>
<Menu
model={menuItems}
popup
ref={menu}
id="profile-options-menu"
/>
</div>
</div>
<Image
alt="user's avatar"
src={returnImageProxy(user.avatar, user?.pubkey || "")}
width={100}
height={100}
className="rounded-full mt-2 mx-auto"
/>
<h3 className="text-center">
{user.username || user?.name || user?.email || "Anon"}
</h3>
<div className="flex flex-col gap-2 justify-center">
{
user?.pubkey && (
<div className="flex flex-row gap-2 justify-center">
<p className="truncate">
{nip19.npubEncode(user.pubkey)}
</p>
<Tooltip target=".pubkey-tooltip" content={"this is your account pubkey"} />
<i className="pi pi-question-circle pubkey-tooltip text-xs cursor-pointer" />
</div>
)
}
{user?.createdAt && (
<p className="truncate text-center">
Joined: {new Date(user.createdAt).toLocaleDateString()}
</p>
)}
</div>
<div className='w-full flex flex-row justify-between'>
<div className="flex flex-col justify-between gap-4 my-2">
{user?.lightningAddress ? (
<h4 className="bg-gray-900 rounded-lg p-3 max-lap:w-fit min-w-[240px]">
<span className="font-bold">Lightning Address:</span> {user.lightningAddress.name}@plebdevs.com <i className="pi pi-copy cursor-pointer hover:text-gray-400" onClick={() => copyToClipboard(user.lightningAddress.name + "@plebdevs.com")} />
</h4>
) : (
<div className="flex flex-row justify-between bg-gray-900 rounded-lg p-3 max-lap:w-fit min-w-[240px]">
<h4 >
<span className="font-bold">Lightning Address:</span> None
</h4>
{/* todo: add tooltip */}
<Tooltip target=".lightning-address-tooltip" content={"this is your account lightning address"} />
<i className="pi pi-question-circle lightning-address-tooltip text-xs cursor-pointer" />
</div>
)}
{user?.nip05 ? (
<h4 className="bg-gray-900 rounded-lg p-3 max-lap:w-fit min-w-[240px]">
<span className="font-bold">NIP-05:</span> {user.nip05.name}@plebdevs.com <i className="pi pi-copy cursor-pointer hover:text-gray-400" onClick={() => copyToClipboard(user.nip05.name + "@plebdevs.com")} />
</h4>
) : (
<div className="flex flex-row justify-between bg-gray-900 rounded-lg p-3 max-lap:w-fit min-w-[240px]">
<h4>
<span className="font-bold">NIP-05:</span> None
</h4>
{/* todo: add tooltip */}
<Tooltip target=".nip05-tooltip" content={"this is your account nip05"} />
<i className="pi pi-question-circle nip05-tooltip text-xs cursor-pointer" />
</div>
)}
</div>
<div className="flex flex-col justify-center min-w-[140px] px-2">
<button
className="w-full py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-full font-semibold"
onClick={() => setShowBadges(true)}
>
View Badges
</button>
</div>
</div>
</div>
);
const DesktopProfileCard = () => (
<div className="w-1/4 bg-gray-800 rounded-lg p-2 py-1 border border-gray-700 shadow-md h-[330px]">
<div className="flex flex-row w-full justify-around">
<Image
alt="user's avatar"
src={returnImageProxy(user.avatar, user?.pubkey || "")}
@ -50,9 +142,8 @@ const UserProfileCard = ({ user }) => {
height={100}
className="rounded-full my-4"
/>
<div className="flex flex-col gap-2 pt-4 w-full relative">
<div className="absolute top-0 right-0">
<div className="flex flex-col gap-2 pt-4 w-fit relative">
<div className="absolute top-[-4px] right-[-10px]">
<i
className="pi pi-ellipsis-h text-2xl cursor-pointer"
onClick={(e) => menu.current.toggle(e)}
@ -85,13 +176,13 @@ const UserProfileCard = ({ user }) => {
)}
</div>
</div>
<div className="flex flex-col gap-2">
<div className="flex flex-col justify-between gap-4 my-2">
{user?.lightningAddress ? (
<h4 className="my-2 bg-gray-900 rounded-lg p-4">
<h4 className="bg-gray-900 rounded-lg p-3 max-lap:w-fit min-w-[240px]">
<span className="font-bold">Lightning Address:</span> {user.lightningAddress.name}@plebdevs.com <i className="pi pi-copy cursor-pointer hover:text-gray-400" onClick={() => copyToClipboard(user.lightningAddress.name + "@plebdevs.com")} />
</h4>
) : (
<div className="flex flex-row justify-between my-2 bg-gray-900 rounded-lg p-4">
<div className="flex flex-row justify-between bg-gray-900 rounded-lg p-3 max-lap:w-fit min-w-[240px]">
<h4 >
<span className="font-bold">Lightning Address:</span> None
</h4>
@ -101,11 +192,11 @@ const UserProfileCard = ({ user }) => {
</div>
)}
{user?.nip05 ? (
<h4 className="my-2 bg-gray-900 rounded-lg p-4">
<h4 className="bg-gray-900 rounded-lg p-3 max-lap:w-fit min-w-[240px]">
<span className="font-bold">NIP-05:</span> {user.nip05.name}@plebdevs.com <i className="pi pi-copy cursor-pointer hover:text-gray-400" onClick={() => copyToClipboard(user.nip05.name + "@plebdevs.com")} />
</h4>
) : (
<div className="flex flex-row justify-between my-2 bg-gray-900 rounded-lg p-4">
<div className="flex flex-row justify-between bg-gray-900 rounded-lg p-3 max-lap:w-fit min-w-[240px]">
<h4>
<span className="font-bold">NIP-05:</span> None
</h4>
@ -114,9 +205,26 @@ const UserProfileCard = ({ user }) => {
<i className="pi pi-question-circle nip05-tooltip text-xs cursor-pointer" />
</div>
)}
<button
className="w-full py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-full font-semibold max-lap:w-fit min-w-[140px]"
onClick={() => setShowBadges(true)}
>
View Badges
</button>
</div>
</div>
);
// 1440px is the max-lap breakpoint from tailwind config
return (
<>
{windowWidth <= 1440 ? <MobileProfileCard /> : <DesktopProfileCard />}
<UserBadges
visible={showBadges}
onHide={() => setShowBadges(false)}
/>
</>
);
};
export default UserProfileCard;

View File

@ -4,7 +4,6 @@ import { Accordion, AccordionTab } from 'primereact/accordion';
import { useSession, signIn, getSession } from 'next-auth/react';
import { useRouter } from 'next/router';
import GenericButton from '@/components/buttons/GenericButton';
import UserBadges from '@/components/profile/UserBadges';
import UserProgressFlow from './UserProgressFlow';
import { Tooltip } from 'primereact/tooltip';
@ -56,7 +55,6 @@ const UserProgress = () => {
const [expandedItems, setExpandedItems] = useState({});
const [completedCourses, setCompletedCourses] = useState([]);
const [tasks, setTasks] = useState([]);
const [showBadges, setShowBadges] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const router = useRouter();
@ -177,7 +175,7 @@ const UserProgress = () => {
};
return (
<div className="bg-gray-800 rounded-lg p-4 m-2 w-full border border-gray-700 shadow-md">
<div className="bg-gray-800 rounded-lg p-4 pb-0 m-2 w-full border border-gray-700 shadow-md max-lap:mx-0">
<div className="flex flex-row justify-between items-center">
<h1 className="text-3xl font-bold text-white mb-2">Dev Journey</h1>
<i className="pi pi-question-circle text-2xl cursor-pointer text-gray-200"
@ -209,8 +207,8 @@ const UserProgress = () => {
)}
</div>
<div className="flex gap-6 mb-6">
<div className="w-1/2">
<div className="flex max-sidebar:flex-col gap-6 mb-6">
<div className="w-1/2 max-sidebar:w-full">
<ul className="space-y-6 pt-2">
{tasks.map((task, index) => (
<li key={index}>
@ -291,7 +289,7 @@ const UserProgress = () => {
</ul>
</div>
<div className="w-1/2">
<div className="w-1/2 max-sidebar:w-full">
{isLoading ? (
<div className="h-[400px] bg-gray-800 rounded-3xl flex items-center justify-center">
<i className="pi pi-spin pi-spinner text-4xl text-gray-600"></i>
@ -301,18 +299,6 @@ const UserProgress = () => {
)}
</div>
</div>
<button
className="w-full py-3 bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-full font-semibold"
onClick={() => setShowBadges(true)}
>
View Badges
</button>
<UserBadges
visible={showBadges}
onHide={() => setShowBadges(false)}
/>
</div>
);
};