Skip to content
Open
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
70 changes: 70 additions & 0 deletions web/src/features/demo/components/CounterDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use client'

import { Button } from '@/shared/ui/button'
import { Box } from '@/shared/ui/box'
import { PageHeader } from '@/shared/ui/page-header'
import { CalculatorIcon } from '@/shared/ui/icons'
import { useAppDispatch, useAppSelector } from '@/shared/stores/store'
import { increment, decrement, incrementByAmount, reset } from '../stores/counterSlice'
import { useTranslations } from 'next-intl'

export function CounterDemo() {
const t = useTranslations('counter')
const count = useAppSelector((state) => state.counter.value)
const dispatch = useAppDispatch()

return (
<div className="max-w-2xl mx-auto">
<PageHeader
icon={<CalculatorIcon size={24} />}
iconClassName="bg-indigo-500/15 text-indigo-600 dark:bg-indigo-500/20 dark:text-indigo-400"
title={t('title')}
description={t('description')}
/>

<Box size="lg">
<div className="space-y-6">
<div className="text-center">
<div className="text-6xl font-bold text-primary mb-6">
{count}
</div>
</div>

<div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
<Button
onClick={() => dispatch(increment())}
variant="default"
className="w-full"
>
{t('increment')}
</Button>

<Button
onClick={() => dispatch(decrement())}
variant="outline"
className="w-full"
>
{t('decrement')}
</Button>

<Button
onClick={() => dispatch(incrementByAmount(5))}
variant="secondary"
className="w-full"
>
{t('incrementBy5')}
</Button>

<Button
onClick={() => dispatch(reset())}
variant="destructive"
className="w-full"
>
{t('reset')}
</Button>
</div>
</div>
</Box>
</div>
)
}
97 changes: 97 additions & 0 deletions web/src/features/demo/components/MultiFileUploadDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
'use client';

import React, { useState } from 'react';
import { useTranslations } from 'next-intl';
import { MultiFileUpload, FileData } from '@/shared/ui/multi-file-upload';
import { Box } from '@/shared/ui/box';
import { Button } from '@/shared/ui/button';
import { PageHeader } from '@/shared/ui/page-header';
import { ImageIcon } from '@/shared/ui/icons';


export function MultiFileUploadDemo() {
const t = useTranslations('multiFileUploadDemo');
const tMultiUpload = useTranslations('multiFileUpload');
const [files, setFiles] = useState<FileData[]>([]);

const handleFilesChange = (newFiles: FileData[]) => {
setFiles(newFiles);
console.log('Files changed:', newFiles);
};

const handleClearAll = () => {
setFiles([]);
};


const getSelectedFilesText = () => {
const plural = files.length === 1 ? '' : 's';
return t('selectedFiles', { count: files.length, plural });
};


return (
<div className="max-w-6xl mx-auto">
<PageHeader
icon={<ImageIcon size={24} />}
iconClassName="bg-purple-500/15 text-purple-600 dark:bg-purple-500/20 dark:text-purple-400"
title={t('title')}
description={t('description')}
/>

<div className="space-y-8">


{/* Multi File Upload Example */}
<Box size="lg">
<div className="space-y-6">
<MultiFileUpload
label={tMultiUpload('title')}
value={files}
onFilesChange={handleFilesChange}
maxFiles={8}
maxSize={5}
columns={{ sm: 2, md: 3, lg: 4, xl: 4 }}
className="w-full"
/>

{files.length > 0 && (
<div className="pt-4 border-t">
<div className="flex items-center justify-between">
<p className="text-sm text-muted-foreground">
{getSelectedFilesText()}
</p>
<Button variant="outline" onClick={handleClearAll}>
{t('clearAll')}
</Button>
</div>
</div>
)}

{/* Debug Section */}
{files.length > 0 && (
<>
<hr className="border-border" />
<div className="space-y-3">
<h3 className="font-semibold text-sm text-muted-foreground">{t('debugTitle')}</h3>
<pre className="text-xs bg-muted p-3 rounded-[0.75rem] overflow-auto">
{JSON.stringify(
files.map(file => ({
fileName: file.file?.name,
fileSize: file.file?.size,
fileType: file.type,
hasPreview: !!file.preview,
})),
null,
2
)}
</pre>
</div>
</>
)}
</div>
</Box>
</div>
</div>
);
}
175 changes: 175 additions & 0 deletions web/src/features/demo/components/PopupDemo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
'use client';

import { useState } from 'react';
import { Button } from '@/shared/ui/button';
import { Input } from '@/shared/ui/input';
import { Box } from '@/shared/ui/box';
import { PageHeader } from '@/shared/ui/page-header';
import { WindowIcon } from '@/shared/ui/icons';
import { usePopupActions } from '@/widgets/feedback-system';

export default function PopupDemo() {
const [customInput, setCustomInput] = useState('');
const { alert, confirm, confirmDelete, success, error, show, close } = usePopupActions();

const handleAlert = async () => {
await alert({
title: 'Information',
message: 'This is a simple alert popup with an OK button.'
});
console.log('Alert closed');
};

const handleConfirm = async () => {
const result = await confirm({
title: 'Confirmation Required',
message: 'Do you want to proceed with this action?',
confirmText: 'Yes, Proceed',
cancelText: 'Cancel'
});

if (result) {
success('Action confirmed successfully!');
} else {
console.log('Action cancelled');
}
};

const handleDelete = async () => {
const result = await confirmDelete('This action cannot be undone. Are you sure?');

if (result) {
success('Item deleted successfully!');
}
};

const handleCustomPopup = () => {
show({
title: 'Custom Popup',
size: 'lg',
children: (
<div className="space-y-4">
<p className="text-sm text-muted-foreground">
This is a custom popup with interactive content.
</p>
<Input
placeholder="Enter some text..."
value={customInput}
onChange={(e) => setCustomInput(e.target.value)}
/>
<div className="flex gap-2">
<Button
onClick={() => {
if (customInput.trim()) {
success(`You entered: "${customInput}"`);
setCustomInput('');
close();
} else {
error('Please enter some text first!');
}
}}
>
Submit
</Button>
<Button variant="outline" onClick={close}>
Cancel
</Button>
</div>
</div>
)
});
};

const handleTransparentPopup = () => {
show({
title: 'Transparent Background',
overlay: 'transparent',
children: (
<div className="space-y-4">
<p className="text-sm text-muted-foreground">
This popup has a transparent background. Click outside to close.
</p>
<Button onClick={close} className="w-full">
Close
</Button>
</div>
)
});
};

const handleFullScreenPopup = () => {
show({
title: 'Full Screen Content',
size: 'full',
children: (
<div className="space-y-6">
<p className="text-sm text-muted-foreground">
This popup takes up most of the screen space, perfect for forms or detailed content.
</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<Input placeholder="Field 1" />
<Input placeholder="Field 2" />
<Input placeholder="Field 3" />
<Input placeholder="Field 4" />
</div>
<div className="flex justify-end gap-2">
<Button variant="outline" onClick={close}>Cancel</Button>
<Button onClick={() => { success('Form submitted!'); close(); }}>
Save Changes
</Button>
</div>
</div>
)
});
};

return (
<div className="max-w-2xl mx-auto">
<PageHeader
icon={<WindowIcon size={24} />}
iconClassName="bg-orange-500/15 text-orange-600 dark:bg-orange-500/20 dark:text-orange-400"
title="Popup System Demo"
description="Interactive modal dialogs and popup components"
/>

<Box size="lg">
<div className="space-y-6">

<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<Button onClick={handleAlert} variant="outline">
Show Alert
</Button>

<Button onClick={handleConfirm} variant="outline">
Show Confirmation
</Button>

<Button onClick={handleDelete} variant="destructive">
Delete Confirmation
</Button>

<Button onClick={() => success('This is a success message!')} variant="outline">
Success Message
</Button>

<Button onClick={() => error('This is an error message!')} variant="outline">
Error Message
</Button>

<Button onClick={handleCustomPopup} variant="outline">
Custom Popup
</Button>

<Button onClick={handleTransparentPopup} variant="outline">
Transparent Background
</Button>

<Button onClick={handleFullScreenPopup} variant="outline">
Full Screen Popup
</Button>
</div>
</div>
</Box>
</div>
);
}
Loading