Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion app/(auth)/login/page.tsx
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure to aligned with the project designed and avoid using 3rd party or inlined SVG. For this SVG Back button,please sure the FontAwesome Chevron Left.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Link from "next/link";
import Image from "next/image";
import LoginForm from "@/app/components/auth/LoginForm";
import { Metadata } from "next";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronLeft } from "@fortawesome/free-solid-svg-icons";

export const metadata: Metadata = {
title: "Login - DevPulse",
Expand Down Expand Up @@ -63,7 +65,15 @@ export default async function Login(props: {
: undefined;

return (
<div className="min-h-screen flex bg-[#0a0a1a] text-white">
<div className="min-h-screen flex bg-[#0a0a1a] text-white relative">
<Link
href="/"
className="absolute top-5 left-5 sm:top-6 sm:left-6 z-40 inline-flex items-center gap-2 text-sm text-gray-400 hover:text-white transition-colors"
>
<FontAwesomeIcon icon={faChevronLeft} className="w-4 h-4" />
Back
</Link>

{/* Left Side - Visual / Branding */}
<div className="hidden lg:flex lg:w-1/2 relative flex-col justify-between p-12 md:p-16 xl:p-24 border-r border-white/5 bg-gradient-to-br from-[#0a0a1a] to-[#0a0a1a] overflow-hidden">
{/* Background elements */}
Expand Down
12 changes: 11 additions & 1 deletion app/(auth)/signup/page.tsx
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure to aligned with the project designed and avoid using 3rd party or inlined SVG. For this SVG Back button,please sure the FontAwesome Chevron Left.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import Link from "next/link";
import Image from "next/image";
import SignupForm from "@/app/components/auth/SignupForm";
import { Metadata } from "next";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronLeft } from "@fortawesome/free-solid-svg-icons";

export const metadata: Metadata = {
title: "Sign Up - DevPulse",
Expand Down Expand Up @@ -50,7 +52,15 @@ export default async function Signup(props: {
: undefined;

return (
<div className="min-h-screen flex bg-[#0a0a1a] text-white">
<div className="min-h-screen flex bg-[#0a0a1a] text-white relative">
<Link
href="/"
className="absolute top-5 left-5 sm:top-6 sm:left-6 z-40 inline-flex items-center gap-2 text-sm text-gray-400 hover:text-white transition-colors"
>
<FontAwesomeIcon icon={faChevronLeft} className="w-4 h-4" />
Back
</Link>

{/* Left Side - Visual / Branding */}
<div className="hidden lg:flex lg:w-1/2 relative flex-col justify-between p-12 md:p-16 xl:p-24 border-r border-white/5 bg-gradient-to-br from-[#0a0a1a] to-[#0a0a1a] overflow-hidden">
{/* Background elements */}
Expand Down
24 changes: 11 additions & 13 deletions app/(public)/join/[code]/JoinButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import { createClient } from "../../../lib/supabase/client";
import { useRouter } from "next/navigation";
import { toast } from "react-toastify";
import Link from "next/link";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faArrowRightToBracket,
faCheck,
faSpinner,
faUserPlus,
} from "@fortawesome/free-solid-svg-icons";

export default function JoinButton({
code,
Expand All @@ -26,9 +33,7 @@ export default function JoinButton({
href={`/leaderboard/${leaderboardSlug}`}
className="btn-primary inline-flex items-center justify-center gap-2 w-full py-4 text-sm font-bold rounded-xl shadow-lg shadow-indigo-500/20"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
<FontAwesomeIcon icon={faCheck} className="w-5 h-5" />
<span className="sm:hidden">View</span>
<span className="hidden sm:inline">View Leaderboard</span>
</Link>
Expand All @@ -42,9 +47,7 @@ export default function JoinButton({
href={`/login?redirect=${encodeURIComponent(`/join?id=${code}`)}`}
className="btn-primary inline-flex items-center justify-center gap-2 w-full py-4 text-sm font-bold rounded-xl shadow-lg shadow-indigo-500/20"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1" />
</svg>
<FontAwesomeIcon icon={faArrowRightToBracket} className="w-5 h-5" />
Log In to Join
</Link>
<p className="text-xs text-gray-500">
Expand Down Expand Up @@ -112,17 +115,12 @@ export default function JoinButton({
>
{joining ? (
<>
<svg className="w-5 h-5 animate-spin" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
</svg>
<FontAwesomeIcon icon={faSpinner} className="w-5 h-5 animate-spin" />
Joining...
</>
) : (
<>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z" />
</svg>
<FontAwesomeIcon icon={faUserPlus} className="w-5 h-5" />
Accept Invite &amp; Join
</>
)}
Expand Down
66 changes: 17 additions & 49 deletions app/(public)/join/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import JoinButton from "./[code]/JoinButton";
import Footer from "@/app/components/layout/Footer";
import Image from "next/image";
import Link from "next/link";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faCircleInfo,
faCircleXmark,
faRankingStar,
faUsers,
} from "@fortawesome/free-solid-svg-icons";

type Props = {
searchParams: Promise<{ id?: string }>;
Expand Down Expand Up @@ -82,19 +89,10 @@ export default async function JoinPage({ searchParams }: Props) {
<div className="min-h-screen flex items-center justify-center bg-[#0a0a1a] text-white grid-bg">
<div className="glass-card p-10 text-center max-w-md mx-auto">
<div className="w-16 h-16 rounded-full bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center mx-auto mb-5">
<svg
<FontAwesomeIcon
icon={faCircleInfo}
className="w-8 h-8 text-indigo-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
/>
</div>
<h1 className="text-xl font-bold text-white mb-2">
Join a Leaderboard
Expand All @@ -118,19 +116,10 @@ export default async function JoinPage({ searchParams }: Props) {
<div className="min-h-screen flex items-center justify-center bg-[#0a0a1a] text-white grid-bg">
<div className="glass-card p-10 text-center max-w-md mx-auto">
<div className="w-16 h-16 rounded-full bg-red-500/10 border border-red-500/20 flex items-center justify-center mx-auto mb-5">
<svg
<FontAwesomeIcon
icon={faCircleXmark}
className="w-8 h-8 text-red-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M6 18L18 6M6 6l12 12"
/>
</svg>
/>
</div>
<h1 className="text-xl font-bold text-white mb-2">
Invite Not Found
Expand Down Expand Up @@ -195,37 +184,16 @@ export default async function JoinPage({ searchParams }: Props) {

<div className="flex items-center justify-center gap-6 mt-6 mb-8">
<div className="flex items-center gap-2 text-gray-400 text-sm">
<svg
className="w-4 h-4 text-indigo-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"
/>
</svg>
<FontAwesomeIcon icon={faUsers} className="w-4 h-4 text-indigo-400" />
<span>
{memberCount} {memberCount === 1 ? "member" : "members"}
</span>
</div>
<div className="flex items-center gap-2 text-gray-400 text-sm">
<svg
<FontAwesomeIcon
icon={faRankingStar}
className="w-4 h-4 text-purple-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"
/>
</svg>
/>
<span>Leaderboard</span>
</div>
</div>
Expand Down
16 changes: 3 additions & 13 deletions app/(public)/leaderboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import CTA from "@/app/components/layout/CTA";
import Image from "next/image";
import { Metadata } from "next";
import { getUserWithProfile } from "@/app/lib/supabase/help/user";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";

export const metadata: Metadata = {
title: "Leaderboards - DevPulse",
Expand Down Expand Up @@ -109,19 +111,7 @@ export default async function Leaderboards() {
</div>
<span className="text-gray-500 text-sm group-hover:text-indigo-400 transition flex items-center gap-2">
View{" "}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"
/>
</svg>
<FontAwesomeIcon icon={faArrowRight} className="w-4 h-4" />
</span>
</a>
),
Expand Down
54 changes: 42 additions & 12 deletions app/(user)/dashboard/settings/page.tsx
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the 'best practices' is should not be there as it should be part of FAQ.

<div className="glass-card p-5 border-t-4 border-indigo-500/40">
              <h3 className="text-xs font-semibold text-indigo-300 uppercase tracking-widest mb-3">
                Best Practices
              </h3>
              <div className="space-y-2 text-xs md:text-sm text-gray-400 leading-relaxed">
                <p>Rotate API keys periodically and avoid sharing them in screenshots.</p>
                <p>Use a strong password and reset it immediately if account activity looks unusual.</p>
                <p>After changing your API key, run a dashboard sync to refresh your metrics.</p>
              </div>
            </div>
  • changing the api should not forced the system to update the coding metrics to avoid API call and charges in vercel and supabase
  • rotating the api keys periodically is not ideal as if the API key rotates the user needs to update the API key not just in our system but also on his/her devices and other 3rd party services connected or integrated to Wakatime.
  • in terms of using a strong password, supabase automatically checks the password strength and if the password is common or in data leaks.

Original file line number Diff line number Diff line change
@@ -1,31 +1,61 @@
import { Metadata } from "next";
import UserProfile from "@/app/components/dashboard/Settings/Profile";
import ResetPassword from "@/app/components/dashboard/Settings/ResetPassword";
import WakaTimeKey from "@/app/components/dashboard/Settings/WakaTimeKey";
import { getUserWithProfile } from "@/app/lib/supabase/help/user";
import { redirect } from "next/navigation";

export const metadata: Metadata = {
title: "Settings - DevPulse",
};

export default async function LeaderboardsPage() {
const { user } = await getUserWithProfile();
export default async function SettingsPage() {
const { user, profile } = await getUserWithProfile();
if (!user) return redirect("/login?from=/dashboard/settings");

const hasWakaKey = Boolean(profile?.wakatime_api_key);
const maskedWakaKey = profile?.wakatime_api_key
? `${profile.wakatime_api_key.slice(0, 8)}...${profile.wakatime_api_key.slice(-4)}`
: null;

return (
<div className="p-6 md:p-8 space-y-6">
<div>
<h1 className="text-2xl font-bold text-white">Settings</h1>
<p className="text-sm text-gray-600">
Manage your account settings and including your WakaTime API key.
</p>
<div className="p-4 md:p-6 space-y-4 max-w-7xl mx-auto">
<div className="glass-card p-4 md:p-5 border-t-4 border-indigo-500/50">
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
<div>
<h1 className="text-xl md:text-2xl font-bold text-white tracking-tight">
Account Settings
</h1>
<p className="text-xs md:text-sm text-gray-400 mt-1">
Manage profile details, WakaTime connection, and account security.
</p>
</div>

<div className="flex items-center gap-2 text-[11px] uppercase tracking-wider">
<span
className={`px-2 py-1 rounded-full border font-semibold ${
hasWakaKey
? "border-emerald-500/30 bg-emerald-500/10 text-emerald-300"
: "border-amber-500/30 bg-amber-500/10 text-amber-300"
}`}
>
{hasWakaKey ? "WakaTime Connected" : "WakaTime Not Connected"}
</span>
</div>
</div>
</div>

{user && (
<>
<UserProfile user={user} />
<ResetPassword user={user} />
</>
<div className="grid grid-cols-1 xl:grid-cols-3 gap-4 items-start">
<div className="xl:col-span-2 space-y-4">
<UserProfile user={user} />
<WakaTimeKey hasKey={hasWakaKey} maskedKey={maskedWakaKey} />
</div>

<div className="xl:col-span-1">
<ResetPassword user={user} />
</div>
</div>
)}
</div>
);
Expand Down
Loading
Loading