Exercises filter by name
This commit is contained in:
@@ -46,6 +46,7 @@ const Profile: React.FC<ProfileProps> = ({ user, onLogout, lang, onLanguageChang
|
|||||||
const [showArchived, setShowArchived] = useState(false);
|
const [showArchived, setShowArchived] = useState(false);
|
||||||
const [editingExercise, setEditingExercise] = useState<ExerciseDef | null>(null);
|
const [editingExercise, setEditingExercise] = useState<ExerciseDef | null>(null);
|
||||||
const [isCreatingEx, setIsCreatingEx] = useState(false);
|
const [isCreatingEx, setIsCreatingEx] = useState(false);
|
||||||
|
const [exerciseNameFilter, setExerciseNameFilter] = useState('');
|
||||||
|
|
||||||
const exerciseTypeLabels: Record<ExerciseType, string> = {
|
const exerciseTypeLabels: Record<ExerciseType, string> = {
|
||||||
[ExerciseType.STRENGTH]: t('type_strength', lang),
|
[ExerciseType.STRENGTH]: t('type_strength', lang),
|
||||||
@@ -282,6 +283,17 @@ const Profile: React.FC<ProfileProps> = ({ user, onLogout, lang, onLanguageChang
|
|||||||
<Plus size={16} /> {t('create_exercise', lang)}
|
<Plus size={16} /> {t('create_exercise', lang)}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div className="bg-surface-container-high rounded-t-lg border-b border-outline-variant px-3 py-2">
|
||||||
|
<label className="text-[10px] text-on-surface-variant font-medium">{t('filter_by_name', lang) || 'Filter by name'}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={exerciseNameFilter}
|
||||||
|
onChange={(e) => setExerciseNameFilter(e.target.value)}
|
||||||
|
placeholder={t('type_to_filter', lang) || 'Type to filter...'}
|
||||||
|
className="w-full bg-transparent text-on-surface focus:outline-none"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-end gap-2">
|
<div className="flex items-center justify-end gap-2">
|
||||||
<label className="text-xs text-on-surface-variant">{t('show_archived', lang)}</label>
|
<label className="text-xs text-on-surface-variant">{t('show_archived', lang)}</label>
|
||||||
<input
|
<input
|
||||||
@@ -295,6 +307,7 @@ const Profile: React.FC<ProfileProps> = ({ user, onLogout, lang, onLanguageChang
|
|||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{exercises
|
{exercises
|
||||||
.filter(e => showArchived || !e.isArchived)
|
.filter(e => showArchived || !e.isArchived)
|
||||||
|
.filter(e => e.name.toLowerCase().includes(exerciseNameFilter.toLowerCase()))
|
||||||
.sort((a, b) => a.name.localeCompare(b.name))
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
.map(ex => (
|
.map(ex => (
|
||||||
<div key={ex.id} className={`p-3 rounded-lg flex justify-between items-center border border-outline-variant/20 ${ex.isArchived ? 'bg-surface-container-low opacity-60' : 'bg-surface-container-high'}`}>
|
<div key={ex.id} className={`p-3 rounded-lg flex justify-between items-center border border-outline-variant/20 ${ex.isArchived ? 'bg-surface-container-low opacity-60' : 'bg-surface-container-high'}`}>
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ const translations = {
|
|||||||
archive: 'Archive',
|
archive: 'Archive',
|
||||||
unarchive: 'Unarchive',
|
unarchive: 'Unarchive',
|
||||||
show_archived: 'Show Archived',
|
show_archived: 'Show Archived',
|
||||||
|
filter_by_name: 'Filter by name',
|
||||||
|
type_to_filter: 'Type to filter...',
|
||||||
profile_saved: 'Profile saved successfully',
|
profile_saved: 'Profile saved successfully',
|
||||||
},
|
},
|
||||||
ru: {
|
ru: {
|
||||||
@@ -300,6 +302,8 @@ const translations = {
|
|||||||
archive: 'Архив',
|
archive: 'Архив',
|
||||||
unarchive: 'Вернуть',
|
unarchive: 'Вернуть',
|
||||||
show_archived: 'Показать архивные',
|
show_archived: 'Показать архивные',
|
||||||
|
filter_by_name: 'Фильтр по названию',
|
||||||
|
type_to_filter: 'Введите для фильтрации...',
|
||||||
profile_saved: 'Профиль успешно сохранен',
|
profile_saved: 'Профиль успешно сохранен',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user