diff --git a/frontend/src/components/profile/ProfileModal.jsx b/frontend/src/components/profile/ProfileModal.jsx index a0c7bb9..6415d54 100644 --- a/frontend/src/components/profile/ProfileModal.jsx +++ b/frontend/src/components/profile/ProfileModal.jsx @@ -3,7 +3,7 @@ import PropTypes from "prop-types"; import { saveProfile, deleteProfile } from "../../api/api"; import Modal from "../ui/Modal"; import Alert from "../ui/Alert"; -import { Loader } from "lucide-react"; +import { Loader, ArrowUp, ArrowDown } from "lucide-react"; function unsanitize(text) { return text.replace(/\\:/g, ":").replace(/\\n/g, "\n"); @@ -30,6 +30,10 @@ function ProfileModal({ const [isDeleting, setIsDeleting] = useState(false); const [loading, setLoading] = useState(true); const [modalTitle, setModalTitle] = useState(""); + const [formatSortKey, setFormatSortKey] = useState("score"); + const [formatSortDirection, setFormatSortDirection] = useState("desc"); + const [tagSortKey, setTagSortKey] = useState("name"); + const [tagSortDirection, setTagSortDirection] = useState("desc"); useEffect(() => { if (isOpen) { @@ -57,17 +61,17 @@ function ProfileModal({ name: format.name, score: existingFormat ? existingFormat.score : 0, tags: format.tags || [], + date_created: format.date_created, + date_modified: format.date_modified, }; }); setCustomFormats(safeCustomFormats); - // Extract all unique tags from custom formats const allTags = [ ...new Set(safeCustomFormats.flatMap((format) => format.tags)), ]; setFormatTags(allTags); - // Initialize tag scores const initialTagScores = {}; allTags.forEach((tag) => { initialTagScores[tag] = 0; @@ -170,6 +174,91 @@ function ProfileModal({ event.target.select(); }; + const sortedFormats = [...filteredFormats].sort((a, b) => { + if (formatSortKey === "name") { + return formatSortDirection === "asc" + ? a.name.localeCompare(b.name) + : b.name.localeCompare(a.name); + } else if (formatSortKey === "score") { + return formatSortDirection === "asc" + ? a.score - b.score + : b.score - a.score; + } else if (formatSortKey === "dateCreated") { + return formatSortDirection === "asc" + ? new Date(a.date_created) - new Date(b.date_created) + : new Date(b.date_created) - new Date(a.date_created); + } else if (formatSortKey === "dateModified") { + return formatSortDirection === "asc" + ? new Date(a.date_modified) - new Date(b.date_modified) + : new Date(b.date_modified) - new Date(a.date_modified); + } + return 0; + }); + + const sortedTags = [...filteredTags].sort((a, b) => { + if (tagSortKey === "name") { + return tagSortDirection === "asc" + ? a.localeCompare(b) + : b.localeCompare(a); + } else if (tagSortKey === "score") { + return tagSortDirection === "asc" + ? tagScores[a] - tagScores[b] + : tagScores[b] - tagScores[a]; + } else if (tagSortKey === "dateCreated") { + return tagSortDirection === "asc" + ? new Date(a.date_created) - new Date(b.date_created) + : new Date(b.date_created) - new Date(a.date_created); + } else if (tagSortKey === "dateModified") { + return tagSortDirection === "asc" + ? new Date(a.date_modified) - new Date(b.date_modified) + : new Date(b.date_modified) - new Date(a.date_modified); + } + return 0; + }); + + const SortDropdown = ({ options, currentKey, currentDirection, onSort }) => { + const [isOpen, setIsOpen] = useState(false); + + const handleSort = (key) => { + if (key === currentKey) { + onSort(key, currentDirection === "asc" ? "desc" : "asc"); + } else { + onSort(key, "desc"); + } + setIsOpen(false); + }; + + return ( +
+ + {isOpen && ( +
+ {options.map((option) => ( + + ))} +
+ )} +
+ ); + }; + return ( {loading ? ( @@ -181,19 +270,24 @@ function ProfileModal({ {error &&
{error}
}
-
+
+
+ +
+
+
setName(e.target.value)} placeholder="Enter profile name" className="w-full p-2 border rounded dark:bg-gray-700 dark:text-gray-200 dark:border-gray-600" - onClick={handleInputFocus} />
+
- +
+ + { + setFormatSortKey(key); + setFormatSortDirection(direction); + }} + /> +
setFormatFilter(e.target.value)} placeholder="Filter formats" - className="w-full p-2 border rounded mb-2 dark:bg-gray-700 dark:text-gray-200 dark:border-gray-600" + className="w-full p-2 border rounded mb-2 dark:bg-gray-800 dark:text-gray-200 dark:border-gray-600" />
- {filteredFormats.map((format) => ( + {sortedFormats.map((format) => (
- {format.name} + + {format.name} +
- +
+ + { + setTagSortKey(key); + setTagSortDirection(direction); + }} + /> +
setTagFilter(e.target.value)} placeholder="Filter tags" - className="w-full p-2 border rounded mb-2 dark:bg-gray-700 dark:text-gray-200 dark:border-gray-600" + className="w-full p-2 border rounded mb-2 dark:bg-gray-700 dark:text-gray-200 dark:border-gray-600 dark:bg-gray-800" />
- {filteredTags.map((tag) => ( -
- {tag} + {sortedTags.map((tag) => ( +
+ + {tag} +