feature/improve-tag-organization-ux #8

Merged
pkartch merged 22 commits from feature/improve-tag-organization-ux into main 2026-01-17 06:13:39 +00:00
2 changed files with 77 additions and 72 deletions
Showing only changes of commit d12021ffdc - Show all commits

View File

@@ -252,19 +252,23 @@ function RecipeDetail() {
<div className="tags-display-inline"> <div className="tags-display-inline">
<strong>Tags:</strong> <strong>Tags:</strong>
{recipe.tags && recipe.tags.length > 0 ? ( {recipe.tags && recipe.tags.length > 0 ? (
recipe.tags.map(tag => ( recipe.tags.map(tagItem => {
<span key={tag} className="tag-chip-inline"> // Handle both string tags and object tags from API
{tag} const tagName = typeof tagItem === 'string' ? tagItem : tagItem.tag?.name || tagItem.name;
<button return (
onClick={() => handleRemoveTag(tag)} <span key={tagName} className="tag-chip-inline">
disabled={savingTags} {tagName}
className="tag-remove-btn-inline" <button
title="Remove tag" onClick={() => handleRemoveTag(tagName)}
> disabled={savingTags}
× className="tag-remove-btn-inline"
</button> title="Remove tag"
</span> >
)) ×
</button>
</span>
);
})
) : ( ) : (
<span className="no-tags-inline"></span> <span className="no-tags-inline"></span>
)} )}

View File

@@ -107,65 +107,9 @@ function RecipeImport() {
/> />
</div> </div>
<div className="import-actions"> <button type="submit" disabled={loading}>
<button type="submit" disabled={loading}> {loading ? 'Importing...' : 'Import Recipe'}
{loading ? 'Importing...' : 'Import Recipe'} </button>
</button>
<div className="import-tags-inline">
<label>Tags:</label>
<div className="import-tags-display">
{selectedTags.length > 0 ? (
selectedTags.map(tag => (
<span key={tag} className="tag-chip-inline">
{tag}
<button
type="button"
onClick={() => handleRemoveTag(tag)}
className="tag-remove-btn-inline"
title="Remove tag"
>
×
</button>
</span>
))
) : (
<span className="no-tags-inline">None</span>
)}
</div>
<div className="import-tag-input">
<input
ref={tagInputRef}
type="text"
value={tagInput}
onChange={(e) => setTagInput(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
handleAddTag();
}
}}
placeholder="Add tag..."
list="import-available-tags"
className="tag-input-small"
/>
<button
type="button"
onClick={handleAddTag}
disabled={!tagInput.trim()}
className="tag-add-btn-small"
title="Add tag"
>
+
</button>
<datalist id="import-available-tags">
{availableTags.map(tag => (
<option key={tag.id} value={tag.name} />
))}
</datalist>
</div>
</div>
</div>
</form> </form>
{error && <div className="error">{error}</div>} {error && <div className="error">{error}</div>}
@@ -211,6 +155,63 @@ function RecipeImport() {
</div> </div>
)} )}
{/* Tag Management Section */}
<div className="import-tags-section" style={{ marginTop: '2rem', marginBottom: '2rem' }}>
<h3>Add Tags</h3>
<div className="import-tags-inline">
<div className="import-tags-display">
{selectedTags.length > 0 ? (
selectedTags.map(tag => (
<span key={tag} className="tag-chip-inline">
{tag}
<button
type="button"
onClick={() => handleRemoveTag(tag)}
className="tag-remove-btn-inline"
title="Remove tag"
>
×
</button>
</span>
))
) : (
<span className="no-tags-inline">No tags yet</span>
)}
</div>
<div className="import-tag-input">
<input
ref={tagInputRef}
type="text"
value={tagInput}
onChange={(e) => setTagInput(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
e.preventDefault();
handleAddTag();
}
}}
placeholder="Add tag..."
list="import-available-tags"
className="tag-input-small"
/>
<button
type="button"
onClick={handleAddTag}
disabled={!tagInput.trim()}
className="tag-add-btn-small"
title="Add tag"
>
+
</button>
<datalist id="import-available-tags">
{availableTags.map(tag => (
<option key={tag.id} value={tag.name} />
))}
</datalist>
</div>
</div>
</div>
<button onClick={handleSave} disabled={loading}> <button onClick={handleSave} disabled={loading}>
Save Recipe Save Recipe
</button> </button>