fix bus and translate to eus
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-12-31 10:31:49 +03:00
parent fdda45da27
commit a81b1a8579
8 changed files with 72 additions and 69 deletions

View File

@ -8,7 +8,7 @@
**Этап:** Фаза 1 (Frontend) завершена
**Фаза MVP:** Готов к тестированию базового функционала
**Последнее обновление:** 2025-12-29
**Последнее обновление:** 2025-12-31
---
@ -33,6 +33,8 @@
| 2025-12-29 | **Фаза 1:** Frontend — Модалка создания идеи |
| 2025-12-29 | **Фаза 1:** Frontend — Skeleton loader и empty state |
| 2025-12-29 | **Фаза 1:** Frontend — Удаление идей |
| 2025-12-31 | Исправлен баг: Select в inline-редактировании закрывался при клике (MenuProps.disablePortal) |
| 2025-12-31 | Локализация интерфейса на русский язык |
---

View File

@ -23,7 +23,7 @@ function App() {
Team Planner
</Typography>
<Typography variant="body1" color="text.secondary">
Backlog management for your team
Управление бэклогом идей команды
</Typography>
</Box>
<Button
@ -31,7 +31,7 @@ function App() {
startIcon={<Add />}
onClick={() => setCreateModalOpen(true)}
>
New Idea
Новая идея
</Button>
</Box>

View File

@ -18,17 +18,17 @@ import { useCreateIdea } from '../../hooks/useIdeas';
import type { CreateIdeaDto, IdeaStatus, IdeaPriority } from '../../types/idea';
const statusOptions: { value: IdeaStatus; label: string }[] = [
{ value: 'backlog', label: 'Backlog' },
{ value: 'todo', label: 'To Do' },
{ value: 'in_progress', label: 'In Progress' },
{ value: 'done', label: 'Done' },
{ value: 'backlog', label: 'Бэклог' },
{ value: 'todo', label: 'К выполнению' },
{ value: 'in_progress', label: 'В работе' },
{ value: 'done', label: 'Готово' },
];
const priorityOptions: { value: IdeaPriority; label: string }[] = [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
{ value: 'critical', label: 'Critical' },
{ value: 'low', label: 'Низкий' },
{ value: 'medium', label: 'Средний' },
{ value: 'high', label: 'Высокий' },
{ value: 'critical', label: 'Критичный' },
];
const initialFormData: CreateIdeaDto = {
@ -76,17 +76,17 @@ export function CreateIdeaModal() {
fullWidth
>
<form onSubmit={handleSubmit}>
<DialogTitle>Create New Idea</DialogTitle>
<DialogTitle>Новая идея</DialogTitle>
<DialogContent>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2, mt: 1 }}>
{createIdea.isError && (
<Alert severity="error">
Failed to create idea. Please try again.
Не удалось создать идею. Попробуйте снова.
</Alert>
)}
<TextField
label="Title"
label="Название"
value={formData.title}
onChange={(e) => handleChange('title', e.target.value)}
required
@ -94,7 +94,7 @@ export function CreateIdeaModal() {
/>
<TextField
label="Description"
label="Описание"
value={formData.description}
onChange={(e) => handleChange('description', e.target.value)}
multiline
@ -103,10 +103,10 @@ export function CreateIdeaModal() {
<Box sx={{ display: 'flex', gap: 2 }}>
<FormControl fullWidth>
<InputLabel>Status</InputLabel>
<InputLabel>Статус</InputLabel>
<Select
value={formData.status}
label="Status"
label="Статус"
onChange={(e) => handleChange('status', e.target.value)}
>
{statusOptions.map((opt) => (
@ -118,10 +118,10 @@ export function CreateIdeaModal() {
</FormControl>
<FormControl fullWidth>
<InputLabel>Priority</InputLabel>
<InputLabel>Приоритет</InputLabel>
<Select
value={formData.priority}
label="Priority"
label="Приоритет"
onChange={(e) => handleChange('priority', e.target.value)}
>
{priorityOptions.map((opt) => (
@ -134,57 +134,57 @@ export function CreateIdeaModal() {
</Box>
<TextField
label="Module"
label="Модуль"
value={formData.module}
onChange={(e) => handleChange('module', e.target.value)}
placeholder="e.g., Auth, Dashboard, API"
placeholder="например: Авторизация, Дашборд, API"
/>
<TextField
label="Target Audience"
label="Целевая аудитория"
value={formData.targetAudience}
onChange={(e) => handleChange('targetAudience', e.target.value)}
placeholder="Who is this for?"
placeholder="Для кого это?"
/>
<TextField
label="Pain Point"
label="Боль"
value={formData.pain}
onChange={(e) => handleChange('pain', e.target.value)}
multiline
rows={2}
placeholder="What problem does this solve?"
placeholder="Какую проблему это решает?"
/>
<TextField
label="AI Role"
label="Роль AI"
value={formData.aiRole}
onChange={(e) => handleChange('aiRole', e.target.value)}
multiline
rows={2}
placeholder="How can AI help with this?"
placeholder="Как AI может помочь с этим?"
/>
<TextField
label="Verification Method"
label="Способ проверки"
value={formData.verificationMethod}
onChange={(e) =>
handleChange('verificationMethod', e.target.value)
}
multiline
rows={2}
placeholder="How to verify this is done?"
placeholder="Как проверить, что это готово?"
/>
</Box>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleClose}>Отмена</Button>
<Button
type="submit"
variant="contained"
disabled={!formData.title || createIdea.isPending}
>
{createIdea.isPending ? 'Creating...' : 'Create'}
{createIdea.isPending ? 'Создание...' : 'Создать'}
</Button>
</DialogActions>
</form>

View File

@ -15,18 +15,18 @@ import { useModulesQuery } from '../../hooks/useIdeas';
import type { IdeaStatus, IdeaPriority } from '../../types/idea';
const statusOptions: { value: IdeaStatus; label: string }[] = [
{ value: 'backlog', label: 'Backlog' },
{ value: 'todo', label: 'To Do' },
{ value: 'in_progress', label: 'In Progress' },
{ value: 'done', label: 'Done' },
{ value: 'cancelled', label: 'Cancelled' },
{ value: 'backlog', label: 'Бэклог' },
{ value: 'todo', label: 'К выполнению' },
{ value: 'in_progress', label: 'В работе' },
{ value: 'done', label: 'Готово' },
{ value: 'cancelled', label: 'Отменено' },
];
const priorityOptions: { value: IdeaPriority; label: string }[] = [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
{ value: 'critical', label: 'Critical' },
{ value: 'low', label: 'Низкий' },
{ value: 'medium', label: 'Средний' },
{ value: 'high', label: 'Высокий' },
{ value: 'critical', label: 'Критичный' },
];
export function IdeasFilters() {
@ -52,7 +52,7 @@ export function IdeasFilters() {
>
<TextField
size="small"
placeholder="Search ideas..."
placeholder="Поиск идей..."
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
sx={{ minWidth: 200 }}
@ -68,16 +68,16 @@ export function IdeasFilters() {
/>
<FormControl size="small" sx={{ minWidth: 120 }}>
<InputLabel>Status</InputLabel>
<InputLabel>Статус</InputLabel>
<Select<IdeaStatus | ''>
value={filters.status ?? ''}
label="Status"
label="Статус"
onChange={(e) => {
const val = e.target.value;
setFilter('status', val === '' ? undefined : val);
}}
>
<MenuItem value="">All</MenuItem>
<MenuItem value="">Все</MenuItem>
{statusOptions.map((opt) => (
<MenuItem key={opt.value} value={opt.value}>
{opt.label}
@ -87,16 +87,16 @@ export function IdeasFilters() {
</FormControl>
<FormControl size="small" sx={{ minWidth: 120 }}>
<InputLabel>Priority</InputLabel>
<InputLabel>Приоритет</InputLabel>
<Select<IdeaPriority | ''>
value={filters.priority ?? ''}
label="Priority"
label="Приоритет"
onChange={(e) => {
const val = e.target.value;
setFilter('priority', val === '' ? undefined : val);
}}
>
<MenuItem value="">All</MenuItem>
<MenuItem value="">Все</MenuItem>
{priorityOptions.map((opt) => (
<MenuItem key={opt.value} value={opt.value}>
{opt.label}
@ -106,13 +106,13 @@ export function IdeasFilters() {
</FormControl>
<FormControl size="small" sx={{ minWidth: 120 }}>
<InputLabel>Module</InputLabel>
<InputLabel>Модуль</InputLabel>
<Select
value={filters.module ?? ''}
label="Module"
label="Модуль"
onChange={(e) => setFilter('module', e.target.value || undefined)}
>
<MenuItem value="">All</MenuItem>
<MenuItem value="">Все</MenuItem>
{modules.map((module) => (
<MenuItem key={module} value={module}>
{module}
@ -130,7 +130,7 @@ export function IdeasFilters() {
setSearchValue('');
}}
>
Clear
Сбросить
</Button>
)}
</Box>

View File

@ -82,6 +82,7 @@ export function EditableCell({
onKeyDown={handleKeyDown}
autoFocus
sx={{ minWidth: 100 }}
MenuProps={{ disablePortal: true }}
>
{options.map((opt) => (
<MenuItem key={opt.value} value={opt.value}>

View File

@ -62,7 +62,7 @@ export function IdeasTable() {
if (isError) {
return (
<Box sx={{ p: 4, textAlign: 'center' }}>
<Typography color="error">Failed to load ideas</Typography>
<Typography color="error">Не удалось загрузить идеи</Typography>
</Box>
);
}
@ -137,9 +137,9 @@ export function IdeasTable() {
}}
>
<Inbox sx={{ fontSize: 48, mb: 2, opacity: 0.5 }} />
<Typography variant="h6">No ideas yet</Typography>
<Typography variant="h6">Идей пока нет</Typography>
<Typography variant="body2">
Create your first idea to get started
Создайте первую идею, чтобы начать
</Typography>
</Box>
</TableCell>

View File

@ -30,7 +30,7 @@ const priorityColors: Record<
export const createColumns = (onDelete: (id: string) => void) => [
columnHelper.accessor('title', {
header: 'Title',
header: 'Название',
cell: (info) => (
<EditableCell
idea={info.row.original}
@ -44,7 +44,7 @@ export const createColumns = (onDelete: (id: string) => void) => [
size: 250,
}),
columnHelper.accessor('status', {
header: 'Status',
header: 'Статус',
cell: (info) => {
const status = info.getValue();
const label =
@ -65,7 +65,7 @@ export const createColumns = (onDelete: (id: string) => void) => [
size: 140,
}),
columnHelper.accessor('priority', {
header: 'Priority',
header: 'Приоритет',
cell: (info) => {
const priority = info.getValue();
const label =
@ -91,7 +91,7 @@ export const createColumns = (onDelete: (id: string) => void) => [
size: 120,
}),
columnHelper.accessor('module', {
header: 'Module',
header: 'Модуль',
cell: (info) => (
<EditableCell
idea={info.row.original}
@ -103,7 +103,7 @@ export const createColumns = (onDelete: (id: string) => void) => [
size: 120,
}),
columnHelper.accessor('targetAudience', {
header: 'Target Audience',
header: 'Целевая аудитория',
cell: (info) => (
<EditableCell
idea={info.row.original}
@ -115,7 +115,7 @@ export const createColumns = (onDelete: (id: string) => void) => [
size: 150,
}),
columnHelper.accessor('description', {
header: 'Description',
header: 'Описание',
cell: (info) => {
const value = info.getValue();
return (

View File

@ -1,16 +1,16 @@
import type { IdeaStatus, IdeaPriority } from '../../types/idea';
export const statusOptions: { value: IdeaStatus; label: string }[] = [
{ value: 'backlog', label: 'Backlog' },
{ value: 'todo', label: 'To Do' },
{ value: 'in_progress', label: 'In Progress' },
{ value: 'done', label: 'Done' },
{ value: 'cancelled', label: 'Cancelled' },
{ value: 'backlog', label: 'Бэклог' },
{ value: 'todo', label: 'К выполнению' },
{ value: 'in_progress', label: 'В работе' },
{ value: 'done', label: 'Готово' },
{ value: 'cancelled', label: 'Отменено' },
];
export const priorityOptions: { value: IdeaPriority; label: string }[] = [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
{ value: 'critical', label: 'Critical' },
{ value: 'low', label: 'Низкий' },
{ value: 'medium', label: 'Средний' },
{ value: 'high', label: 'Высокий' },
{ value: 'critical', label: 'Критичный' },
];