Skip to content

Feature/explore #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 22, 2025
Binary file added public/default.webp
Binary file not shown.
199 changes: 199 additions & 0 deletions src/app/(default)/explore/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
'use client'

import { useEffect, useState } from "react";
import { notifications } from "@mantine/notifications";
import {
ExploreItemOrganization,
ExploreItemProduct,
ExploreItemUser
} from "@/component/explore/ExploreItem";
import { ExploreItemHeader } from "@/component/explore/ExploreItemHeader";
import {Pagination} from "@mantine/core";

export type ExplorePageProps =
undefined
| ExploreProduct
| ExploreUser
| ExploreOrganization;

export interface ExploreProduct {
total: number,
type: string,
data: {
created_at: string,
default_branch: string,
description?: string,
fork: number,
star: number,
watch: number,
name: string,
rtype: string,
topic: string[],
uid: string,
updated_at: string,
owner: {
avatar: string,
description?: string,
uid: string,
name: string,
}
}[]
}

export interface ExploreUser {
total: number,
type: string,
data: {
created_at: string,
description?: string,
name: string,
uid: string,
avatar?: string,
updated_at: string,
}[]
}

export interface ExploreOrganization {
total: number,
type: string,
data: {
created_at: string,
description?: string,
name: string,
avatar?: string,
uid: string,
updated_at: string,
repo: number,
member: number,
}[]
}

export default function ExplorePage() {
const [Data, setData] = useState<ExplorePageProps>();
const [Rtype,setRtype] = useState<undefined | "product" | "user" | "organization">();
const [Filter, setFilter] = useState<undefined | 'public' | 'private'>();
const [Search, setSearch] = useState<string>("");
const [Page, setPage] = useState<{
page: number,
size: number,
}>({
page: 1,
size: 10,
})

const FetchData = async () => {
const payload = {
type: Rtype,
filter: Filter,
search: Search,
}
const parma = new URLSearchParams();
parma.append("rtype", payload.type ? payload.type : "product");
parma.append("filter", payload.filter ? payload.filter : "all");
parma.append("search", payload.search);
parma.append("page", Page.page.toString())
parma.append("size", Page.size.toString())
const response = await fetch(`/api/v1/explore?${parma}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});

if (response.status === 200) {
response.json().then((result: ExplorePageProps) => {
if(result) {
setData(result);
}
});
} else {
notifications.show({
title: 'Failed',
message: 'Unable to fetch explore data',
color: 'red',
});
}
};

useEffect(() => {
FetchData().then().catch().finally();
},
// !!!forbid insert FetchData in useEffect deps
[Rtype, Filter, Search]);
return (
<div className="explore">
<ExploreItemHeader setRtype={(x)=>{
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
setRtype(x)
}} rtype={Rtype} Filter={Filter} setFilter={(x)=>{
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
setFilter(x)
}} search={Search} setSearch={(x)=>{
setSearch(x)
}}
/>
<div className="explore-list">
{
Data?.type === "product" &&
Data?.data?.map((item, index) => (
<ExploreItemProduct props={item as {
created_at: string,
default_branch: string,
description?: string,
fork: number,
star: number,
watch: number,
name: string,
rtype: string,
topic: string[],
uid: string,
updated_at: string,
owner: {
avatar: string,
description?: string,
uid: string,
name: string,
}
}} key={index}/>
))
}
{
Data?.type === "user" &&
Data?.data?.map((item, index) => (
<ExploreItemUser props={item as {
created_at: string,
description?: string,
name: string,
uid: string,
avatar?: string,
updated_at: string,
}} key={index}/>
))
}
{
Data?.type === "organization" &&
Data?.data?.map((item, index) => (
<ExploreItemOrganization props={item as {
created_at: string,
description?: string,
name: string,
avatar?: string,
uid: string,
updated_at: string,
repo: number,
member: number,
}} key={index}/>
))
}
</div>
<Pagination className="explore-pagin" total={Data?.total ? Math.ceil(Data?.total / Page.size) : 1} color={"gray"} onChange={(x)=>{
setPage({
page: x,
size: Page.size,
})
}}/>
</div>
);
}
20 changes: 14 additions & 6 deletions src/app/(repo)/[user]/[repo]/setting/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
export default function Page(){
return(
<>
</>
)
}
import React from 'react';
import RepoSetHeader from '@/component/repo/RepoSetHeader';


export default function Repo(props: { owner: string, repo: string, setting: string }) {
return (
<div className="repo">
<RepoSetHeader owner={props.owner} repo={props.repo} setting={props.setting} />
<div>
<p>这里是 repo 的其他内容</p>
</div>
</div>
);
}
119 changes: 119 additions & 0 deletions src/component/explore/ExploreItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React from 'react';
import {CiLink, CiStar} from "react-icons/ci";
import {GoRepo, GoRepoForked} from 'react-icons/go';
import {LuUsers} from "react-icons/lu";


export interface ExploreItemProductProps {
props:{
created_at: string,
default_branch: string,
description?: string,
fork: number,
star: number,
watch: number,
name: string,
rtype: string,
topic: string[],
uid: string,
updated_at: string,
owner: {
avatar: string,
description?: string,
uid: string,
name: string,
}
}
}


export const ExploreItemProduct = ({props}:ExploreItemProductProps) => {
return(
<div className="explore-product">
<img className='explore-product-avatar' src={props.owner.avatar ?? '/default.webp'} alt={props.owner.name}/>
<div className="explore-product-title">
<div className="explore-product-title-name">
{props.name}
</div>
<div className="explore-product-title-desc">
{props.description}
</div>
</div>
<div className="explore-product-data">
<div className="explore-product-data-item">
<CiStar />{props.star}
</div>
<div className="explore-product-data-item">
<CiLink />{props.watch}
</div>
<div className="explore-product-data-item">
<GoRepoForked />{props.fork}
</div>
</div>
</div>
)
}

export interface ExploreItemUserProps {
props:{
created_at: string,
description?: string,
name: string,
uid: string,
avatar?: string,
updated_at: string,
}
}

export const ExploreItemUser = ({props}:ExploreItemUserProps) => {
return(
<div className="explore-users">
<img className='explore-users-avatar' src={props.avatar ?? '/default.webp'} alt={props.name}/>
<div className="explore-users-title">
<div className="explore-users-title-name">
{props.name}
</div>
<div className="explore-users-title-desc">
{props.description}
</div>
</div>
</div>
)
}
export interface ExploreItemOrganizationProps {
props:{
created_at: string,
description?: string,
name: string,
avatar?: string,
uid: string,
updated_at: string,
repo: number,
member: number,
}
}

export const ExploreItemOrganization = ({props}:ExploreItemOrganizationProps) => {
return(
<div className="explore-organization">
<img className='explore-organization-avatar' src={props.avatar ?? '/default.webp'} alt={props.name}/>
<div className="explore-organization-title">
<div className="explore-organization-title-name">
{props.name}
</div>
<div className="explore-organization-title-desc">
{props.description}
</div>
</div>
<div className="explore-organization-data">
<div className="explore-organization-data-item">
<GoRepo />{props.repo}
</div>
<div className="explore-organization-data-item">
<LuUsers />{props.member}
</div>
</div>

</div>
)
}
Loading
Loading