Skip to content
Merged
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
70 changes: 63 additions & 7 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,53 @@

:root {
color-scheme: light;
--background: 210 40% 98%;
--foreground: 222 47% 11%;
--card: 0 0% 100%;
--card-foreground: 222 47% 11%;
--muted: 210 20% 96%;
--muted-foreground: 215 16% 47%;
--border: 214 32% 91%;
--input: 214 32% 91%;
--ring: 217 91% 60%;
--primary: 217 91% 60%;
--primary-foreground: 210 40% 98%;
--secondary: 191 91% 42%;
--secondary-foreground: 210 40% 98%;
--accent: 199 89% 48%;
--accent-foreground: 210 40% 98%;
--destructive: 0 84% 60%;
--destructive-foreground: 210 40% 98%;
}

.dark {
color-scheme: dark;
--background: 222 47% 8%;
--foreground: 210 40% 96%;
--card: 222 47% 11%;
--card-foreground: 210 40% 96%;
--muted: 217 33% 17%;
--muted-foreground: 215 20% 65%;
--border: 217 33% 20%;
--input: 217 33% 20%;
--ring: 217 91% 60%;
--primary: 217 91% 60%;
--primary-foreground: 210 40% 98%;
--secondary: 191 91% 42%;
--secondary-foreground: 210 40% 98%;
--accent: 199 89% 48%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62% 40%;
--destructive-foreground: 210 40% 98%;
}

* {
@apply box-border;
border-color: hsl(var(--border));
}

body {
@apply bg-slate-50 text-slate-900 antialiased;
@apply bg-background text-foreground antialiased;
font-family: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
background-image:
radial-gradient(circle at 20% 20%, rgba(59, 130, 246, 0.08), transparent 35%),
Expand All @@ -21,22 +60,39 @@ body {
}

.dark body {
@apply bg-slate-950 text-slate-100;
@apply bg-background text-foreground;
background-image:
radial-gradient(circle at 20% 20%, rgba(59, 130, 246, 0.08), transparent 35%),
radial-gradient(circle at 80% 0%, rgba(124, 58, 237, 0.12), transparent 30%),
linear-gradient(180deg, #0f172a 0%, #0b1221 40%, #0a0f1c 100%);
}

.card {
@apply bg-white/90 shadow-card rounded-2xl border border-slate-100 backdrop-blur;
@apply bg-card/90 text-card-foreground shadow-card rounded-2xl border border-border backdrop-blur;
transition: transform 180ms ease, box-shadow 180ms ease;
box-shadow: 0 18px 48px rgba(15, 23, 42, 0.12);

box-shadow: 0 18px 48px rgba(15, 23, 42, 0.12);
}


.dark .card {
@apply bg-slate-900/80 border-slate-800;
@apply bg-card/80 border-border;
box-shadow: 0 18px 48px rgba(0, 0, 0, 0.45);
}
}

html.theme-transition,
html.theme-transition *,
html.theme-transition *::before,
html.theme-transition *::after {
transition-property: background-color, border-color, color, fill, stroke, box-shadow;
transition-duration: 460ms;
transition-timing-function: cubic-bezier(0.32, 0, 0.2, 1);
}

@media (prefers-reduced-motion: reduce) {
html.theme-transition,
html.theme-transition *,
html.theme-transition *::before,
html.theme-transition *::after {
transition: none !important;
}
}
2 changes: 1 addition & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const metadata = {

export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html>
<html lang="en" suppressHydrationWarning>
<body>
<Providers>{children}</Providers>
</body>
Expand Down
6 changes: 4 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ResultDashboard } from "../components/result-dashboard";
import { DashboardSkeleton } from "../components/skeletons";
import { UserResult } from "@/types/user-result";
import { LanguageSwitcher } from "@/components/language-switcher";
import { ThemeToggle } from "@/components/theme-toggle";

type ApiResponse = {
success: boolean;
Expand Down Expand Up @@ -68,7 +69,7 @@ export default function HomePage() {
return (
<main className="min-h-screen flex flex-col">
{" "}
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<header className="sticky top-0 z-50 w-full border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 max-w-7xl items-center justify-between m-auto px-4">
<div className="flex items-center gap-2 font-bold text-xl">
<span className="bg-gradient-to-r from-primary to-primary/60 bg-clip-text text-transparent">
Expand All @@ -78,6 +79,7 @@ export default function HomePage() {

<div className="flex gap-4">
<LanguageSwitcher />
<ThemeToggle />
</div>
</div>
</header>
Expand Down Expand Up @@ -122,7 +124,7 @@ export default function HomePage() {
</div>
)}
</div>
<footer className="border-t py-6 text-center text-sm text-muted-foreground">
<footer className="border-t border-border py-6 text-center text-sm text-muted-foreground">
<div className="container max-w-7xl mx-auto px-4">
<span className="font-medium">DevImpact</span> — Compare GitHub developer metrics
</div>
Expand Down
9 changes: 6 additions & 3 deletions app/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import { LanguageProvider } from "@/components/language-provider";
import { TooltipProvider } from "@/components/ui/tooltip";
import { ThemeProvider } from "@/components/theme-provider";

export default function Providers({ children }: { children: React.ReactNode }) {
return (
<LanguageProvider>
<TooltipProvider>{children}</TooltipProvider>{" "}
</LanguageProvider>
<ThemeProvider>
<LanguageProvider>
<TooltipProvider>{children}</TooltipProvider>
</LanguageProvider>
</ThemeProvider>
);
}
4 changes: 2 additions & 2 deletions components/compare-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ export function CompareForm({
<CardContent>
<div className="grid gap-3 md:grid-cols-2">
<input
className="h-11 rounded-lg border border-slate-200 px-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary/60 focus:border-transparent bg-white"
className="h-11 rounded-lg border border-input bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/60 focus:border-transparent"
ref={firstInputRef}
placeholder={t("form.username1") }
value={username1}
onChange={(e) => setUsername1(e.target.value)}
/>
<input
className="h-11 rounded-lg border border-slate-200 px-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary/60 focus:border-transparent bg-white"
className="h-11 rounded-lg border border-input bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/60 focus:border-transparent"
placeholder={t("form.username2") }
value={username2}
onChange={(e) => setUsername2(e.target.value)}
Expand Down
2 changes: 1 addition & 1 deletion components/comparison-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const {t} = useTranslation();
</CardTitle>
</CardHeader>
<CardContent className="pt-6 space-y-4">
<div className="flex justify-between items-center border-b pb-2">
<div className="flex justify-between items-center border-b border-border pb-2">
<span className="text-muted-foreground">{t("comparsion.final.score")}</span>
<span className="text-2xl font-bold">{user.finalScore}</span>
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/language-switcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function LanguageSwitcher() {
return (
<div className={cn("flex items-center gap-2 text-sm", dir === "rtl" && "flex-row-reverse")}>
<select
className="h-9 rounded-lg border border-slate-200 bg-white px-3 text-sm focus:outline-none focus:ring-2 focus:ring-primary/60"
className="h-9 rounded-lg border border-input bg-background px-3 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary/60"
value={locale}
onChange={(e) => setLocale(e.target.value as any)}
>
Expand Down
10 changes: 5 additions & 5 deletions components/score-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ export function ScoreCard({ title, value, highlight, subtitle }: ScoreCardProps)
return (
<div
className={cn(
"card p-4 flex flex-col gap-1 border bg-gradient-to-br from-white via-white to-slate-50 transition-all",
highlight ? "border-blue-500/50 shadow-blue-200" : "border-slate-100"
"card p-4 flex flex-col gap-1 border bg-gradient-to-br from-card via-card to-muted/40 transition-all",
highlight ? "border-primary/50 shadow-blue-200 dark:shadow-blue-950/40" : "border-border"
)}
>
<p className="text-xs uppercase tracking-wide text-slate-500">{title}</p>
<p className="text-xs uppercase tracking-wide text-muted-foreground">{title}</p>
<div className="flex items-baseline gap-2">
<span className="text-2xl font-semibold text-slate-900">
<span className="text-2xl font-semibold text-foreground">
{value.toFixed(2)}
</span>
{subtitle && (
<span className="text-xs text-slate-500 leading-tight">{subtitle}</span>
<span className="text-xs text-muted-foreground leading-tight">{subtitle}</span>
)}
</div>
</div>
Expand Down
12 changes: 7 additions & 5 deletions components/skeletons.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Skeleton } from "@/components/ui/skeleton";

export function DashboardSkeleton() {
return (
<div className="card p-6 animate-pulse space-y-4">
<div className="h-5 bg-slate-200 rounded w-1/3" />
<div className="h-4 bg-slate-200 rounded w-1/2" />
<Skeleton className="h-5 w-1/3" />
<Skeleton className="h-4 w-1/2" />
<div className="grid gap-3 md:grid-cols-2">
<div className="h-24 bg-slate-200 rounded-lg" />
<div className="h-24 bg-slate-200 rounded-lg" />
<Skeleton className="h-24 rounded-lg" />
<Skeleton className="h-24 rounded-lg" />
</div>
<div className="h-64 bg-slate-200 rounded-xl" />
<Skeleton className="h-64 rounded-xl" />
</div>
);
}
17 changes: 17 additions & 0 deletions components/theme-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"use client";

import { ThemeProvider as NextThemesProvider } from "next-themes";
import type { ReactNode } from "react";

export function ThemeProvider({ children }: { children: ReactNode }) {
return (
<NextThemesProvider
attribute="class"
defaultTheme="system"
enableSystem
storageKey="devimpact-theme"
>
{children}
</NextThemesProvider>
);
}
43 changes: 43 additions & 0 deletions components/theme-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import { Moon, Sun } from "lucide-react";
import { useTheme } from "next-themes";
import { Button } from "./ui/button";
import { useEffect, useState } from "react";

export function ThemeToggle() {
const { theme, setTheme, resolvedTheme } = useTheme();
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
const THEME_TRANSITION_MS = 520;

const current = resolvedTheme || theme || "light";
const next = current === "light" ? "dark" : "light";

const handleToggle = () => {
if (typeof document !== "undefined") {
const root = document.documentElement;
root.classList.add("theme-transition");
window.setTimeout(() => {
root.classList.remove("theme-transition");
}, THEME_TRANSITION_MS);
}

requestAnimationFrame(() => {
setTheme(next);
});
};

return (
<Button
type="button"
variant="ghost"
size="sm"
onClick={handleToggle}
className="flex items-center gap-2"
aria-label="Toggle color mode"
>
{mounted && current === "dark" ? <Sun size={16} /> : <Moon size={16} />}
</Button>
);
}
8 changes: 4 additions & 4 deletions components/top-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ export function TopList({ userResults }: Props) {
key: string | number;
}) => (
<div
className="rounded-lg border p-3 transition-all hover:bg-muted/50 flex items-center justify-between"
className="rounded-lg border border-border p-3 transition-all hover:bg-muted/50 flex items-center justify-between"
key={data.key}
>
<div>
<div className="font-medium text-slate-900">
<div className="font-medium text-foreground">
{data.titleUrl ? (
<a
href={data.titleUrl}
Expand Down Expand Up @@ -67,10 +67,10 @@ export function TopList({ userResults }: Props) {
</div>
</div>
<div className="text-right">
<p className="text-sm font-semibold text-slate-900">
<p className="text-sm font-semibold text-foreground">
{(data.score ?? 0).toFixed(2)}
</p>
<p className="text-[11px] text-slate-500">{t('comparsion.score')}</p>
<p className="text-[11px] text-muted-foreground">{t('comparsion.score')}</p>
</div>
</div>
);
Expand Down
19 changes: 19 additions & 0 deletions components/ui/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from "react"

import { cn } from "@/lib/utils"

function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<input
type={type}
data-slot="input"
className={cn(
"h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
className
)}
{...props}
/>
)
}

export { Input }
13 changes: 13 additions & 0 deletions components/ui/skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { cn } from "@/lib/utils"

function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="skeleton"
className={cn("animate-pulse rounded-md bg-muted", className)}
{...props}
/>
)
}

export { Skeleton }
2 changes: 1 addition & 1 deletion next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/types/routes.d.ts";

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
Loading
Loading