Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/features/repo-list/index.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
.repo-list {
margin-left: 38px;

&__placeholder {
margin: 20px 0;
text-align: center;
}

&__tab {
width: 10rem;
margin-right: 10px;
}
}
49 changes: 42 additions & 7 deletions src/features/repo-list/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,64 @@
import React from "react";
import { StringParam, useQueryParam, withDefault } from "use-query-params";
import { Skeleton } from "antd";
import { Repo, Tabs } from "shared/components";
import { RepositoryAffiliation } from "models";
import { useReposQuery } from "./queries.gen";
import "./index.scss";

type Props = {
username: string;
};

const typesMap: Record<string, RepositoryAffiliation> = {
repositories: RepositoryAffiliation.Owner,
collabs: RepositoryAffiliation.Collaborator,
};

// FIXME: rename to UserRepoList? (coz - user as dep)

const RepoList = ({ username }: Props) => {
const { data } = useReposQuery({
variables: { login: username },
const [tab, setTab] = useQueryParam("tab", withDefault(StringParam, "repositories"));
const typeEnum = typesMap[tab];

const { data, loading } = useReposQuery({
variables: { login: username, ownerAffiliations: [typeEnum] },
});
const length = data?.user?.repositories.edges?.length;

return (
<div className="repo-list">
<Tabs className="repo-list__tabs">
<Tabs.Item name="Repositories" />
{Object.keys(typesMap).map((type) => (
<Tabs.Item
key={type}
name={type.charAt(0).toUpperCase() + type.slice(1)}
className="repo-list__tab"
active={tab === type}
onClick={() => setTab(type)}
/>
))}
</Tabs>

<div className="repo-list__items">
{data?.user?.repositories.edges?.map((edge, index) => (
// FIXME: destruct more elegant later
<Repo key={index} {...edge?.node} />
))}
{loading && (
<>
<Skeleton active />
<Skeleton active />
<Skeleton active />
</>
)}

{length !== 0 ? (
data?.user?.repositories.edges?.map((edge, index) => (
// FIXME: destruct more elegant later
<Repo key={index} {...edge?.node} />
))
) : (
<h2 className="repo-list__placeholder">
{username} doesn’t have any public repositories yet.
</h2>
)}
</div>
</div>
);
Expand Down
6 changes: 4 additions & 2 deletions src/features/repo-list/queries.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@ import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
export type ReposQueryVariables = Types.Exact<{
login: Types.Scalars['String'];
ownerAffiliations?: Types.Maybe<ReadonlyArray<Types.Maybe<Types.RepositoryAffiliation>>>;
}>;


export type ReposQuery = { readonly user?: Types.Maybe<{ readonly repositories: { readonly edges?: Types.Maybe<ReadonlyArray<Types.Maybe<{ readonly node?: Types.Maybe<{ readonly id: string, readonly name: string, readonly updatedAt: any, readonly viewerHasStarred: boolean, readonly url: any, readonly primaryLanguage?: Types.Maybe<{ readonly color?: Types.Maybe<string>, readonly name: string }> }> }>>> } }> };


export const ReposDocument = gql`
query Repos($login: String!) {
query Repos($login: String!, $ownerAffiliations: [RepositoryAffiliation]) {
user(login: $login) {
repositories(ownerAffiliations: OWNER, first: 50, orderBy: {field: PUSHED_AT, direction: DESC}) {
repositories(ownerAffiliations: $ownerAffiliations, first: 50, orderBy: {field: PUSHED_AT, direction: DESC}) {
edges {
node {
id
Expand Down Expand Up @@ -46,6 +47,7 @@ export const ReposDocument = gql`
* const { data, loading, error } = useReposQuery({
* variables: {
* login: // value for 'login'
* ownerAffiliations: // value for 'ownerAffiliations'
* },
* });
*/
Expand Down
4 changes: 2 additions & 2 deletions src/features/repo-list/queries.gql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
query Repos ($login: String!) {
query Repos ($login: String!, $ownerAffiliations: [RepositoryAffiliation]) {
user(login: $login) {
repositories(ownerAffiliations: OWNER, first: 50, orderBy: {field: PUSHED_AT, direction: DESC}) {
repositories(ownerAffiliations: $ownerAffiliations, first: 50, orderBy: {field: PUSHED_AT, direction: DESC}) {
edges {
node {
id
Expand Down
29 changes: 24 additions & 5 deletions src/features/user-info/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,40 @@
color: var(--clr-text);

&__img {
width: 100%;
border-radius: 10px;
min-width: 100%;

&-ava {
width: 100%;
border-radius: 10px;
}

&-placeholder {
min-width: 100%;
height: 0;
padding-bottom: 100%;
border-radius: 10px;
}
}

&__name {
margin: 15px 0;
margin-top: 15px;
margin-bottom: 5px;
}

&__username {
font-size: 18px;
font-weight: var(--fw--light);
line-height: 28px;
}

&__bio {
font-size: 20px;
font-size: 15px;
line-height: 28px;
}

// !!! FIXME: styles (enhance colors)
&__btn.follow {
&__btn.follow,
&__btn.edit {
display: block;
width: 100px;
height: 100%;
Expand Down
25 changes: 20 additions & 5 deletions src/features/user-info/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
import React from "react";
import { Button } from "antd";
import { useUserInfoQuery } from "./queries.gen";
import { Button, Skeleton } from "antd";
import { useCredentialsQuery, useUserInfoQuery } from "./queries.gen";
import "./index.scss";

type Props = {
username: string;
};

const UserInfo = ({ username }: Props) => {
const { data } = useUserInfoQuery({
const { data, loading } = useUserInfoQuery({
variables: { login: username },
});
const { login } = useCredentialsQuery().data?.viewer || {};

const { name, avatarUrl, bio } = data?.user || {};

return (
<div className="user-info">
<img className="user-info__img" src={avatarUrl} alt="user avatar"></img>
<div className="user-info__img">
{loading && (
<Skeleton.Avatar
className="user-info__img-placeholder"
active
shape={"square"}
/>
)}
<img className="user-info__img-ava" src={avatarUrl} alt=""></img>
</div>
<h1 className="user-info__name">{name}</h1>
<h4 className="user-info__username">{username}</h4>
<span className="user-info__bio">{bio}</span>
<Button className="user-info__btn follow">Follow</Button>
{login !== username ? (
<Button className="user-info__btn follow">Follow</Button>
) : (
<Button className="user-info__btn edit">Edit profile</Button>
)}
</div>
);
};
Expand Down
39 changes: 38 additions & 1 deletion src/features/user-info/queries.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ export type UserInfoQueryVariables = Types.Exact<{

export type UserInfoQuery = { readonly user?: Types.Maybe<{ readonly name?: Types.Maybe<string>, readonly avatarUrl: any, readonly bio?: Types.Maybe<string> }> };

export type CredentialsQueryVariables = Types.Exact<{ [key: string]: never; }>;


export type CredentialsQuery = { readonly viewer: { readonly login: string } };


export const UserInfoDocument = gql`
query UserInfo($login: String!) {
Expand Down Expand Up @@ -45,4 +50,36 @@ export function useUserInfoLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<U
}
export type UserInfoQueryHookResult = ReturnType<typeof useUserInfoQuery>;
export type UserInfoLazyQueryHookResult = ReturnType<typeof useUserInfoLazyQuery>;
export type UserInfoQueryResult = Apollo.QueryResult<UserInfoQuery, UserInfoQueryVariables>;
export type UserInfoQueryResult = Apollo.QueryResult<UserInfoQuery, UserInfoQueryVariables>;
export const CredentialsDocument = gql`
query Credentials {
viewer {
login
}
}
`;

/**
* __useCredentialsQuery__
*
* To run a query within a React component, call `useCredentialsQuery` and pass it any options that fit your needs.
* When your component renders, `useCredentialsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useCredentialsQuery({
* variables: {
* },
* });
*/
export function useCredentialsQuery(baseOptions?: Apollo.QueryHookOptions<CredentialsQuery, CredentialsQueryVariables>) {
return Apollo.useQuery<CredentialsQuery, CredentialsQueryVariables>(CredentialsDocument, baseOptions);
}
export function useCredentialsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<CredentialsQuery, CredentialsQueryVariables>) {
return Apollo.useLazyQuery<CredentialsQuery, CredentialsQueryVariables>(CredentialsDocument, baseOptions);
}
export type CredentialsQueryHookResult = ReturnType<typeof useCredentialsQuery>;
export type CredentialsLazyQueryHookResult = ReturnType<typeof useCredentialsLazyQuery>;
export type CredentialsQueryResult = Apollo.QueryResult<CredentialsQuery, CredentialsQueryVariables>;
6 changes: 6 additions & 0 deletions src/features/user-info/queries.gql
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,10 @@ query UserInfo ($login: String!) {
avatarUrl
bio
}
}

query Credentials {
viewer {
login
}
}
4 changes: 2 additions & 2 deletions src/pages/user/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ const UserPage = (props: Props) => {

return (
<Row className="page page-user">
<Col span={7} className="user-info">
<Col span={6} className="user-info">
<UserInfo username={username} />
</Col>
<Col span={17} className="repos">
<Col span={18} className="repos">
<RepoList username={username} />
</Col>
</Row>
Expand Down
1 change: 1 addition & 0 deletions src/shared/components/tabs/item/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
font-size: 19px;
line-height: 33px;
color: #000000;
text-align: left;
background: linear-gradient(270deg, rgba(238, 238, 238, 0.24) 35.11%, var(--clr-gray--100) 100%);
border: none;
border-radius: 5px;
Expand Down