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
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
## Table of Contents

- [Parameters](#parameters)
- [Customizations](#customizations)
- [Views Parameters](#views-parameters)

- [Cards](https://gitmystat.vercel.app#config)
- [User](#user)
- [Recent repos](#recent-repo)
- [Repo card](#repo-card)
- [Top languages](#top-languages)
- [Wakatime](#wakatime)
- [Views](#views)

- [Themes](https://gitmystat.vercel.app#themes)

Expand Down Expand Up @@ -75,6 +78,31 @@ All cards are built equally. Which means these apply to every card possible
>
> ![recent theme](https://gitmystat.vercel.app/recent?username=rahuletto&theme=gold)

### Views Parameters

Parameters specific to the `/views` badge:

| Parameters | Description | Default |
| ---------- | -------------------------------------------------------------- | ------- |
| `label` | Custom prefix text before the view count | `views` |
| `size` | Sizing of badge text & icon (`small`, `medium`, `large`) | `small` |
| `nobg` | Transparent background mode without borders (`true`, `false`) | `false` |
| `samp` | GitHub `<samp>` code monospace font style with white text | `false` |
| `icon` | Toggle eye icon (`true`, `false`) | `true` (Normal)<br>`false` (`samp`) |

- Views Badge Examples

```
![views](https://gitmystat.vercel.app/views?username=rahuletto&theme=tokyonight)
```

![views](https://gitmystat.vercel.app/views?username=rahuletto&theme=tokyonight)

> [!TIP]
> You can also showcase profile views inside your **User Stats Card** by adding `showViews=true` to `/user`.
>
> Example: `https://gitmystat.vercel.app/user?username=rahuletto&showViews=true`

---

## Cards
Expand All @@ -83,6 +111,7 @@ All cards are built equally. Which means these apply to every card possible
- [Repo card](https://gitmystat.vercel.app#config)
- [Top languages](https://gitmystat.vercel.app#config)
- [Wakatime](https://gitmystat.vercel.app#config)
- [Views](https://gitmystat.vercel.app#config)

> [!WARNING]
> For wakatime, We are using WakaTime api, which only displays for profiles that are public. Make sure the `Display code time publicly` and `Display languages, editors, os, categories publicly` are enabled.
Expand Down
162 changes: 140 additions & 22 deletions app/home/Builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ export default function Builder() {
const [themeColors, setThemeColors] = useState(Themes["dark"]);
const [error, setError] = useState(0);

const [viewsLabel, setViewsLabel] = useState("views");
const [viewsSize, setViewsSize] = useState("small");
const [viewsNobg, setViewsNobg] = useState(false);
const [viewsSamp, setViewsSamp] = useState(false);
const [viewsIcon, setViewsIcon] = useState<boolean | null>(null);
const [showViews, setShowViews] = useState(false);

const handleColorChange = (key: keyof typeof themeColors, value: string) => {
setThemeColors((prevThemeColors) => ({
...prevThemeColors,
Expand Down Expand Up @@ -89,6 +96,12 @@ export default function Builder() {
username,
repo,
layout: card == "top" || card == "wakatime" ? layout : "",
viewsLabel,
viewsSize,
viewsNobg,
viewsSamp,
viewsIcon,
showViews,
custom: themeColors as any,
})
);
Expand Down Expand Up @@ -142,6 +155,12 @@ export default function Builder() {
>
Wakatime
</button>
<button
className={`${btnStyle} ${card === "views" && "bg-paper-border text-paper-color dark:bg-moonlight-color dark:text-moonlight-background"}`}
onClick={() => setCard("views")}
>
Views
</button>
</div>

{card ? (
Expand Down Expand Up @@ -183,27 +202,39 @@ export default function Builder() {
className={`${error == 1 ? "border-4 border-red-400" : ""} appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent`}
/>
</div>
{card == "top" ||
(card == "wakatime" && (
<div className="flex flex-col items-start justify-start gap-2">
<label>layout</label>
<select
required
value={layout}
onChange={(e) => setLayout(e.target.value)}
className="appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent"
>
<option disabled value="" selected>
Select Layout
</option>
<option value="bar">bar</option>
<option value="compact">compact</option>
<option value="default" selected>
default
</option>
</select>
</div>
))}
{card === "user" && (
<div className="flex flex-col items-start justify-start gap-2">
<label>showViews</label>
<select
value={showViews ? "true" : "false"}
onChange={(e) => setShowViews(e.target.value === "true")}
className="appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent"
>
<option value="false">false</option>
<option value="true">true</option>
</select>
</div>
)}
{(card == "top" || card == "wakatime") && (
<div className="flex flex-col items-start justify-start gap-2">
<label>layout</label>
<select
required
value={layout}
onChange={(e) => setLayout(e.target.value)}
className="appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent"
>
<option disabled value="" selected>
Select Layout
</option>
<option value="bar">bar</option>
<option value="compact">compact</option>
<option value="default" selected>
default
</option>
</select>
</div>
)}

{card === "repo" && (
<div className="flex flex-col items-start justify-start gap-2">
Expand All @@ -216,6 +247,69 @@ export default function Builder() {
/>
</div>
)}

{card === "views" && (
<>
<div className="flex flex-col items-start justify-start gap-2">
<label>label</label>
<input
value={viewsLabel}
onChange={(e) => setViewsLabel(e.target.value)}
placeholder="views"
className="appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent"
/>
</div>
<div className="flex flex-col items-start justify-start gap-2">
<label>size</label>
<select
value={viewsSize}
onChange={(e) => setViewsSize(e.target.value)}
className="appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent"
>
<option value="small">small</option>
<option value="medium">medium</option>
<option value="large">large</option>
</select>
</div>
<div className="flex flex-col items-start justify-start gap-2">
<label>nobg (transparent)</label>
<select
value={viewsNobg ? "true" : "false"}
onChange={(e) => setViewsNobg(e.target.value === "true")}
className="appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent"
>
<option value="false">false</option>
<option value="true">true</option>
</select>
</div>
<div className="flex flex-col items-start justify-start gap-2">
<label>samp (code font)</label>
<select
value={viewsSamp ? "true" : "false"}
onChange={(e) => setViewsSamp(e.target.value === "true")}
className="appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent"
>
<option value="false">false</option>
<option value="true">true</option>
</select>
</div>
<div className="flex flex-col items-start justify-start gap-2">
<label>icon</label>
<select
value={viewsIcon === null ? "default" : viewsIcon ? "true" : "false"}
onChange={(e) => {
const val = e.target.value;
setViewsIcon(val === "default" ? null : val === "true");
}}
className="appearance-none rounded-xl border-paper-border px-4 py-2 text-lg text-paper-color dark:bg-moonlight-background dark:text-moonlight-accent"
>
<option value="default">default</option>
<option value="true">true</option>
<option value="false">false</option>
</select>
</div>
</>
)}
</div>
</details>

Expand Down Expand Up @@ -258,20 +352,36 @@ function generateURL({
username,
repo,
layout,
viewsLabel,
viewsSize,
viewsNobg,
viewsSamp,
viewsIcon,
showViews,
custom,
}: {
card: string;
theme: string;
username: string;
repo?: string;
layout?: string;
viewsLabel?: string;
viewsSize?: string;
viewsNobg?: boolean;
viewsSamp?: boolean;
viewsIcon?: boolean | null;
showViews?: boolean;
custom: ThemeType;
}) {
const params = new URLSearchParams();

params.append("theme", theme);
if (theme) params.append("theme", theme);
params.append("username", username);

if (card === "user" && showViews) {
params.append("showViews", "true");
}

if (card === "repo" && repo) {
params.append("repo", repo);
}
Expand All @@ -280,6 +390,14 @@ function generateURL({
params.append("layout", layout);
}

if (card === "views") {
if (viewsLabel && viewsLabel !== "views") params.append("label", viewsLabel);
if (viewsSize && viewsSize !== "small") params.append("size", viewsSize);
if (viewsNobg) params.append("nobg", "true");
if (viewsSamp) params.append("samp", "true");
if (viewsIcon !== null) params.append("icon", viewsIcon ? "true" : "false");
}

const defaultTheme = Themes[theme || "dark"];

Object.keys(defaultTheme).forEach((key) => {
Expand Down
37 changes: 37 additions & 0 deletions app/home/Config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,43 @@ export default function Config() {
/>
</div>
</div>

<div className="flex flex-col gap-4 w-full">
<h4 className="text-left text-3xl font-bold">Views</h4>
<div
className="grid w-full gap-12 rounded-xl"
style={{
gridTemplateColumns: "repeat(auto-fill, minmax(24rem, 1fr))",
gridTemplateRows: "min-content",
}}
>
<Card
url="/views?username=rahuletto"
text="/views?username=rahuletto"
width={200}
/>
<Card
url="/views?username=rahuletto&nobg=true"
text="/views?username=rahuletto&nobg=true"
width={200}
/>
<Card
url="/views?username=rahuletto&nobg=true&samp=true"
text="/views?username=rahuletto&nobg=true&samp=true"
width={200}
/>
<Card
url="/views?username=rahuletto&size=large"
text="/views?username=rahuletto&size=large"
width={240}
/>
<Card
url="/user?username=rahuletto&showViews=true"
text="/user?username=rahuletto&showViews=true"
width={285}
/>
</div>
</div>
</section>
</>
);
Expand Down
12 changes: 6 additions & 6 deletions app/home/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,15 @@ export default function Hero() {
</div>
<picture>
<source
srcSet="/wakatime?username=rahuletto&theme=catppuccin&layout=bar"
srcSet="/top?username=rahuletto&theme=catppuccin&layout=bar"
media="(prefers-color-scheme: dark)"
/>
<Image
width={300}
height={337}
loading="lazy"
src="/wakatime?username=rahuletto&theme=catppuccin-light&layout=bar"
alt="Recent"
src="/top?username=rahuletto&theme=catppuccin-light&layout=bar"
alt="Top bar"
/>
</picture>
</div>
Expand All @@ -149,14 +149,14 @@ export default function Hero() {
</div>
<picture>
<source
srcSet="/wakatime?username=rahuletto&layout=compact&theme=catppuccin"
srcSet="/top?username=rahuletto&layout=compact&theme=catppuccin"
media="(prefers-color-scheme: dark)"
/>
<Image
width={480}
height={130}
loading="lazy"
src="/wakatime?username=rahuletto&layout=compact&theme=catppuccin-light"
src="/top?username=rahuletto&layout=compact&theme=catppuccin-light"
alt="Top compact"
/>
</picture>
Expand All @@ -172,7 +172,7 @@ export default function Hero() {
AAAAAAAAA *crash*
</h2>
<p className="dark:text-cyred-accent text-cyred-light-accent max-w-[800px] text-xl font-medium lg:mx-auto lg:text-center">
Imagine, what if these stats are crutial for your README? I got
Imagine, what if these stats are crucial for your README? I got
you covered with amazing error handling, which tells you what
{"'"}s wrong instead of{" "}
<i className="dark:text-cyred-color text-cyred-light-color font-bold">
Expand Down
16 changes: 15 additions & 1 deletion app/user/User.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ThemeData } from "@/types/Theme";
import { UserStats } from "@/types/UserStats";
import Container from "../Container";
import { calculateRank } from "@/helpers/calculateRank";
import { GoCommit, GoGitPullRequest, GoIssueOpened, GoStar } from "react-icons/go";
import { GoCommit, GoGitPullRequest, GoIssueOpened, GoStar, GoEye } from "react-icons/go";
import { formatNumber } from "@/helpers/formatNum";

export default function UserComp(data: UserStats, theme: ThemeData) {
Expand Down Expand Up @@ -66,6 +66,20 @@ export default function UserComp(data: UserStats, theme: ThemeData) {
{formatNumber(data.pullRequests)}
</div>
</div>

{data.views !== undefined && (
<div tw="flex justify-between w-full">
<div tw="flex items-center" style={{ gap: 8 }}>
<GoEye color={theme.tip} size={20} />
<div tw={`flex text-[${theme.color}] text-xl font-bold`}>
Views
</div>
</div>
<div tw={`flex text-[${theme.accent}] text-lg font-medium`}>
{formatNumber(data.views)}
</div>
</div>
)}
</div>
</div>
</Container>
Expand Down
Loading