mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-05 00:32:03 +00:00
Basic layout for profile card mobile
This commit is contained in:
parent
c04a42eeb7
commit
600ddadbb4
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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} />
|
||||
) : (
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user