Skip to content

Commit

Permalink
Merge pull request #135 from kamranahmedse/master
Browse files Browse the repository at this point in the history
Create a new pull request by comparing changes across two branches
  • Loading branch information
GulajavaMinistudio authored May 8, 2024
2 parents 7d5dd45 + 8ab7f2c commit 18656f9
Show file tree
Hide file tree
Showing 20 changed files with 346 additions and 245 deletions.
76 changes: 43 additions & 33 deletions src/components/Activity/ActivityStream.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { getRelativeTimeString } from '../../lib/date';
import type { ResourceType } from '../../lib/resource-progress';
import { EmptyStream } from './EmptyStream';
import { ActivityTopicsModal } from './ActivityTopicsModal.tsx';
import {Book, BookOpen, ChevronsDown, ChevronsDownUp, ChevronsUp, ChevronsUpDown} from 'lucide-react';
import { ChevronsDown, ChevronsUp } from 'lucide-react';
import { ActivityTopicTitles } from './ActivityTopicTitles.tsx';

export const allowedActivityActionType = [
'in_progress',
Expand All @@ -21,7 +22,7 @@ export type UserStreamActivity = {
resourceSlug?: string;
isCustomResource?: boolean;
actionType: AllowedActivityActionType;
topicIds?: string[];
topicTitles?: string[];
createdAt: Date;
updatedAt: Date;
};
Expand All @@ -38,7 +39,9 @@ export function ActivityStream(props: ActivityStreamProps) {
useState<UserStreamActivity | null>(null);

const sortedActivities = activities
.filter((activity) => activity?.topicIds && activity.topicIds.length > 0)
.filter(
(activity) => activity?.topicTitles && activity.topicTitles.length > 0,
)
.sort((a, b) => {
return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
})
Expand All @@ -57,8 +60,8 @@ export function ActivityStream(props: ActivityStreamProps) {
resourceId={selectedActivity.resourceId}
resourceType={selectedActivity.resourceType}
isCustomResource={selectedActivity.isCustomResource}
topicIds={selectedActivity.topicIds || []}
topicCount={selectedActivity.topicIds?.length || 0}
topicTitles={selectedActivity.topicTitles || []}
topicCount={selectedActivity.topicTitles?.length || 0}
actionType={selectedActivity.actionType}
/>
)}
Expand All @@ -73,7 +76,7 @@ export function ActivityStream(props: ActivityStreamProps) {
resourceTitle,
actionType,
updatedAt,
topicIds,
topicTitles,
isCustomResource,
} = activity;

Expand All @@ -96,7 +99,7 @@ export function ActivityStream(props: ActivityStreamProps) {
</a>
);

const topicCount = topicIds?.length || 0;
const topicCount = topicTitles?.length || 0;

const timeAgo = (
<span className="ml-1 text-xs text-gray-400">
Expand All @@ -108,32 +111,35 @@ export function ActivityStream(props: ActivityStreamProps) {
<li key={_id} className="py-2 text-sm text-gray-600">
{actionType === 'in_progress' && (
<>
Started{' '}
<button
className="font-medium underline underline-offset-2 hover:text-black"
onClick={() => setSelectedActivity(activity)}
>
{topicCount} topic{topicCount > 1 ? 's' : ''}
</button>{' '}
in {resourceLinkComponent} {timeAgo}
<p className="mb-1">
Started&nbsp;{topicCount}&nbsp;topic
{topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;
{resourceLinkComponent}&nbsp;
{timeAgo}
</p>
<ActivityTopicTitles topicTitles={topicTitles || []} />
</>
)}
{actionType === 'done' && (
<>
Completed{' '}
<button
className="font-medium underline underline-offset-2 hover:text-black"
onClick={() => setSelectedActivity(activity)}
>
{topicCount} topic{topicCount > 1 ? 's' : ''}
</button>{' '}
in {resourceLinkComponent} {timeAgo}
<p className="mb-1">
Completed&nbsp;{topicCount}&nbsp;topic
{topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;
{resourceLinkComponent}&nbsp;
{timeAgo}
</p>
<ActivityTopicTitles topicTitles={topicTitles || []} />
</>
)}
{actionType === 'answered' && (
<>
Answered {topicCount} question{topicCount > 1 ? 's' : ''} in{' '}
{resourceLinkComponent} {timeAgo}
<p className="mb-1">
Answered&nbsp;{topicCount}&nbsp;question
{topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;
{resourceLinkComponent}&nbsp;
{timeAgo}
</p>
<ActivityTopicTitles topicTitles={topicTitles || []} />
</>
)}
</li>
Expand All @@ -146,16 +152,20 @@ export function ActivityStream(props: ActivityStreamProps) {

{activities.length > 10 && (
<button
className="mt-3 gap-2 flex items-center rounded-md border border-black pl-1.5 pr-2 py-1 text-xs uppercase tracking-wide text-black transition-colors hover:border-black hover:bg-black hover:text-white"
className="mt-3 flex items-center gap-2 rounded-md border border-black py-1 pl-1.5 pr-2 text-xs uppercase tracking-wide text-black transition-colors hover:border-black hover:bg-black hover:text-white"
onClick={() => setShowAll(!showAll)}
>
{showAll ? <>
<ChevronsUp size={14} />
Show less
</> : <>
<ChevronsDown size={14} />
Show more
</>}
{showAll ? (
<>
<ChevronsUp size={14} />
Show less
</>
) : (
<>
<ChevronsDown size={14} />
Show more
</>
)}
</button>
)}
</div>
Expand Down
43 changes: 43 additions & 0 deletions src/components/Activity/ActivityTopicTitles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useState } from 'react';
import { cn } from '../../lib/classname';

type ActivityTopicTitlesProps = {
topicTitles: string[];
className?: string;
onSelectActivity?: () => void;
};

export function ActivityTopicTitles(props: ActivityTopicTitlesProps) {
const { topicTitles, onSelectActivity, className } = props;

const [showAll, setShowAll] = useState(false);
const filteredTopicTitles = topicTitles.slice(
0,
showAll ? topicTitles.length : 3,
);

const shouldShowButton = topicTitles.length > 3;

return (
<div
className={cn(
'flex flex-wrap gap-1 text-sm font-normal text-gray-600',
className,
)}
>
{filteredTopicTitles.map((topicTitle, index) => (
<span key={index} className="rounded-md bg-gray-200 px-1">
{topicTitle}
</span>
))}
{shouldShowButton && (
<button
onClick={() => setShowAll(!showAll)}
className="text-gray-600 underline underline-offset-2 hover:text-black"
>
{showAll ? '- Show less' : `+${topicTitles.length - 3} more`}
</button>
)}
</div>
);
}
56 changes: 4 additions & 52 deletions src/components/Activity/ActivityTopicsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type ActivityTopicDetailsProps = {
resourceId: string;
resourceType: ResourceType | 'question';
isCustomResource?: boolean;
topicIds: string[];
topicTitles: string[];
topicCount: number;
actionType: AllowedActivityActionType;
onClose: () => void;
Expand All @@ -22,56 +22,12 @@ export function ActivityTopicsModal(props: ActivityTopicDetailsProps) {
resourceId,
resourceType,
isCustomResource,
topicIds = [],
topicTitles = [],
topicCount,
actionType,
onClose,
} = props;

const [isLoading, setIsLoading] = useState(true);
const [topicTitles, setTopicTitles] = useState<Record<string, string>>({});
const [error, setError] = useState<string | null>(null);

const loadTopicTitles = async () => {
setIsLoading(true);
setError(null);

const { response, error } = await httpPost(
`${import.meta.env.PUBLIC_API_URL}/v1-get-topic-titles`,
{
resourceId,
resourceType,
isCustomResource,
topicIds,
},
);

if (error || !response) {
setError(error?.message || 'Failed to load topic titles');
setIsLoading(false);
return;
}

setTopicTitles(response);
setIsLoading(false);
};

useEffect(() => {
loadTopicTitles().finally(() => {
setIsLoading(false);
});
}, []);

if (isLoading || error) {
return (
<ModalLoader
error={error!}
text={'Loading topics..'}
isLoading={isLoading}
/>
);
}

let pageUrl = '';
if (resourceType === 'roadmap') {
pageUrl = isCustomResource ? `/r/${resourceId}` : `/${resourceId}`;
Expand All @@ -85,8 +41,6 @@ export function ActivityTopicsModal(props: ActivityTopicDetailsProps) {
<Modal
onClose={() => {
onClose();
setError(null);
setIsLoading(false);
}}
>
<div className={`popup-body relative rounded-lg bg-white p-4 shadow`}>
Expand All @@ -108,9 +62,7 @@ export function ActivityTopicsModal(props: ActivityTopicDetailsProps) {
</a>
</span>
<ul className="flex max-h-[50vh] flex-col gap-1 overflow-y-auto max-md:max-h-full">
{topicIds.map((topicId) => {
const topicTitle = topicTitles[topicId] || 'Unknown Topic';

{topicTitles.map((topicTitle) => {
const ActivityIcon =
actionType === 'done'
? Check
Expand All @@ -119,7 +71,7 @@ export function ActivityTopicsModal(props: ActivityTopicDetailsProps) {
: Check;

return (
<li key={topicId} className="flex items-start gap-2">
<li key={topicTitle} className="flex items-start gap-2">
<ActivityIcon
strokeWidth={3}
className="relative top-[4px] text-green-500"
Expand Down
2 changes: 1 addition & 1 deletion src/components/Activity/EmptyStream.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export function EmptyStream() {
return (
<div className="rounded-md">
<div className="flex flex-col items-center p-7 text-center">
<List className="mb-2 h-[60px] w-[60px] opacity-10 sm:h-[120px] sm:w-[120px]" />
<List className="mb-4 h-[60px] w-[60px] opacity-10 sm:h-[60px] sm:w-[60px]" />

<h2 className="text-lg font-bold sm:text-xl">No Activities</h2>
<p className="my-1 max-w-[400px] text-balance text-sm text-gray-500 sm:my-2 sm:text-base">
Expand Down
23 changes: 14 additions & 9 deletions src/components/CreateTeam/CreateTeamForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { pageProgressMessage } from '../../stores/page';
import type { TeamResourceConfig } from './RoadmapSelector';
import { Step3 } from './Step3';
import { Step4 } from './Step4';
import {useToast} from "../../hooks/use-toast";
import { useToast } from '../../hooks/use-toast';

export interface TeamDocument {
_id?: string;
Expand All @@ -22,6 +22,7 @@ export interface TeamDocument {
linkedIn?: string;
};
type: ValidTeamType;
personalProgressOnly?: boolean;
canMemberSendInvite: boolean;
teamSize?: ValidTeamSize;
createdAt: Date;
Expand All @@ -40,10 +41,10 @@ export function CreateTeamForm() {

async function loadTeam(
teamIdToFetch: string,
requiredStepIndex: number | string
requiredStepIndex: number | string,
) {
const { response, error } = await httpGet<TeamDocument>(
`${import.meta.env.PUBLIC_API_URL}/v1-get-team/${teamIdToFetch}`
`${import.meta.env.PUBLIC_API_URL}/v1-get-team/${teamIdToFetch}`,
);

if (error || !response) {
Expand All @@ -70,7 +71,7 @@ export function CreateTeamForm() {

async function loadTeamResourceConfig(teamId: string) {
const { error, response } = await httpGet<TeamResourceConfig>(
`${import.meta.env.PUBLIC_API_URL}/v1-get-team-resource-config/${teamId}`
`${import.meta.env.PUBLIC_API_URL}/v1-get-team-resource-config/${teamId}`,
);
if (error || !Array.isArray(response)) {
console.error(error);
Expand All @@ -96,7 +97,7 @@ export function CreateTeamForm() {
}, [teamId, queryStepIndex]);

const [selectedTeamType, setSelectedTeamType] = useState<ValidTeamType>(
team?.type || 'company'
team?.type || 'company',
);

const [completedSteps, setCompletedSteps] = useState([0]);
Expand Down Expand Up @@ -191,13 +192,17 @@ export function CreateTeamForm() {

return (
<div className={'mx-auto max-w-[700px] py-1 md:py-6'}>
<div className={'mb-3 md:mb-8 pb-3 md:pb-0 border-b md:border-b-0 flex flex-col items-start md:items-center'}>
<h1 className={'text-xl md:text-4xl font-bold'}>Create Team</h1>
<p className={'mt-1 md:mt-2 text-sm md:text-base text-gray-500'}>
<div
className={
'mb-3 flex flex-col items-start border-b pb-3 md:mb-8 md:items-center md:border-b-0 md:pb-0'
}
>
<h1 className={'text-xl font-bold md:text-4xl'}>Create Team</h1>
<p className={'mt-1 text-sm text-gray-500 md:mt-2 md:text-base'}>
Complete the steps below to create your team
</p>
</div>
<div className="mb-8 mt-8 hidden sm:flex w-full">
<div className="mb-8 mt-8 hidden w-full sm:flex">
<Stepper
activeIndex={stepIndex}
completeSteps={completedSteps}
Expand Down
Loading

0 comments on commit 18656f9

Please sign in to comment.