Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(): update extensions cards #2496

Merged
merged 14 commits into from
Nov 26, 2024
106 changes: 56 additions & 50 deletions extensions/apps/extensions/src/components/explore.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,79 @@
import React from 'react';
import AppList, { App } from '@akashaorg/design-system-components/lib/components/AppList';
import AppList from '@akashaorg/design-system-components/lib/components/AppList';
import Button from '@akashaorg/design-system-core/lib/components/Button';
import Card from '@akashaorg/design-system-core/lib/components/Card';
import Image from '@akashaorg/design-system-core/lib/components/Image';
import Stack from '@akashaorg/design-system-core/lib/components/Stack';
import Text from '@akashaorg/design-system-core/lib/components/Text';
import ExtensionCard, {
ExtensionCardProps,
} from '@akashaorg/design-system-components/lib/components/ExtensionCard';
import { ReactNode } from '@tanstack/react-router';
import { useTranslation } from 'react-i18next';
import { getExtensionTypeLabel } from '../utils/extension-utils';

type TLatestExtensionsCardProps = {
buttonLabel: string;
latestExtensionsLabel: string;
latestExtensions?: App[];
onViewAllClick: () => void;
};

export type TExploreProps = TLatestExtensionsCardProps & {
export type TExploreProps = {
titleLabel: string;
publicImgPath?: string;
assetExtension?: string;
sections: {
assetName?: string;
popularExtensions?: ExtensionCardProps[];
popularExtensionsLabel: string;
viewAllLabel: string;
cta: {
title: string;
description: string;
ctaNode: React.ReactNode;
}[];
action: ReactNode;
};
onViewAllClick: () => void;
};

export const Explore: React.FC<TExploreProps> = props => {
const {
titleLabel,
publicImgPath = '/images',
assetExtension = 'webp',
sections,
latestExtensionsLabel,
latestExtensions,
buttonLabel,
popularExtensions,
popularExtensionsLabel,
viewAllLabel,
cta,
onViewAllClick,
} = props;
const { t } = useTranslation('app-extensions');

return (
<Stack spacing="gap-y-4" customStyle="mb-2">
<Text variant="h5">{titleLabel}</Text>
{sections.map((section, idx) => (
<React.Fragment key={section.title + idx}>
{!!latestExtensions?.length && idx === 1 && (
<Card padding="p-4">
<Stack spacing="gap-y-4">
<Stack direction="row" align="center" justify="between">
<Text variant="h6">{latestExtensionsLabel}</Text>
<Button variant="text" label={buttonLabel} onClick={onViewAllClick} />
</Stack>
<AppList apps={latestExtensions} onLoadMore={() => null} />
</Stack>
</Card>
)}
<Card key={section.title + idx} padding="p-4">
<Stack spacing="gap-y-3">
{section.assetName && (
<Image
customStyle="object-contain rounded-2xl"
src={`${publicImgPath}/${section.assetName}.${assetExtension}`}
/>
)}
<Text variant="h6">{section.title}</Text>
<Text variant="body2">{section.description}</Text>
{section.ctaNode}
</Stack>
</Card>
</React.Fragment>
))}
{popularExtensions?.length > 0 && (
<ExtensionCard
coverImageSrc={popularExtensions[0]?.coverImageSrc}
displayName={popularExtensions[0]?.displayName}
applicationType={popularExtensions[0]?.applicationType}
extensionTypeLabel={t('{{extensionTypeLabel}}', {
extensionTypeLabel: getExtensionTypeLabel(popularExtensions[0]?.applicationType),
})}
author={popularExtensions[0]?.author}
description={popularExtensions[0]?.description}
featured={true}
action={popularExtensions[0]?.action}
/>
)}
{popularExtensions?.length > 1 && (
<Stack spacing="gap-y-4">
<Stack direction="row" align="center" spacing="gap-x-2">
<Text variant="h6">{popularExtensionsLabel}</Text>
<Button
variant="text"
size="md"
label={viewAllLabel}
onClick={onViewAllClick}
customStyle="ml-auto"
/>
</Stack>
<AppList apps={popularExtensions.slice(1)} onLoadMore={() => null} />
</Stack>
)}
<Card padding="p-4">
<Stack spacing="gap-y-3">
<Text variant="h6">{cta.title}</Text>
<Text variant="body2">{cta.description}</Text>
{cta.action}
</Stack>
</Card>
</Stack>
);
};
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React from 'react';
import AppList, { App } from '@akashaorg/design-system-components/lib/components/AppList';
import AppList from '@akashaorg/design-system-components/lib/components/AppList';
import Card from '@akashaorg/design-system-core/lib/components/Card';
import Image from '@akashaorg/design-system-core/lib/components/Image';
import Stack from '@akashaorg/design-system-core/lib/components/Stack';
import Text from '@akashaorg/design-system-core/lib/components/Text';
import { ExtensionCardProps } from '@akashaorg/design-system-components/lib/components/ExtensionCard';

export type TExtensionsHubProps = {
titleLabel: string;
publicImgPath?: string;
assetExtension?: string;
extensions?: App[];
extensions?: ExtensionCardProps[];
sections: {
assetName?: string;
title: string;
Expand Down
105 changes: 56 additions & 49 deletions extensions/apps/extensions/src/components/pages/explore.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React from 'react';
import Button from '@akashaorg/design-system-core/lib/components/Button';
import routes, { DEVELOPER_MODE, EXTENSIONS } from '../../routes';
import { useTranslation } from 'react-i18next';
import { useNavigate } from '@tanstack/react-router';
import { useRootComponentProps } from '@akashaorg/ui-awf-hooks';
import { transformSource, useRootComponentProps } from '@akashaorg/ui-awf-hooks';
import { ArrowLongRightIcon } from '@heroicons/react/24/outline';
import Button from '@akashaorg/design-system-core/lib/components/Button';
import { Explore } from '../explore';
import routes, { DEVELOPER_MODE, EXTENSIONS } from '../../routes';
import { AkashaAppApplicationType } from '@akashaorg/typings/lib/sdk/graphql-types-new';
import { getExtensionTypeLabel } from '../../utils/extension-utils';

export const ExplorePage: React.FC<unknown> = () => {
const navigate = useNavigate();
Expand Down Expand Up @@ -36,65 +38,70 @@ export const ExplorePage: React.FC<unknown> = () => {
});
};

const handleAppClick = (appId: string) => {
navigate({
to: '/info/$appId',
params: {
appId,
},
});
};

const handleCTAClick = () => {
navigate({
to: routes[DEVELOPER_MODE],
});
};
const latestExtensions = [];

//TODO: mock data
const popularExtensions = [
{
id: '',
coverImageSrc: null,
author: {
profileDID: 'k2t6wzhkhabz1ftv1zfwnlrzcz5yyg0fxyf580fkvzr22g8ra8fa8y7hpdz0jc',
name: 'AKASHA',
alternativeAvatars: null,
avatar: transformSource({
src: 'ipfs://bafkreidk5aoxy2bde5nc6w4l6slxos3lbj5n75y766irlrb7vnfxgv4hwu',
width: 192,
height: 192,
}),
nsfw: false,
},
displayName: t('Vibes Console'),
description: `${t("Dive into AKASHA WORLD's Vibes Console!")} 💫 ${t("Your spot to become a moderator, explore applicants, and curate content. Together, let's shape our vibrant community!")} 🌟🔍✨`,
applicationType: AkashaAppApplicationType.App,
},
];

return (
<Explore
titleLabel={t("What's new!")}
sections={[
{
assetName: t('vibes-console-explore'),
title: t('Vibes Console'),
description: `${t("Dive into AKASHA WORLD's Vibes Console!")} 💫 ${t("Your spot to become a moderator, explore applicants, and curate content. Together, let's shape our vibrant community!")} 🌟🔍✨`,
ctaNode: (
<Button
variant={isInstalled ? 'secondary' : 'primary'}
label={isInstalled ? t('Installed') : t('Open')}
customStyle="w-fit self-end"
onClick={() => handleButtonClick('@akashaorg/app-vibes-console')}
/>
),
},
{
title: t('Want to create your own extension?'),
description: t(
'Create awesome extensions, spark your imagination, and be part of an enthusiastic developer community!',
),
ctaNode: (
<Button
size="md"
variant="text"
iconDirection="right"
icon={<ArrowLongRightIcon />}
label={t('Start your journey')}
customStyle="w-fit self-end"
onClick={handleCTAClick}
/>
),
},
]}
latestExtensionsLabel={t('Latest Extensions')}
latestExtensions={latestExtensions.map(ext => ({
cta={{
title: t('Want to create your own extension?'),
description: t(
'Create awesome extensions, spark your imagination, and be part of an enthusiastic developer community!',
),
action: (
<Button
size="md"
variant="text"
iconDirection="right"
icon={<ArrowLongRightIcon />}
label={t('Start your journey')}
customStyle="w-fit self-end"
onClick={handleCTAClick}
/>
),
}}
popularExtensionsLabel={t('Popular Extensions')}
popularExtensions={popularExtensions.map(ext => ({
...ext,
extensionTypeLabel: t('{{extensionTypeLabel}}', {
extensionTypeLabel: getExtensionTypeLabel(ext?.applicationType),
}),
action: (
<Button variant="primary" label={t('Open')} onClick={() => handleAppClick(ext.id)} />
<Button
variant={isInstalled ? 'secondary' : 'primary'}
label={isInstalled ? t('Installed') : t('Open')}
onClick={() => handleButtonClick('@akashaorg/app-vibes-console')}
customStyle="w-fit self-end"
/>
),
}))}
buttonLabel={t('View All')}
viewAllLabel={t('View All')}
onViewAllClick={handleViewAllLatestExtensions}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ import Icon from '@akashaorg/design-system-core/lib/components/Icon';
import CopyToClipboard from '@akashaorg/design-system-core/lib/components/CopyToClipboard';
import ProfileAvatarButton from '@akashaorg/design-system-core/lib/components/ProfileAvatarButton';
import Pill from '@akashaorg/design-system-core/lib/components/Pill';
import { AkashaAppApplicationType } from '@akashaorg/typings/lib/sdk/graphql-types-new';
import { useInstalledExtensions } from '@akashaorg/ui-awf-hooks/lib/use-installed-extensions';
import { UninstallModal } from './uninstall-modal';
import AppCoverImage from './AppCoverImage';
import StackedAvatar from '@akashaorg/design-system-core/lib/components/StackedAvatar';
import { AppInfoNotificationCards } from '@akashaorg/design-system-components/lib/components/AppInfo/notification-cards';
import { getExtensionTypeLabel } from '../../../utils/extension-utils';

type InfoPageProps = {
appId: string;
Expand Down Expand Up @@ -150,22 +150,6 @@ export const InfoPage: React.FC<InfoPageProps> = ({ appId }) => {
const appData = selectAkashaApp(appReq.data);
const latestRelease = useMemo(() => selectLatestRelease(appReq.data), [appReq.data]);

const extensionTypeLabel = useMemo(() => {
if (!appData?.applicationType) {
return '';
}
switch (appData.applicationType) {
case AkashaAppApplicationType.App:
return t('App');
case AkashaAppApplicationType.Plugin:
return t('Plugin');
case AkashaAppApplicationType.Widget:
return t('Widget');
default:
return t('Other');
}
}, [appData?.applicationType, t]);

const coverImageSrc = useMemo(() => {
if (appData?.coverImage?.src) {
return transformSource(appData.coverImage)?.src;
Expand Down Expand Up @@ -228,7 +212,9 @@ export const InfoPage: React.FC<InfoPageProps> = ({ appId }) => {
}}
nsfw={appData.nsfw}
nsfwLabel={'NSFW'}
extensionTypeLabel={extensionTypeLabel}
extensionTypeLabel={t('{{extensionTypeLabel}}', {
extensionTypeLabel: getExtensionTypeLabel(appData?.applicationType),
})}
share={{ label: t('Share'), icon: <ShareIcon /> }}
report={{
label: t('Flag'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Spinner from '@akashaorg/design-system-core/lib/components/Spinner';
import { NetworkStatus } from '@apollo/client';
import ErrorLoader from '@akashaorg/design-system-core/lib/components/ErrorLoader';
import DefaultEmptyCard from '@akashaorg/design-system-components/lib/components/DefaultEmptyCard';
import { getExtensionTypeLabel } from '../../../../utils/extension-utils';

type DevInfoPageProps = {
devDid: string;
Expand Down Expand Up @@ -102,8 +103,27 @@ export const DevInfoPage = (props: DevInfoPageProps) => {
// @todo: we'll need to show the curated apps only. filtering will be made here
?.filter(() => true)
.map(app => ({
...app,
logoImage: transformSource(app.logoImage),
coverImageSrc: app?.coverImage?.src,
displayName: app?.displayName,
applicationType: app?.applicationType,
extensionTypeLabel: t('{{extensionTypeLabel}}', {
extensionTypeLabel: getExtensionTypeLabel(app?.applicationType),
}),
author: app.author
? {
profileDID: app.author?.akashaProfile?.did?.id,
name: app.author?.akashaProfile?.name,
avatar: transformSource(app.author?.akashaProfile?.avatar?.default),
alternativeAvatars: app.author?.akashaProfile?.avatar.alternatives?.map(alt =>
transformSource(alt),
),
nsfw: app.author?.akashaProfile?.nsfw,
}
: null,
description: app?.description,
defaultLabel: t('Default'),
nsfwLabel: t('NSFW'),
nsfw: app?.nsfw,
action: <Button onClick={handleAppOpen(app.name)} label={t('Open')} />,
})),
[appsReq.data, handleAppOpen, t],
Expand Down
Loading