From 0639cad2d3ead5f35dc32ddb538cb4da4338d086 Mon Sep 17 00:00:00 2001 From: Vichea Date: Sun, 29 Sep 2024 22:47:27 -0500 Subject: [PATCH] Add UI Profile and repository --- src/SearchBugs.Api/Program.cs | 2 +- src/SearchBugs.Ui/src/Route.tsx | 11 +- .../src/components/footer/Footer.tsx | 10 + .../src/components/header/Header.tsx | 45 ++++ src/SearchBugs.Ui/src/layouts/Main.tsx | 48 +--- .../modules/profile/ContibutionActivity.tsx | 99 +++++++++ .../src/modules/profile/Overview.tsx | 83 +++++++ .../src/modules/profile/PopularRepository.tsx | 53 +++++ .../src/modules/profile/Profile.tsx | 53 +++++ .../src/modules/profile/RecentActivity.tsx | 71 ++++++ .../src/modules/profile/Repositories.tsx | 102 +++++++++ .../src/modules/profile/Repository.ts | 7 + .../src/modules/repository/CodeTree.tsx | 125 +++++++++++ src/SearchBugs.Ui/src/pages/ProfilePage.tsx | 83 +++++++ .../src/pages/RepositoriesPage.tsx | 206 ++++++++---------- src/SearchBugs.Ui/src/pages/index.ts | 3 +- src/SearchBugs.Ui/tsconfig.app.json | 1 + 17 files changed, 837 insertions(+), 165 deletions(-) create mode 100644 src/SearchBugs.Ui/src/components/footer/Footer.tsx create mode 100644 src/SearchBugs.Ui/src/components/header/Header.tsx create mode 100644 src/SearchBugs.Ui/src/modules/profile/ContibutionActivity.tsx create mode 100644 src/SearchBugs.Ui/src/modules/profile/Overview.tsx create mode 100644 src/SearchBugs.Ui/src/modules/profile/PopularRepository.tsx create mode 100644 src/SearchBugs.Ui/src/modules/profile/Profile.tsx create mode 100644 src/SearchBugs.Ui/src/modules/profile/RecentActivity.tsx create mode 100644 src/SearchBugs.Ui/src/modules/profile/Repositories.tsx create mode 100644 src/SearchBugs.Ui/src/modules/profile/Repository.ts create mode 100644 src/SearchBugs.Ui/src/modules/repository/CodeTree.tsx create mode 100644 src/SearchBugs.Ui/src/pages/ProfilePage.tsx diff --git a/src/SearchBugs.Api/Program.cs b/src/SearchBugs.Api/Program.cs index 261b4be..412e184 100644 --- a/src/SearchBugs.Api/Program.cs +++ b/src/SearchBugs.Api/Program.cs @@ -33,7 +33,7 @@ private static void Main(string[] args) app.MapProjectsEndpoints(); app.MapRepoEndpoints(); - app.UseHttpsRedirection(); + // app.UseHttpsRedirection(); app.UseAuthentication(); app.UseMiddleware(); diff --git a/src/SearchBugs.Ui/src/Route.tsx b/src/SearchBugs.Ui/src/Route.tsx index 40aea5f..6244686 100644 --- a/src/SearchBugs.Ui/src/Route.tsx +++ b/src/SearchBugs.Ui/src/Route.tsx @@ -7,10 +7,11 @@ import { DashboardPage, LoginPage, NotificationsPage, + ProfilePage, ProjectDetailsPage, ProjectsPage, RegisterPage, - RepositoriesPage, + RepositoryPage, RepositoryDetailsPage, SettingPage, UserDetailsPage, @@ -50,13 +51,17 @@ const router = createBrowserRouter([ path: "/users", element: , }, + { + path: "/profile", + element: , + }, { path: "/users/:userId", element: , }, { - path: "/repositories", - element: , + path: "/:username/:repository", + element: , }, { path: "/repositories/:url", diff --git a/src/SearchBugs.Ui/src/components/footer/Footer.tsx b/src/SearchBugs.Ui/src/components/footer/Footer.tsx new file mode 100644 index 0000000..6b50170 --- /dev/null +++ b/src/SearchBugs.Ui/src/components/footer/Footer.tsx @@ -0,0 +1,10 @@ + +export const Footer = () => { + return ( +
+
+

© 2021 SearchBugs. All rights reserved.

+
+
+ ) +} diff --git a/src/SearchBugs.Ui/src/components/header/Header.tsx b/src/SearchBugs.Ui/src/components/header/Header.tsx new file mode 100644 index 0000000..4ab2ebb --- /dev/null +++ b/src/SearchBugs.Ui/src/components/header/Header.tsx @@ -0,0 +1,45 @@ +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Bell, Plus } from "lucide-react"; +import { useNavigate } from "react-router-dom"; + +export const Header = () => { + const navigate = useNavigate(); + return ( +
+
+
+ + +
+ +
+ + + navigate("/profile")}> + + UN + +
+
+
+ ); +} \ No newline at end of file diff --git a/src/SearchBugs.Ui/src/layouts/Main.tsx b/src/SearchBugs.Ui/src/layouts/Main.tsx index a7a1966..dbaca99 100644 --- a/src/SearchBugs.Ui/src/layouts/Main.tsx +++ b/src/SearchBugs.Ui/src/layouts/Main.tsx @@ -1,54 +1,16 @@ -import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; -import { Button } from "@/components/ui/button"; -import { Input } from "@/components/ui/input"; -import { Bell, Plus } from "lucide-react"; + +import { Footer } from "@/components/footer/Footer"; +import { Header } from "@/components/header/Header"; import { Outlet } from "react-router-dom"; export default function Layout() { return (
-
-
-
- - -
- -
- - - - - UN - -
-
-
+
-
-
- © 2024 GitHub, Inc. Terms Privacy Security Status Help -
-
+
); } diff --git a/src/SearchBugs.Ui/src/modules/profile/ContibutionActivity.tsx b/src/SearchBugs.Ui/src/modules/profile/ContibutionActivity.tsx new file mode 100644 index 0000000..ef889f6 --- /dev/null +++ b/src/SearchBugs.Ui/src/modules/profile/ContibutionActivity.tsx @@ -0,0 +1,99 @@ +import { + Card, + CardContent, + CardHeader, + CardTitle, + } from "@/components/ui/card"; + import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + } from "@/components/ui/select"; + +const ContributionCell: React.FC<{ level: number }> = ({ level }) => { + const bgColor = [ + "bg-gray-100", + "bg-green-100", + "bg-green-300", + "bg-green-500", + "bg-green-700", + ][level]; + + return
; + }; + +const ContributionGraph: React.FC = () => { + const weeks = 52; + const days = 7; + + const generateRandomContributions = () => { + return Array.from({ length: weeks * days }, () => + Math.floor(Math.random() * 5) + ); + }; + + const contributions = generateRandomContributions(); + + return ( +
+ {Array.from({ length: weeks }).map((_, weekIndex) => ( +
+ {Array.from({ length: days }).map((_, dayIndex) => ( + + ))} +
+ ))} +
+ ); + }; + +interface ContributionActivityProps { + years: string[]; + selectedYear: string; + setSelectedYear: (year: string) => void; +} + + +export const ContributionActivity: React.FC = ({ + years, + selectedYear, + setSelectedYear, + }) => { + + return ( + + + Contribution Activity + + + +
+ Less + + + + + + More +
+ +
+
+ ); +}; diff --git a/src/SearchBugs.Ui/src/modules/profile/Overview.tsx b/src/SearchBugs.Ui/src/modules/profile/Overview.tsx new file mode 100644 index 0000000..2c09733 --- /dev/null +++ b/src/SearchBugs.Ui/src/modules/profile/Overview.tsx @@ -0,0 +1,83 @@ +import React, { useState } from "react"; +import { ContributionActivity } from "@/modules/profile/ContibutionActivity"; +import { Activity, ActivityType, RecentActivity } from "./RecentActivity"; +import { PopularRepository } from "./PopularRepository"; + +export const Overview: React.FC = () => { + const [selectedYear, setSelectedYear] = useState( + new Date().getFullYear().toString() + ); + const years = Array.from({ length: 5 }, (_, i) => + (new Date().getFullYear() - i).toString() + ); + + const activities : Activity[] = [ + { + type: ActivityType.Push, + actor: "vicheanath", + repository: "search-bugs", + createdAt: "2021-10-10", + title: "pushed to", + description: "Add new feature", + avatar: "https://avatars.githubusercontent.com/u/48352653", + }, + { + type: ActivityType.PullRequest, + actor: "vicheanath", + repository: "search-bugs", + createdAt: "2021-10-10", + title: "opened a pull request in", + description: "Add new feature", + avatar: "https://avatars.githubusercontent.com/u/48352653", + }, + { + type: ActivityType.Issue, + actor: "vicheanath", + repository: "search-bugs", + createdAt: "2021-10-10", + title: "opened an issue in", + description: "Add new feature", + avatar: "https://avatars.githubusercontent.com/u/48352653", + }, + { + type: ActivityType.Create, + actor: "vicheanath", + repository: "search-bugs", + createdAt: "2021-10-10", + title: "created a repository", + description: "You have created this repository", + avatar: "https://avatars.githubusercontent.com/u/48352653", + }, + { + type: ActivityType.Fork, + actor: "vicheanath", + repository: "search-bugs", + createdAt: "2021-10-10", + title: "forked", + description: "You have forked this repository", + avatar: "https://avatars.githubusercontent.com/u/48352653", + }, + { + type: ActivityType.Watch, + actor: "vicheanath", + repository: "search-bugs", + createdAt: "2021-10-10", + title: "starred", + description: "You have starred this repository", + avatar: "https://avatars.githubusercontent.com/u/48352653", + }, + ]; + + return ( + <> + + + + + + ); +}; diff --git a/src/SearchBugs.Ui/src/modules/profile/PopularRepository.tsx b/src/SearchBugs.Ui/src/modules/profile/PopularRepository.tsx new file mode 100644 index 0000000..23cc8a5 --- /dev/null +++ b/src/SearchBugs.Ui/src/modules/profile/PopularRepository.tsx @@ -0,0 +1,53 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, + } from "@/components/ui/card"; + import { Badge } from "@/components/ui/badge"; + import { Book, GitFork, Star } from "lucide-react"; + +export const PopularRepository: React.FC = () => { + + return ( + + + Popular repositories + + +
+ {[1, 2, 3, 4].map((_, index) => ( + + + + + + repo-name-{index + 1} + + + + Short description of the repository + + + +
+ + + {Math.floor(Math.random() * 1000)} + + + + {Math.floor(Math.random() * 100)} + + Public +
+
+
+ ))} +
+
+
+ ); + +} \ No newline at end of file diff --git a/src/SearchBugs.Ui/src/modules/profile/Profile.tsx b/src/SearchBugs.Ui/src/modules/profile/Profile.tsx new file mode 100644 index 0000000..753089e --- /dev/null +++ b/src/SearchBugs.Ui/src/modules/profile/Profile.tsx @@ -0,0 +1,53 @@ +import { Card, CardContent } from "@/components/ui/card"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { MapPin, Users } from "lucide-react"; +import { Button } from "@/components/ui/button"; + +interface ProfileProps { + displayName: string; + username: string; + profileImage: string; + bio: string; + followers: number; + following: number; + location: string; +} + +export const Profile: React.FC = ({ + displayName, + username, + bio, + followers, + following, + location, + profileImage, +}) => { + return ( + + +
+ + + JD + +

{displayName}

+

@{username}

+
+
+

{bio}

+
+ + + {followers} followers · {following} following + +
+
+ + {location} +
+ +
+
+
+ ); +}; diff --git a/src/SearchBugs.Ui/src/modules/profile/RecentActivity.tsx b/src/SearchBugs.Ui/src/modules/profile/RecentActivity.tsx new file mode 100644 index 0000000..ab77416 --- /dev/null +++ b/src/SearchBugs.Ui/src/modules/profile/RecentActivity.tsx @@ -0,0 +1,71 @@ +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { + GitPullRequest, + Star, + GitBranchPlus, + GitFork, + BugIcon, + Eye as Watch, +} from 'lucide-react'; +import React from "react"; + +export enum ActivityType { + Push = "PushEvent", + PullRequest = "PullRequestEvent", + Issue = "IssueEvent", + Create = "CreateEvent", + Fork = "ForkEvent", + Watch = "WatchEvent", +} + +export interface Activity { + type: ActivityType; + actor: string; + repository: string; + createdAt: string; + title: string; + description: string; + avatar: string; +} + +interface RecentActivityProps { + activities: Activity[]; +} + +export const RecentActivity: React.FC = ({ activities }) => { + const icons = { + [ActivityType.Push]: , + [ActivityType.PullRequest]: , + [ActivityType.Issue]: , + [ActivityType.Create]: , + [ActivityType.Fork]: , + [ActivityType.Watch]: , + }; + return ( + + + Recent Activity + + +
    + {activities.map((activity, index) => ( +
  • +
    + {icons[activity.type]} +
    +
    +

    + {activity.actor} {activity.title}{" "} + + {activity.repository} + +

    +

    {activity.description}

    +
    +
  • + ))} +
+
+
+ ); +}; diff --git a/src/SearchBugs.Ui/src/modules/profile/Repositories.tsx b/src/SearchBugs.Ui/src/modules/profile/Repositories.tsx new file mode 100644 index 0000000..07b0d8c --- /dev/null +++ b/src/SearchBugs.Ui/src/modules/profile/Repositories.tsx @@ -0,0 +1,102 @@ +import { + Card, + CardContent, + CardHeader, + } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { GitFork, Star } from "lucide-react"; + +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + } from "@/components/ui/select"; +import { Repository } from "./Repository"; + + + +interface RepositoriesProps { + repositories: Repository[]; +} + +export const Repositories : React.FC = ({repositories}) => { + return ( + + + {/* + feltering repositories by name , select type of repository (public or private), sort by stars, forks, and date created, language, and topics + */} +
+ + + + + + +
+ + +
+ +
    + {repositories.map((item, index) => ( +
    +
    +

    + + {item.name} + +

    + {item.description} +

    +
    +
    + + + {item.stars} + + + + {item.forks} + + + {item.isPublic ? "Public" : "Private"} + +
    +
    + ))} +
+
+
+ ); +} \ No newline at end of file diff --git a/src/SearchBugs.Ui/src/modules/profile/Repository.ts b/src/SearchBugs.Ui/src/modules/profile/Repository.ts new file mode 100644 index 0000000..d693ad7 --- /dev/null +++ b/src/SearchBugs.Ui/src/modules/profile/Repository.ts @@ -0,0 +1,7 @@ +export class Repository { + name: string = ''; + description: string = ''; + stars: number = 0; + forks: number = 0; + isPublic: boolean = false; +} \ No newline at end of file diff --git a/src/SearchBugs.Ui/src/modules/repository/CodeTree.tsx b/src/SearchBugs.Ui/src/modules/repository/CodeTree.tsx new file mode 100644 index 0000000..1243a0a --- /dev/null +++ b/src/SearchBugs.Ui/src/modules/repository/CodeTree.tsx @@ -0,0 +1,125 @@ +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { GitBranch } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + + +export const CodeTree: React.FC = () => { + return ( + <> +
+
+
+ + main +
+ +
+ +
+
+
+ + + +
+
+
+ + + + + README.md +
+ Updated 3 days ago +
+
+
+ + + + + + index.js +
+ Updated 1 week ago +
+
+
+ + + + + + + + package.json +
+ Updated 2 weeks ago +
+
+
+
+ + + README.md + + + The README.md file is a markdown file that contains information about + the repository. + + + + ); +}; diff --git a/src/SearchBugs.Ui/src/pages/ProfilePage.tsx b/src/SearchBugs.Ui/src/pages/ProfilePage.tsx new file mode 100644 index 0000000..e6cb9ee --- /dev/null +++ b/src/SearchBugs.Ui/src/pages/ProfilePage.tsx @@ -0,0 +1,83 @@ +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; + +import { Profile } from "@/modules/profile/Profile"; +import { Overview } from "@/modules/profile/Overview"; +import { Repositories } from "@/modules/profile/Repositories"; +import { Repository } from "@/modules/profile/Repository"; + +const mockRepositories: Repository[] = []; +mockRepositories.push({ + name: "repo-name-1", + description: "Short description of the repository", + stars: 100, + forks: 10, + isPublic: true, +}); +mockRepositories.push({ + name: "repo-name-2", + description: "Short description of the repository", + stars: 200, + forks: 20, + isPublic: true, +}); +mockRepositories.push({ + name: "repo-name-3", + description: "Short description of the repository", + stars: 300, + forks: 30, + isPublic: true, +}); +mockRepositories.push({ + name: "repo-name-4", + description: "Short description of the repository", + stars: 400, + forks: 40, + isPublic: true, +}); +mockRepositories.push({ + name: "repo-name-5", + description: "Short description of the repository", + stars: 500, + forks: 50, + isPublic: true, +}); + +export const ProfilePage: React.FC = () => { + return ( +
+
+
+ +
+
+ + + Overview + Repositories + Projects + Packages + + + + + + + + Projects + Packages + +
+
+
+ ); +}; + +export default ProfilePage; diff --git a/src/SearchBugs.Ui/src/pages/RepositoriesPage.tsx b/src/SearchBugs.Ui/src/pages/RepositoriesPage.tsx index 1349f7f..4656e39 100644 --- a/src/SearchBugs.Ui/src/pages/RepositoriesPage.tsx +++ b/src/SearchBugs.Ui/src/pages/RepositoriesPage.tsx @@ -1,129 +1,101 @@ -import { ListFilter, MoreHorizontal, PlusCircle } from "lucide-react"; +import React from "react"; import { Button } from "@/components/ui/button"; -import { Card, CardContent, CardFooter } from "@/components/ui/card"; import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; + Card, + CardContent, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Badge } from "@/components/ui/badge"; import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; + AlertCircle, + Book, + Eye, + Code, + GitFork, + GitPullRequest, + Play, + Star, +} from "lucide-react"; +import { CodeTree } from "@/modules/repository/CodeTree"; -import { - DropdownMenuCheckboxItem, - DropdownMenuSeparator, -} from "@/components/ui/dropdown-menu"; - -import { useApi } from "@/hooks/useApi"; -import { useNavigate } from "react-router-dom"; -interface Repository { - id: string; - name: string; - url: string; - description: string; - createdOnUtc: string; -} +export const RepositoryPage: React.FC = () => { -export const RepositoriesPage = () => { - const navigate = useNavigate(); - const { data } = useApi("repo"); return ( -
-
-
Bugs
-
- - - - - - Filter by - - Open - In Progress - Closed - - - + +
- - - - - - Name - Description - - Actions - - - - - {data?.value.map((repo) => ( - - {repo.name} - {repo.description} - - - - - - - Actions - - navigate(`/repositories/${repo.id}`)} - > - View - - - navigate(`/repositories/${repo.id}/edit`) - } - > - Edit - - Delete - - - - - ))} - -
-
- - - {data?.value.length} repositories - - -
+ + + + + Code + + + + Issues + + + + Pull requests + + + + Actions + + + + + + + + + Projects + + + + + +
); }; diff --git a/src/SearchBugs.Ui/src/pages/index.ts b/src/SearchBugs.Ui/src/pages/index.ts index 9378432..35405b9 100644 --- a/src/SearchBugs.Ui/src/pages/index.ts +++ b/src/SearchBugs.Ui/src/pages/index.ts @@ -12,4 +12,5 @@ export * from './LoginPage'; export * from './RegisterPage'; export * from './SettingPage'; export * from './BugAddPage'; -export * from './CreateProjectPage'; \ No newline at end of file +export * from './CreateProjectPage'; +export * from './ProfilePage'; \ No newline at end of file diff --git a/src/SearchBugs.Ui/tsconfig.app.json b/src/SearchBugs.Ui/tsconfig.app.json index 5534c75..4514269 100644 --- a/src/SearchBugs.Ui/tsconfig.app.json +++ b/src/SearchBugs.Ui/tsconfig.app.json @@ -31,6 +31,7 @@ "@/lib/*": ["src/lib/*"], "@/types/*": ["src/types/*"], "@/styles/*": ["src/styles/*"], + "@/modules/*": ["src/modules/*"], } }, "include": ["src"],