Skip to content

Commit

Permalink
chore: repo card with story and test (#737)
Browse files Browse the repository at this point in the history
* chore: repo card with story and test

* fix comments

* fix coment

Co-authored-by: Victor Chukwuebuka Umeh <[email protected]>
  • Loading branch information
hdJerry and vyktoremario authored Nov 11, 2022
1 parent 4e0cceb commit 88d452c
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 0 deletions.
4 changes: 4 additions & 0 deletions solidjs-tailwind/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ Signals can live outside of components. Each relevant component subscribes to it

Demonstrates how to retrieve data from a third-party API by using `createResource`.

#### Other Resources

- [Solidjs Icons](https://www.npmjs.com/package/solid-icons)

## Installation

### CLI (Recommended)
Expand Down
2 changes: 2 additions & 0 deletions solidjs-tailwind/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
"@testing-library/jest-dom": "5.16.5",
"@typescript-eslint/parser": "5.41.0",
"autoprefixer": "10.4.12",
"dayjs": "^1.11.6",
"eslint": "8.26.0",
"eslint-plugin-solid": "0.7.4",
"eslint-plugin-unused-imports": "2.0.0",
"jsdom": "20.0.1",
"postcss": "8.4.18",
"prettier": "2.7.1",
"solid-icons": "^1.0.2",
"solid-testing-library": "0.3.0",
"storybook-addon-mock": "3.2.0",
"tailwindcss": "3.2.1",
Expand Down
17 changes: 17 additions & 0 deletions solidjs-tailwind/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions solidjs-tailwind/src/components/PrivacyBadge/PrivacyBadge.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { splitProps } from 'solid-js';

const PrivacyBadge = (props) => {
const [local] = splitProps(props, ['visibility']);
return (
<span class="py-0.5 px-2 text-xs rounded-xl text-gray-600 border border-gray-300 font-medium capitalize">
{local.visibility}
</span>
);
};

export default PrivacyBadge;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import PrivacyBadge from './PrivacyBadge';

export default {
title: 'Components/PrivacyBadge',
argTypes: {
visibility: {},
},
};

const Template = (args) => <PrivacyBadge {...args} />;

export const Default = Template.bind({});
Default.args = {
visibility: 'Public',
};
1 change: 1 addition & 0 deletions solidjs-tailwind/src/components/PrivacyBadge/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as PrivacyBadge } from './PrivacyBadge';
60 changes: 60 additions & 0 deletions solidjs-tailwind/src/components/RepoCard/RepoCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Link } from '@solidjs/router';
import { Show, splitProps } from 'solid-js';
import RepoMeta from '../RepoMeta/RepoMeta';
import { OcStar2 } from 'solid-icons/oc';
import PrivacyBadge from '../PrivacyBadge/PrivacyBadge';

const RepoCard = (props) => {
const [local] = splitProps(props, [
'name',
'description',
'primaryLanguage',
'stargazerCount',
'owner',
'isProfilePage',
'updatedAt',
'visibility',
]);
const repoNameWithOwnerLink = () =>
`${local.owner?.login || ''}/${local.name || ''}`;
const repoNameWithOwner = () =>
`${!local.isProfilePage ? `${local.owner?.login || ''}/` : ''}${
local.name || ''
}`;

return (
<div class="px-4 py-8 border-b border-gray-200 first-of-type:border-t flex justify-between flex-wrap md:flex-nowrap gap-x-4">
<div class="col-span-12 md:col-span-7 text-left">
<h3 class="mb-4">
<Link href={repoNameWithOwnerLink()}>
<span class="text-xl text-blue-600 font-semibold hover:underline mr-3">
{repoNameWithOwner()}
</span>
</Link>
<PrivacyBadge visibility={local.visibility} />
</h3>
<Show when={local.description}>
<div class="text-gray-600 text-sm max-w-prose">
{local.description}
</div>
</Show>
<RepoMeta
primaryLanguage={local.primaryLanguage}
stargazerCount={local.stargazerCount}
updatedAt={local.updatedAt}
/>
</div>
<div class="col-span-12 md:col-span-5 flex items-start md:justify-end mt-4 lg:mt-0">
<button class="inline-flex gap-2 items-center px-3 py-1 rounded-md bg-gray-100 bg-opacity-75 border border-gray-300 text-sm font-medium text-gray-800 hover:bg-gray-200 hover:bg-opacity-50">
<span class="-translate-x-1 -translate-y-[0.45rem]">
<OcStar2 size={2} />
</span>
<span class="ml-2">Star</span>
</button>
</div>
</div>
);
};


export default RepoCard;
51 changes: 51 additions & 0 deletions solidjs-tailwind/src/components/RepoCard/RepoCard.spec.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Router } from '@solidjs/router';
import { render } from 'solid-testing-library';
import { beforeEach, describe, expect, it } from 'vitest';
import RepoCard from './RepoCard';
import { repoCardProps } from './data';

describe('RepoCard for profilepage', () => {
let wrapper;
beforeEach(async () => {
wrapper = await render(() => (
<Router>
<RepoCard {...repoCardProps} />
</Router>
));
});

it('should mount', () => {
expect(wrapper).toBeTruthy();
});

it('a tag text should contain only name', async () => {
const repoName = await wrapper.getByText(repoCardProps.name);
expect(repoName).toBeVisible();
});
});
describe('RepoCard for non profile page', () => {
let wrapper;
const notProfileData = {
...repoCardProps,
isProfilePage: false,
};

beforeEach(async () => {
wrapper = await render(() => (
<Router>
<RepoCard {...notProfileData} />
</Router>
));
});

it('should mount', () => {
expect(wrapper).toBeTruthy();
});

it('a tag text should contain owner/name', async () => {
const repowithOwner = await wrapper.getByText(
`${notProfileData.owner.login}/${notProfileData.name}`
);
expect(repowithOwner).toBeVisible();
});
});
28 changes: 28 additions & 0 deletions solidjs-tailwind/src/components/RepoCard/RepoCard.stories.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Router } from '@solidjs/router';
import RepoCard from './RepoCard';
import { repoCardProps } from './data';

export default {
title: 'Components/Repo Card',
component: RepoCard,
argTypes: {
name: {},
description: {},
primaryLanguage: {},
owner: {},
isProfilePage: {},
stargazerCount: {},
},
};

const Template = (args) => (
<Router>
<RepoCard {...args} />
</Router>
);

export const Default = Template.bind({});

Default.args = {
...repoCardProps,
};
16 changes: 16 additions & 0 deletions solidjs-tailwind/src/components/RepoCard/data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const repoCardProps = {
name: 'cowrywise-unsplashed',
owner: {
login: 'hdjerry',
},
isProfilePage: true,
stargazerCount: 2,
visibility: 'Private',
primaryLanguage: {
color: 'yellow',
name: 'Javascript',
},
description:
'Using basic pull requests to add your name and github link to BE A MEMBER of ZTM-ng',
updatedAt: '23 Sep 2020',
};
1 change: 1 addition & 0 deletions solidjs-tailwind/src/components/RepoCard/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as RepoCard } from './RepoCard';
40 changes: 40 additions & 0 deletions solidjs-tailwind/src/components/RepoMeta/RepoMeta.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Show, splitProps } from 'solid-js';
import { OcStar2 } from 'solid-icons/oc';
import getFriendlyDate from '../../helper/getFriendlyDate';

const RepoMeta = (props) => {
const [local] = splitProps(props, [
'primaryLanguage',
'stargazerCount',
'updatedAt',
]);

const friendlyUpdatedAt = () => getFriendlyDate(local.updatedAt);

return (
<div class="flex mt-4 text-xs text-gray-600 space-x-4">
<Show when={local.primaryLanguage}>
<div class="language flex items-center gap-3">
<span
style={{
'background-color': local.primaryLanguage.color || '#ccc',
}}
class="w-3 h-3 rounded-full"
/>
<span>{local.primaryLanguage.name}</span>
</div>
</Show>
<Show when={local.stargazerCount}>
<div class="language flex items-baseline gap-3">
<span class="-translate-x-1 -translate-y-[0.65rem]">
<OcStar2 size={2} />
</span>
<span>{local.stargazerCount}</span>
</div>
</Show>
<span class="text-subtitle">Updated {friendlyUpdatedAt()}</span>
</div>
);
};

export default RepoMeta;
1 change: 1 addition & 0 deletions solidjs-tailwind/src/components/RepoMeta/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as RepoMeta } from './RepoMeta';
3 changes: 3 additions & 0 deletions solidjs-tailwind/src/components/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export * from './CounterExample';
export * from './FetchExample';
export * from './RepoMeta';
export * from './RepoCard';
export * from './PrivacyBadge';
export * from './Header';
export * from './UserDropdown';
export { default as PageHeader } from './PageHeader';
Expand Down
12 changes: 12 additions & 0 deletions solidjs-tailwind/src/helper/getFriendlyDate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';

const getFriendlyDate = (dateStr) => {
dayjs.extend(relativeTime);

const formatted = dayjs(dateStr).fromNow();

return formatted;
};

export default getFriendlyDate;

0 comments on commit 88d452c

Please sign in to comment.