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
4 changes: 2 additions & 2 deletions client/src/modules/app/routes/auth-routes/v1/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
export default function getRoutesV1() {
const routes = [
<Route
key={ROUTES_V1.HOME}
path={ROUTES_V1.HOME}
key={`${ROUTES_V1.HOME}/*`}
path={`${ROUTES_V1.HOME}/*`}
element={
<Suspense fallback={<Loader size={32} secondary={LOADING} />}>
<HomePageLazyComponent />
Expand Down
15 changes: 11 additions & 4 deletions client/src/modules/app/routes/constants/routes.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
export enum ROUTES_PAGE_V1 {
HOME = 'home',
SETTINGS = 'settings',
}

export enum ROUTES_V1 {
HOME = '/v1/home',
SETTINGS = '/v1/settings',
SETTINGS_PROFILE = '/profile',
}

export enum ROUTES_PAGE_V1 {
HOME = 'home',
SETTINGS = 'settings',
export enum ROUTES_HOME_V1 {
PROJECT = '/:project_id',
}

export enum ROUTES_SETTINGS_V1 {
PROFILE = '/profile',
}
3 changes: 3 additions & 0 deletions client/src/modules/home/modules/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { lazy } from 'react';

export const ProjectLazyComponentV1 = lazy(() => import('./project/v1'));
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
import { useState } from 'react';
import { Box, Button, useTheme } from '@mui/material';
import { OutputBlockData } from '@editorjs/editorjs';
import A2ZTypography from '../../../../../../shared/components/atoms/typography';

const ParagraphBlock = ({ text }: { text: string }) => {
return (
<A2ZTypography
variant="body1"
text=""
props={{
dangerouslySetInnerHTML: { __html: text },
sx: { lineHeight: 1.8 },
}}
/>
);
Comment on lines +6 to +16
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The empty text="" prop passed to A2ZTypography when using dangerouslySetInnerHTML is unnecessary and could be confusing. When using dangerouslySetInnerHTML, you should omit the text prop entirely since it won't be used. This makes the component's API clearer.

Copilot uses AI. Check for mistakes.
};

const HeaderBlock = ({ level, text }: { level: number; text: string }) => {
const variant = level === 3 ? 'h5' : 'h4';
const component = level === 3 ? 'h3' : 'h2';
return (
<A2ZTypography
variant={variant}
component={component}
text=""
props={{
dangerouslySetInnerHTML: { __html: text },
sx: { fontWeight: 600, mb: 2, mt: 3 },
}}
/>
);
Comment on lines +19 to +32
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the ParagraphBlock, using text="" with dangerouslySetInnerHTML is unnecessary. Omit the text prop when using dangerouslySetInnerHTML.

Copilot uses AI. Check for mistakes.
};

const ImageBlock = ({ url, caption }: { url: string; caption: string }) => {
return (
<Box
sx={{
textAlign: 'center',
my: { xs: 2, md: 3 },
'& img': {
maxWidth: '100%',
borderRadius: 2,
height: 'auto',
},
}}
>
<img src={url} alt={caption} />
{caption && (
<A2ZTypography
variant="body2"
text={caption}
props={{
sx: {
color: 'text.secondary',
mt: 1,
},
}}
/>
)}
</Box>
);
};

const QuoteBlock = ({ text, caption }: { text: string; caption: string }) => {
const theme = useTheme();
return (
<Box
sx={{
bgcolor: 'action.hover',
borderLeft: `4px solid ${theme.palette.primary.main}`,
p: 2,
pl: 3,
my: { xs: 2, md: 3 },
borderRadius: 1,
}}
>
<A2ZTypography
variant="h6"
text={text}
props={{
sx: {
mb: caption ? 1 : 0,
fontStyle: 'italic',
},
}}
/>
{caption && (
<A2ZTypography
variant="body2"
text={caption}
props={{
sx: {
color: 'primary.main',
},
}}
/>
)}
</Box>
);
};

const ListBlock = ({ style, items }: { style: string; items: string[] }) => {
const Tag = style === 'ordered' ? 'ol' : 'ul';
const styleType = style === 'ordered' ? 'decimal' : 'disc';
return (
<Box
component={Tag}
sx={{
pl: 3,
listStyleType: styleType,
my: { xs: 2, md: 3 },
'& li': {
mb: 1,
},
}}
>
{items.map((item, i) => (
<li key={i}>
<A2ZTypography
variant="body1"
text=""
props={{
dangerouslySetInnerHTML: { __html: item },
}}
/>
</li>
Comment on lines +118 to +127
Copy link

Copilot AI Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using text="" with dangerouslySetInnerHTML is redundant. Omit the text prop when using dangerouslySetInnerHTML.

Copilot uses AI. Check for mistakes.
))}
</Box>
);
};

const CodeBlock = ({ code, language }: { code: string; language: string }) => {
const theme = useTheme();
const codeText = code || '';
const [copied, setCopied] = useState(false);

const handleCopy = async () => {
try {
await navigator.clipboard.writeText(codeText);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
setCopied(false);
}
};

return (
<Box
sx={{
bgcolor: theme.palette.mode === 'dark' ? 'grey.900' : 'grey.100',
color: 'text.primary',
p: 2,
borderRadius: 2,
overflow: 'auto',
position: 'relative',
my: { xs: 2, md: 3 },
}}
>
{language && (
<A2ZTypography
variant="caption"
text={language}
props={{
sx: {
position: 'absolute',
top: 8,
left: 8,
opacity: 0.7,
textTransform: 'uppercase',
},
}}
/>
)}
<Button
size="small"
onClick={handleCopy}
variant="outlined"
sx={{
position: 'absolute',
top: 8,
right: 8,
minWidth: 'auto',
px: 1.5,
}}
>
{copied ? 'Copied' : 'Copy'}
</Button>
<Box
component="pre"
sx={{
fontFamily: 'monospace',
mt: language ? 4 : 0,
whiteSpace: 'pre-wrap',
fontSize: '0.875rem',
lineHeight: 1.6,
}}
>
{codeText}
</Box>
</Box>
);
};

const ProjectContent = ({ block }: { block: OutputBlockData }) => {
const { type, data } = block || {};

switch (type) {
case 'paragraph':
return <ParagraphBlock text={data?.text ?? ''} />;
case 'header':
return <HeaderBlock level={data?.level ?? 2} text={data?.text ?? ''} />;
case 'image':
return (
<ImageBlock url={data?.file?.url ?? ''} caption={data?.caption ?? ''} />
);
case 'quote':
return (
<QuoteBlock text={data?.text ?? ''} caption={data?.caption ?? ''} />
);
case 'list':
return <ListBlock style={data?.style} items={data?.items || []} />;
case 'code':
return (
<CodeBlock code={data?.code ?? ''} language={data?.language ?? ''} />
);
default:
return null;
}
};

export default ProjectContent;
Loading