Add layout for overview panel in project details page (#3)
* Create layout for overview panel * Populate project details in overview panel * Add more types * Fix typo --------- Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
parent
348ff92fa9
commit
5a17747be2
37
packages/frontend/src/assets/activities.json
Normal file
37
packages/frontend/src/assets/activities.json
Normal file
@ -0,0 +1,37 @@
|
||||
[
|
||||
{
|
||||
"author": "Bob",
|
||||
"authorAvatar": "^",
|
||||
"createdAt": "2023-12-11T04:20:00",
|
||||
"branch": "main",
|
||||
"message": "Design integrate and tested"
|
||||
},
|
||||
{
|
||||
"author": "Alice",
|
||||
"authorAvatar": "^",
|
||||
"createdAt": "2023-12-11T04:20:00",
|
||||
"branch": "prod",
|
||||
"message": "Fix lint errors"
|
||||
},
|
||||
{
|
||||
"author": "Charlie",
|
||||
"authorAvatar": "^",
|
||||
"createdAt": "2023-12-11T04:20:00",
|
||||
"branch": "main",
|
||||
"message": "Sidebar changed"
|
||||
},
|
||||
{
|
||||
"author": "Roy",
|
||||
"authorAvatar": "^",
|
||||
"createdAt": "2023-12-11T04:20:00",
|
||||
"branch": "staging",
|
||||
"message": "Add style to the page"
|
||||
},
|
||||
{
|
||||
"author": "Brad",
|
||||
"authorAvatar": "^",
|
||||
"createdAt": "2023-12-11T04:20:00",
|
||||
"branch": "dev",
|
||||
"message": "404 not found"
|
||||
}
|
||||
]
|
@ -4,9 +4,13 @@
|
||||
"icon": "^",
|
||||
"title": "iglotools",
|
||||
"domain": "iglotools.com",
|
||||
"createdAt": "2023-12-07T04:20:00",
|
||||
"createdBy": "Bob",
|
||||
"deployment": "iglotools.snowball.com",
|
||||
"source": "feature/add-remote-control",
|
||||
"latestCommit": {
|
||||
"message": "Subscription added",
|
||||
"time": "2023-12-11T04:20:00",
|
||||
"createdAt": "2023-12-11T04:20:00",
|
||||
"branch": "main"
|
||||
}
|
||||
},
|
||||
@ -15,9 +19,13 @@
|
||||
"icon": "^",
|
||||
"title": "snowball-starter-kit",
|
||||
"domain": "snowball-starter-kit.com",
|
||||
"createdAt": "2023-12-04T04:20:00",
|
||||
"createdBy": "Erin",
|
||||
"deployment": "snowball-starter-kit.com",
|
||||
"source": "prod/add-docker-compose",
|
||||
"latestCommit": {
|
||||
"message": "404 added",
|
||||
"time": "2023-12-11T04:20:00",
|
||||
"createdAt": "2023-12-11T04:20:00",
|
||||
"branch": "staging"
|
||||
}
|
||||
},
|
||||
@ -26,9 +34,13 @@
|
||||
"icon": "^",
|
||||
"title": "passkeys-demo",
|
||||
"domain": "passkeys-demo.com",
|
||||
"createdAt": "2023-12-01T04:20:00",
|
||||
"createdBy": "Charlie",
|
||||
"deployment": "passkeys-demo.com",
|
||||
"source": "dev/style-page",
|
||||
"latestCommit": {
|
||||
"message": "Design system integrated",
|
||||
"time": "2023-12-11T04:20:00",
|
||||
"createdAt": "2023-12-01T04:20:00",
|
||||
"branch": "main"
|
||||
}
|
||||
},
|
||||
@ -37,9 +49,13 @@
|
||||
"icon": "^",
|
||||
"title": "watcher-tool",
|
||||
"domain": "azimuth-watcher.com",
|
||||
"createdAt": "2023-12-11T04:20:00",
|
||||
"createdBy": "Alice",
|
||||
"deployment": "azimuth-watcher.com",
|
||||
"source": "prod/fix-error",
|
||||
"latestCommit": {
|
||||
"message": "Listen for subscription",
|
||||
"time": "2023-12-10T04:20:00",
|
||||
"createdAt": "2023-12-09T04:20:00",
|
||||
"branch": "prod"
|
||||
}
|
||||
}
|
||||
|
33
packages/frontend/src/components/ActivityCard.tsx
Normal file
33
packages/frontend/src/components/ActivityCard.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
|
||||
import { relativeTime } from '../utils/time';
|
||||
|
||||
interface ActivityDetails {
|
||||
author: string;
|
||||
authorAvatar: string;
|
||||
createdAt: string;
|
||||
branch: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
interface ActivityCardProps {
|
||||
activity: ActivityDetails;
|
||||
}
|
||||
|
||||
const ActivityCard = ({ activity }: ActivityCardProps) => {
|
||||
return (
|
||||
<div className="flex hover:bg-gray-200 rounded mt-1">
|
||||
<div className="w-4">{activity.authorAvatar}</div>
|
||||
|
||||
<div className="grow text-sm text-gray-500">
|
||||
<p className="text-black">{activity.author}</p>
|
||||
<p className="text-xs">
|
||||
{relativeTime(activity.createdAt)} ^ {activity.branch}
|
||||
</p>
|
||||
<p>{activity.message}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ActivityCard;
|
57
packages/frontend/src/components/Overview.tsx
Normal file
57
packages/frontend/src/components/Overview.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
|
||||
import ActivityCard from './ActivityCard';
|
||||
import activityDetails from '../assets/activities.json';
|
||||
import { ProjectDetails } from '../types/project';
|
||||
import { relativeTime } from '../utils/time';
|
||||
|
||||
interface OverviewProps {
|
||||
project: ProjectDetails;
|
||||
}
|
||||
|
||||
const Overview = ({ project }: OverviewProps) => (
|
||||
<div className="grid grid-cols-5">
|
||||
<div className="col-span-3 p-2">
|
||||
<div className="flex items-center gap-2 p-2 ">
|
||||
<div>^</div>
|
||||
<div className="grow">
|
||||
<p className="text-sm text-gray-700">{project.title}</p>
|
||||
<p className="text-sm text-gray-400">{project.domain}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-between p-2 text-sm">
|
||||
<p>Domain</p>
|
||||
<button>Set up</button>
|
||||
</div>
|
||||
<div className="flex justify-between p-2 text-sm">
|
||||
<p>Source</p>
|
||||
<p>{project.source}</p>
|
||||
</div>
|
||||
<div className="flex justify-between p-2 text-sm">
|
||||
<p>deployment</p>
|
||||
<p>{project.deployment}</p>
|
||||
</div>
|
||||
<div className="flex justify-between p-2 text-sm">
|
||||
<p>Created</p>
|
||||
<p>
|
||||
{relativeTime(project.createdAt)} by {project.createdBy}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-2 p-2">
|
||||
<div className="flex justify-between">
|
||||
<p>Activity</p>
|
||||
<button className="text-xs bg-gray-300 rounded-full p-2">
|
||||
See all
|
||||
</button>
|
||||
</div>
|
||||
<div className="p-2">
|
||||
{activityDetails.map((activity, key) => {
|
||||
return <ActivityCard activity={activity} key={key} />;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Overview;
|
@ -1,19 +1,11 @@
|
||||
import React from 'react';
|
||||
import { DateTime } from 'luxon';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
interface projectDetails {
|
||||
icon: string;
|
||||
title: string;
|
||||
domain: string;
|
||||
id: number;
|
||||
latestCommit: {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
import { relativeTime } from '../utils/time';
|
||||
import { ProjectDetails } from '../types/project';
|
||||
|
||||
interface ProjectCardProps {
|
||||
project: projectDetails;
|
||||
project: ProjectDetails;
|
||||
}
|
||||
|
||||
const ProjectCard: React.FC<ProjectCardProps> = ({ project }) => {
|
||||
@ -32,7 +24,7 @@ const ProjectCard: React.FC<ProjectCardProps> = ({ project }) => {
|
||||
<div className="border-slate-200 border-t-2 border-solid p-4 text-gray-500 text-xs">
|
||||
<p>{project.latestCommit.message}</p>
|
||||
<p>
|
||||
{DateTime.fromISO(project.latestCommit.time).toRelative()} on{' '}
|
||||
{relativeTime(project.latestCommit.createdAt)} on{' '}
|
||||
{project.latestCommit.branch}
|
||||
</p>
|
||||
</div>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { relativeTime } from '../utils/time';
|
||||
|
||||
interface RepositoryDetails {
|
||||
title: string;
|
||||
@ -16,7 +17,7 @@ const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
|
||||
<div>^</div>
|
||||
<div className="grow">
|
||||
<p>{repository.title}</p>
|
||||
<p>{DateTime.fromISO(repository.updatedTime).toRelative()}</p>
|
||||
<p>{relativeTime(repository.updatedTime)}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,14 +1,13 @@
|
||||
import React from 'react';
|
||||
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
|
||||
|
||||
const Overview = () => (
|
||||
<div>
|
||||
Content of overview tab
|
||||
<p className="block">
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
import Overview from './Overview';
|
||||
import { ProjectDetails } from '../types/project';
|
||||
|
||||
interface ProjectTabsProps {
|
||||
project: ProjectDetails;
|
||||
}
|
||||
|
||||
const Deployments = () => (
|
||||
<div>
|
||||
Content of deployments tab
|
||||
@ -44,7 +43,7 @@ const Settings = () => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const ProjectTab = () => {
|
||||
const ProjectTabs = ({ project }: ProjectTabsProps) => {
|
||||
return (
|
||||
<Tabs
|
||||
selectedTabClassName={
|
||||
@ -59,7 +58,7 @@ const ProjectTab = () => {
|
||||
<Tab className={'p-2 cursor-pointer'}>Settings</Tab>
|
||||
</TabList>
|
||||
<TabPanel>
|
||||
<Overview />
|
||||
<Overview project={project} />
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<Deployments />
|
||||
@ -77,4 +76,4 @@ const ProjectTab = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectTab;
|
||||
export default ProjectTabs;
|
||||
|
@ -6,7 +6,7 @@ import TemplateCard from '../../components/TemplateCard';
|
||||
import RepositoryList from '../../components/RepositoryList';
|
||||
import ConnectAccount from '../../components/ConnectAccount';
|
||||
|
||||
const isGitAuth = true;
|
||||
const IS_GIT_AUTH = true;
|
||||
|
||||
const CreateProject = () => {
|
||||
return (
|
||||
@ -31,7 +31,7 @@ const CreateProject = () => {
|
||||
})}
|
||||
</div>
|
||||
<h5 className="mt-4 ml-4">Import a repository</h5>
|
||||
{isGitAuth ? <RepositoryList /> : <ConnectAccount />}
|
||||
{IS_GIT_AUTH ? <RepositoryList /> : <ConnectAccount />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
import HorizontalLine from '../../components/HorizontalLine';
|
||||
import projects from '../../assets/projects.json';
|
||||
import ProjectTab from '../../components/Tab';
|
||||
import ProjectTabs from '../../components/Tab';
|
||||
|
||||
const getProject = (id: number) => {
|
||||
return projects.find((project) => {
|
||||
@ -18,6 +18,8 @@ const Project = () => {
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-3xl h-full">
|
||||
{project ? (
|
||||
<>
|
||||
<div className="flex p-4 gap-4">
|
||||
<button onClick={() => navigate(-1)}>{'<'}</button>
|
||||
<h3 className="grow">{project?.title} </h3>
|
||||
@ -26,8 +28,12 @@ const Project = () => {
|
||||
</div>
|
||||
<HorizontalLine />
|
||||
<div className="p-4">
|
||||
<ProjectTab />
|
||||
<ProjectTabs project={project} />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<h4>Project not found</h4>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
15
packages/frontend/src/types/project.ts
Normal file
15
packages/frontend/src/types/project.ts
Normal file
@ -0,0 +1,15 @@
|
||||
export interface ProjectDetails {
|
||||
icon: string;
|
||||
title: string;
|
||||
domain: string;
|
||||
id: number;
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
deployment: string;
|
||||
source: string;
|
||||
latestCommit: {
|
||||
message: string;
|
||||
createdAt: string;
|
||||
branch: string;
|
||||
};
|
||||
}
|
11
packages/frontend/src/utils/time.ts
Normal file
11
packages/frontend/src/utils/time.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
/**
|
||||
* Converts an ISO 8601 formatted time to a human-readable relative time with respect to the current time.
|
||||
*
|
||||
* @param {string} time - The input time in ISO 8601 format.
|
||||
* @returns {string} - A human-readable relative time string.
|
||||
*/
|
||||
export const relativeTime = (time: string) => {
|
||||
return DateTime.fromISO(time).toRelative();
|
||||
};
|
Loading…
Reference in New Issue
Block a user