Redid the front end so it now uses gitea as data source
continuous-integration/drone/push Build is running
Details
continuous-integration/drone/push Build is running
Details
parent
18c1970550
commit
6fa3241768
@ -1 +1,2 @@
|
||||
NEXT_PUBLIC_GITHUB_USERNAME=Guusvanmeerveld
|
||||
NEXT_PUBLIC_GITEA_USERNAME=Guusvanmeerveld
|
||||
NEXT_PUBLIC_GITEA_SERVER=git.guusvanmeerveld.dev
|
||||
|
@ -1,67 +1,3 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8
|
||||
},
|
||||
"plugins": [
|
||||
"prettier",
|
||||
"css-modules"
|
||||
],
|
||||
"ignorePatterns": [
|
||||
"node_modules/*",
|
||||
".next/*",
|
||||
".out/*"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:css-modules/recommended"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"settings": {
|
||||
"react": {
|
||||
"version": "detect"
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:jsx-a11y/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": "error",
|
||||
"react/prop-types": "off",
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"jsx-a11y/anchor-is-valid": "off",
|
||||
"jsx-a11y/no-autofocus": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error"
|
||||
],
|
||||
"@typescript-eslint/explicit-function-return-type": [
|
||||
"warn",
|
||||
{
|
||||
"allowExpressions": true,
|
||||
"allowConciseArrowFunctionExpressionsStartingWithVoid": true,
|
||||
"allowTypedFunctionExpressions": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
"extends": "next/core-web-vitals"
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"stylelint-config-standard",
|
||||
"stylelint-config-idiomatic-order"
|
||||
],
|
||||
"rules": {
|
||||
"indentation": "tab"
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
// @ts-check
|
||||
/**
|
||||
* @type {import('next/dist/next-server/server/config').NextConfig}
|
||||
* @type {import('next').NextConfig}
|
||||
**/
|
||||
module.exports = {
|
||||
reactStrictMode: true,
|
||||
}
|
||||
reactStrictMode: true,
|
||||
images: {
|
||||
domains: [process.env.NEXT_PUBLIC_GITEA_SERVER]
|
||||
}
|
||||
};
|
||||
|
@ -1,40 +1,47 @@
|
||||
import Link from "next/link";
|
||||
|
||||
import { FC } from "react";
|
||||
import z from "zod";
|
||||
|
||||
import { BestRepository } from "@interfaces/repository";
|
||||
import { RepositoryResponse } from "@models/responses";
|
||||
|
||||
const BestRepository: FC<{ repository: BestRepository }> = ({ repository }) => {
|
||||
return (
|
||||
<div className="hero bg-primary">
|
||||
<div className="container">
|
||||
<div className="columns">
|
||||
<div className="column col-8 col-md-12 col-mx-auto">
|
||||
<h3 className="text-secondary">My most popular project:</h3>
|
||||
<h1>{repository.name}</h1>
|
||||
<h3 className="text-secondary">
|
||||
{repository.stargazers_count} Star(s)
|
||||
</h3>
|
||||
<h5>{repository.description}</h5>
|
||||
<p className="text-secondary">
|
||||
Written in {repository.language}, has{" "}
|
||||
{repository.open_issues_count} issue(s) and{" "}
|
||||
{repository.forks_count} fork(s).
|
||||
</p>
|
||||
const BestRepository: FC<{ repository: z.infer<typeof RepositoryResponse> }> =
|
||||
({ repository }) => {
|
||||
return (
|
||||
<div className="hero bg-primary">
|
||||
<div className="container">
|
||||
<div className="columns">
|
||||
<div className="column col-8 col-md-12 col-mx-auto">
|
||||
<h3 className="text-secondary">My most popular project:</h3>
|
||||
<h1>{repository.full_name}</h1>
|
||||
<h3 className="text-secondary">{repository.size} byes</h3>
|
||||
<h5>{repository.description}</h5>
|
||||
<p className="text-secondary">
|
||||
Written in {repository.language}, has{" "}
|
||||
{repository.open_issues_count} issue(s) and{" "}
|
||||
{repository.forks_count} fork(s).
|
||||
</p>
|
||||
|
||||
<Link href={repository.url}>
|
||||
<a className="btn mr-2">Github</a>
|
||||
</Link>
|
||||
{repository.homepage && (
|
||||
<Link href={repository.homepage}>
|
||||
<a className="btn">Website</a>
|
||||
</Link>
|
||||
)}
|
||||
<p>
|
||||
<Link href={repository.html_url}>
|
||||
<a className="btn mr-2">Github</a>
|
||||
</Link>
|
||||
{repository.website && (
|
||||
<Link href={repository.website}>
|
||||
<a className="btn">Website</a>
|
||||
</Link>
|
||||
)}
|
||||
</p>
|
||||
|
||||
<h5 className="text-secondary">
|
||||
Last commit on{" "}
|
||||
{new Date(repository.updated_at).toLocaleDateString()}
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
);
|
||||
};
|
||||
|
||||
export default BestRepository;
|
||||
|
@ -1,46 +0,0 @@
|
||||
import { FC } from "react";
|
||||
|
||||
import styles from "./intro.module.scss";
|
||||
|
||||
const Intro: FC<{ isAvailable: boolean }> = ({ isAvailable }) => {
|
||||
return (
|
||||
<div className={styles.main}>
|
||||
<div className="container">
|
||||
<div className="columns">
|
||||
<div className="column col-8 col-md-12 col-mx-auto text-center">
|
||||
<h1>Guus van Meerveld</h1>
|
||||
|
||||
<h3>
|
||||
Open source <u>web developer</u>
|
||||
</h3>
|
||||
|
||||
<p>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={`https://github.com/${process.env.NEXT_PUBLIC_GITHUB_USERNAME}`}
|
||||
className="btn btn-primary mr-2"
|
||||
>
|
||||
Github
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="mailto:contact@guusvanmeerveld.dev"
|
||||
className="btn btn-primary"
|
||||
>
|
||||
Contact
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p className="text-gray">
|
||||
Availibility: {isAvailable && "Available"}
|
||||
{!isAvailable && "Not available"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Intro;
|
@ -0,0 +1,67 @@
|
||||
import { FC } from "react";
|
||||
import z from "zod";
|
||||
|
||||
import Image from "next/image";
|
||||
|
||||
import { UserResponse } from "@models/responses";
|
||||
import { giteaServerUrl } from "@utils/config";
|
||||
import multipleClassNames from "@utils/multipleClassNames";
|
||||
|
||||
import styles from "./user.module.scss";
|
||||
|
||||
const User: FC<{ isAvailable: boolean; user: z.infer<typeof UserResponse> }> =
|
||||
({ isAvailable, user }) => {
|
||||
return (
|
||||
<div className={styles.main}>
|
||||
<div className="container">
|
||||
<div className="columns">
|
||||
<div
|
||||
className={multipleClassNames(
|
||||
"column",
|
||||
"col-4",
|
||||
"col-mx-auto",
|
||||
styles.avatarCol
|
||||
)}
|
||||
>
|
||||
<div className={styles.avatarContainer}>
|
||||
<Image
|
||||
src={user.avatar_url}
|
||||
className={styles.avatar}
|
||||
width={256}
|
||||
height={256}
|
||||
alt={`${user.full_name}'s avatar`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="column col-8 col-md-12 col-mx-auto">
|
||||
<h1>{user.full_name}</h1>
|
||||
|
||||
<h3>{user.description}</h3>
|
||||
|
||||
<p>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={`https://${giteaServerUrl}/${user.login}`}
|
||||
className="btn btn-primary mr-2"
|
||||
>
|
||||
Git
|
||||
</a>
|
||||
|
||||
<a href={`mailto:${user.email}`} className="btn btn-primary">
|
||||
Contact
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p className="text-gray">
|
||||
Availibility: {isAvailable && "Available"}
|
||||
{!isAvailable && "Not available"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default User;
|
@ -1,3 +0,0 @@
|
||||
.main {
|
||||
padding-top: 10rem;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
.main {
|
||||
padding-top: 10rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
|
||||
.avatar {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.avatarContainer {
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.avatarCol {
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
export interface GithubAPIRepository {
|
||||
id: number;
|
||||
node_id: string;
|
||||
name: string;
|
||||
full_name: string;
|
||||
private: boolean;
|
||||
owner: Owner;
|
||||
html_url: string;
|
||||
description: null | string;
|
||||
fork: boolean;
|
||||
url: string;
|
||||
forks_url: string;
|
||||
keys_url: string;
|
||||
collaborators_url: string;
|
||||
teams_url: string;
|
||||
hooks_url: string;
|
||||
issue_events_url: string;
|
||||
events_url: string;
|
||||
assignees_url: string;
|
||||
branches_url: string;
|
||||
tags_url: string;
|
||||
blobs_url: string;
|
||||
git_tags_url: string;
|
||||
git_refs_url: string;
|
||||
trees_url: string;
|
||||
statuses_url: string;
|
||||
languages_url: string;
|
||||
stargazers_url: string;
|
||||
contributors_url: string;
|
||||
subscribers_url: string;
|
||||
subscription_url: string;
|
||||
commits_url: string;
|
||||
git_commits_url: string;
|
||||
comments_url: string;
|
||||
issue_comment_url: string;
|
||||
contents_url: string;
|
||||
compare_url: string;
|
||||
merges_url: string;
|
||||
archive_url: string;
|
||||
downloads_url: string;
|
||||
issues_url: string;
|
||||
pulls_url: string;
|
||||
milestones_url: string;
|
||||
notifications_url: string;
|
||||
labels_url: string;
|
||||
releases_url: string;
|
||||
deployments_url: string;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
pushed_at: Date;
|
||||
git_url: string;
|
||||
ssh_url: string;
|
||||
clone_url: string;
|
||||
svn_url: string;
|
||||
homepage: null | string;
|
||||
size: number;
|
||||
stargazers_count: number;
|
||||
watchers_count: number;
|
||||
language: null | string;
|
||||
has_issues: boolean;
|
||||
has_projects: boolean;
|
||||
has_downloads: boolean;
|
||||
has_wiki: boolean;
|
||||
has_pages: boolean;
|
||||
forks_count: number;
|
||||
mirror_url: null;
|
||||
archived: boolean;
|
||||
disabled: boolean;
|
||||
open_issues_count: number;
|
||||
license: License | null;
|
||||
allow_forking: boolean;
|
||||
is_template: boolean;
|
||||
web_commit_signoff_required: boolean;
|
||||
topics: string[];
|
||||
visibility: string;
|
||||
forks: number;
|
||||
open_issues: number;
|
||||
watchers: number;
|
||||
default_branch: string;
|
||||
}
|
||||
|
||||
export interface License {
|
||||
key: string;
|
||||
name: string;
|
||||
spdx_id: string;
|
||||
url: string;
|
||||
node_id: string;
|
||||
}
|
||||
|
||||
export interface Owner {
|
||||
login: string;
|
||||
id: number;
|
||||
node_id: string;
|
||||
avatar_url: string;
|
||||
gravatar_id: string;
|
||||
url: string;
|
||||
html_url: string;
|
||||
followers_url: string;
|
||||
following_url: string;
|
||||
gists_url: string;
|
||||
starred_url: string;
|
||||
subscriptions_url: string;
|
||||
organizations_url: string;
|
||||
repos_url: string;
|
||||
events_url: string;
|
||||
received_events_url: string;
|
||||
type: string;
|
||||
site_admin: boolean;
|
||||
}
|
||||
|
||||
export interface RecentRepository {
|
||||
name: string;
|
||||
description: string;
|
||||
url: string;
|
||||
homepage?: string;
|
||||
stargazers_count: number;
|
||||
}
|
||||
|
||||
export interface BestRepository extends RecentRepository {
|
||||
forks_count: number;
|
||||
language: string;
|
||||
open_issues_count: number;
|
||||
pushed_at: Date;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
import z from "zod";
|
||||
|
||||
export const RepositoryResponse = z.object({
|
||||
full_name: z.string(),
|
||||
html_url: z.string(),
|
||||
language: z.string(),
|
||||
website: z.string(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
forks_count: z.number(),
|
||||
open_issues_count: z.number(),
|
||||
description: z.string(),
|
||||
size: z.number()
|
||||
});
|
||||
|
||||
export const SearchResultsResponse = z.object({
|
||||
ok: z.boolean(),
|
||||
data: RepositoryResponse.array()
|
||||
});
|
||||
|
||||
export const UserResponse = z.object({
|
||||
id: z.number(),
|
||||
login: z.string(),
|
||||
email: z.string(),
|
||||
avatar_url: z.string(),
|
||||
full_name: z.string(),
|
||||
description: z.string()
|
||||
});
|
@ -0,0 +1,5 @@
|
||||
export const giteaServerUrl =
|
||||
process.env.NEXT_PUBLIC_GITEA_SERVER ?? "https://git.guusvanmeerveld.dev";
|
||||
|
||||
export const giteaUsername =
|
||||
process.env.NEXT_PUBLIC_GITEA_USERNAME ?? "Guusvanmeerveld";
|
@ -0,0 +1,52 @@
|
||||
import axios from "axios";
|
||||
import z from "zod";
|
||||
|
||||
import createConfigCatClient from "./createConfigCatClient";
|
||||
|
||||
import {
|
||||
RepositoryResponse,
|
||||
SearchResultsResponse,
|
||||
UserResponse
|
||||
} from "@models/responses";
|
||||
import { giteaServerUrl } from "./config";
|
||||
|
||||
const apiUrl = `https://${giteaServerUrl}/api/v1`;
|
||||
|
||||
export const fetchAvailability = async (): Promise<boolean> => {
|
||||
const configCatClient = createConfigCatClient();
|
||||
|
||||
const isAvailable: boolean =
|
||||
(await configCatClient?.getValueAsync("amiavailable", true)) ?? true;
|
||||
|
||||
return isAvailable;
|
||||
};
|
||||
|
||||
export const fetchUser = async (
|
||||
giteaUsername: string
|
||||
): Promise<z.infer<typeof UserResponse>> => {
|
||||
const { data: user } = await axios.get<unknown>(
|
||||
`${apiUrl}/users/${giteaUsername}`
|
||||
);
|
||||
|
||||
return UserResponse.parse(user);
|
||||
};
|
||||
|
||||
export const fetchRepositories = async (
|
||||
giteaUserUid: number
|
||||
): Promise<z.infer<typeof RepositoryResponse>[]> => {
|
||||
const { data: repositories } = await axios.get<unknown>(
|
||||
`${apiUrl}/repos/search`,
|
||||
{
|
||||
params: {
|
||||
topic: true,
|
||||
q: "on-portfolio",
|
||||
id: giteaUserUid
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const results = SearchResultsResponse.parse(repositories);
|
||||
|
||||
if (results.ok) return results.data;
|
||||
else throw results.data;
|
||||
};
|
Loading…
Reference in new issue