diff --git a/.vscode/settings.json b/.vscode/settings.json index 2b36aa7..b0b5383 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,5 +18,10 @@ "titleBar.inactiveBackground": "#ff2fa299", "titleBar.inactiveForeground": "#e7e7e799" }, - "peacock.color": "#ff2fa2" + "peacock.color": "#ff2fa2", + "cSpell.words": [ + "audiotrack", + "Nominatim", + "videocam" + ] } \ No newline at end of file diff --git a/frontend/public/videos/3191901-uhd_3840_2160_25fps.mp4 b/frontend/public/videos/3191901-uhd_3840_2160_25fps.mp4 new file mode 100644 index 0000000..c812a02 Binary files /dev/null and b/frontend/public/videos/3191901-uhd_3840_2160_25fps.mp4 differ diff --git a/frontend/public/videos/3326928-hd_1920_1080_24fps.mp4 b/frontend/public/videos/3326928-hd_1920_1080_24fps.mp4 new file mode 100644 index 0000000..5291768 Binary files /dev/null and b/frontend/public/videos/3326928-hd_1920_1080_24fps.mp4 differ diff --git a/frontend/src/css/app.css b/frontend/src/css/app.css index 941386c..1d8d514 100644 --- a/frontend/src/css/app.css +++ b/frontend/src/css/app.css @@ -1 +1 @@ -.controls{display:flex;justify-content:space-between;width:100%;max-width:500px;margin-bottom:10px}.button{padding:6px 12px;background-color:#4f46e5;color:#fff;border:none;border-radius:4px;cursor:pointer}.visualization-container{position:relative;width:100%;height:calc(100vh - 86px);overflow:hidden}.gradient-bg{position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1;background:linear-gradient(45deg, #8634f9, #ffab1a, #ff2fa2);background-size:200% 200%;animation:gradientAnimation 20s ease infinite}@keyframes gradientAnimation{0%{background-position:0% 0%}25%{background-position:100% 0%}50%{background-position:100% 100%}75%{background-position:0% 100%}100%{background-position:0% 0%}}.median{position:absolute;top:51.2%;left:0;right:0;height:1px;background-color:rgba(255,255,255,.3);z-index:0}.scroll-container{position:relative;width:100%;height:100%;overflow-x:auto;overflow-y:hidden;min-height:400px;z-index:1;-ms-overflow-style:none;scrollbar-width:none}.scroll-container::-webkit-scrollbar{display:none}.smooth-scroll{scroll-behavior:smooth}.active{cursor:grabbing}.spacer{height:100vh}.dot-tooltip{pointer-events:none;opacity:1}.dot-tooltip .tooltip-background{fill:rgba(0,0,0,0)}.dot-tooltip .tooltip-content{display:flex;justify-content:center;align-items:center;flex-direction:column;width:100%;height:100%;color:#fff}.dot-tooltip .image_container{margin-top:8px;box-shadow:0 0 20px 0 rgba(255,255,255,.25);transition:box-shadow .25s ease-in-out;width:80px;height:80px;overflow:hidden;border-radius:50%;border:2px solid #fff;display:flex;justify-content:center}.dot-tooltip .image_container:hover{box-shadow:0 0 30px 0 rgba(255,255,255,.8)}.dot-tooltip .tooltip-image{width:100%;height:auto;display:block;pointer-events:auto}.dot-tooltip .tooltip-title{font-size:14px;font-weight:400;margin-bottom:2px;text-align:center;text-wrap:balance;-webkit-hyphens:auto;hyphens:auto;line-height:1.1}.dot-tooltip .tooltip-description{font-size:12px;font-weight:300}.dot-tooltip .tooltip-arrow{width:1px;height:30px;background:linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.5), transparent)}.dot{transition:r .2s ease,fill .2s ease;cursor:pointer}.dot:hover{fill:rgba(255,255,255,.9);filter:drop-shadow(0 0 5px rgba(255, 255, 255, 0.8))}.tooltip-img{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;border-radius:4px} \ No newline at end of file +.controls{display:flex;justify-content:space-between;width:100%;max-width:500px;margin-bottom:10px}.button{padding:6px 12px;background-color:#4f46e5;color:#fff;border:none;border-radius:4px;cursor:pointer}.visualization-container{position:relative;width:100%;height:calc(100vh - 86px);overflow:hidden}.gradient-bg{position:absolute;top:0;left:0;width:100%;height:100%;z-index:-1;background:linear-gradient(45deg, #8634f9, #ffab1a, #ff2fa2);background-size:200% 200%;animation:gradientAnimation 20s ease infinite}@keyframes gradientAnimation{0%{background-position:0% 0%}25%{background-position:100% 0%}50%{background-position:100% 100%}75%{background-position:0% 100%}100%{background-position:0% 0%}}.median{position:absolute;top:51.2%;left:0;right:0;height:1px;background-color:rgba(255,255,255,.3);z-index:1}.scroll-container{position:relative;width:100%;height:100%;overflow-x:auto;overflow-y:hidden;min-height:400px;z-index:2;-ms-overflow-style:none;scrollbar-width:none}.scroll-container::-webkit-scrollbar{display:none}.smooth-scroll{scroll-behavior:smooth}.active{cursor:grabbing}.spacer{height:100vh}.dot-tooltip{pointer-events:none;opacity:1}.dot-tooltip .tooltip-background{fill:rgba(0,0,0,0)}.dot-tooltip .tooltip-content{display:flex;justify-content:center;align-items:center;flex-direction:column;width:100%;height:100%;color:#fff}.dot-tooltip .image_container{margin-top:8px;box-shadow:0 0 20px 0 rgba(255,255,255,.25);transition:box-shadow .25s ease-in-out;width:80px;height:80px;overflow:hidden;border-radius:50%;border:2px solid #fff;display:flex;justify-content:center}.dot-tooltip .image_container:hover{box-shadow:0 0 30px 0 rgba(255,255,255,.8)}.dot-tooltip .tooltip-image{width:100%;height:auto;display:block;pointer-events:auto}.dot-tooltip .tooltip-title{font-size:14px;font-weight:400;margin-bottom:2px;text-align:center;text-wrap:balance;-webkit-hyphens:auto;hyphens:auto;line-height:1.1}.dot-tooltip .tooltip-description{font-size:12px;font-weight:300}.dot-tooltip .tooltip-arrow{width:1px;height:30px;background:linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.5), transparent)}.dot{transition:r .2s ease,fill .2s ease;cursor:pointer}.dot:hover{fill:rgba(255,255,255,.9);filter:drop-shadow(0 0 5px rgba(255, 255, 255, 0.8))}.tooltip-img{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;border-radius:4px}.q-card{box-shadow:none !important}.q-card--bordered{box-shadow:none !important}.q-card--flat{box-shadow:none !important}.bg-white,.q-layout__section--marginal{background:rgba(0,0,0,0) !important}footer .text-primary,footer .text-grey{color:#fff !important} \ No newline at end of file diff --git a/frontend/src/css/app.scss b/frontend/src/css/app.scss index 63a47bc..a0d8d1d 100644 --- a/frontend/src/css/app.scss +++ b/frontend/src/css/app.scss @@ -67,7 +67,7 @@ $image-size: 80px; right: 0; height: 1px; background-color: rgba(255,255,255,0.3); - z-index: 0; + z-index: 1; } .scroll-container { @@ -77,7 +77,7 @@ $image-size: 80px; overflow-x: auto; overflow-y: hidden; min-height:400px; - z-index: 1; + z-index: 2; &::-webkit-scrollbar { display: none; } diff --git a/frontend/src/pages/EditPage.vue b/frontend/src/pages/EditPage.vue index cb5c0f4..03af6ca 100644 --- a/frontend/src/pages/EditPage.vue +++ b/frontend/src/pages/EditPage.vue @@ -173,15 +173,15 @@ - + - + - - - - - - Are you sure you want to delete this entry? This action cannot be undone. - - - - - - - - - { - showDeleteDialog.value = true - } - - const onDelete = () => { - // TODO: Implement delete functionality - $q.notify({ - type: 'negative', - message: 'Entry deleted successfully!', - position: 'top' - }) - router.push('/wave') - } - // Mobile image selection methods const openCamera = () => { const cameraInput = document.getElementById('cameraInput') @@ -1487,7 +1457,6 @@ export default { return { form, - showDeleteDialog, currentTab, selectedMainCategory, availableSubcategories, @@ -1519,8 +1488,6 @@ export default { goToTagSelector, onSave, onCancel, - confirmDelete, - onDelete, // Location methods getCurrentLocation, // Key image methods diff --git a/frontend/src/pages/EntryDetailPage.vue b/frontend/src/pages/EntryDetailPage.vue new file mode 100644 index 0000000..f117854 --- /dev/null +++ b/frontend/src/pages/EntryDetailPage.vue @@ -0,0 +1,924 @@ + + + + + \ No newline at end of file diff --git a/frontend/src/pages/WavePage.vue b/frontend/src/pages/WavePage.vue index 8811faf..bd36f9e 100644 --- a/frontend/src/pages/WavePage.vue +++ b/frontend/src/pages/WavePage.vue @@ -5,21 +5,87 @@
+ + + + + + + + + + + + + \ No newline at end of file + + + \ No newline at end of file diff --git a/frontend/src/router/routes.js b/frontend/src/router/routes.js index 4e06d4a..a70a93a 100644 --- a/frontend/src/router/routes.js +++ b/frontend/src/router/routes.js @@ -48,6 +48,12 @@ const routes = [ component: () => import('pages/TagSelector.vue'), meta: { hideFooter: true } }, + { + path: 'entry/:id', + name: 'entry-detail', + component: () => import('pages/EntryDetailPage.vue'), + meta: { hideFooter: true } + }, ], }, diff --git a/frontend/src/utils/ConnectedDotsVisualization.ts b/frontend/src/utils/ConnectedDotsVisualization.ts index b62a592..eba1518 100644 --- a/frontend/src/utils/ConnectedDotsVisualization.ts +++ b/frontend/src/utils/ConnectedDotsVisualization.ts @@ -4,6 +4,7 @@ export interface DotConfig { value: number; x: number; link?: string; // URL to navigate to when dot is clicked + onClick?: () => void; // Function to call when dot is clicked imageUrl?: string; // Image to display in tooltip title?: string; // Optional title for the tooltip description?: string; // Optional description for the tooltip @@ -358,9 +359,13 @@ export class ConnectedDotsVisualization { let imgWrapper: HTMLElement; // if (dot.imageUrl) { - if (dot.link) { + if (dot.link || dot.onClick) { const link = document.createElement("a"); - link.href = dot.link; + if (dot.link) { + link.href = dot.link; + } else { + link.href = "#"; // Prevent default href for onClick + } link.target = "_self"; // Opens in the same window const imgElement = document.createElement("img"); @@ -372,12 +377,15 @@ export class ConnectedDotsVisualization { imgWrapper = link; // Use the link as the wrapper // Add the event listener to the link - link.addEventListener("click", () => { - if (dot.link) { + link.addEventListener("click", (e) => { + if (dot.onClick) { + e.preventDefault(); // Prevent default navigation + dot.onClick(); + } else if (dot.link) { window.location.href = dot.link; } else { - console.error("Dot has no link"); - throw new Error("Dot has no link"); + console.error("Dot has no link or onClick handler"); + throw new Error("Dot has no link or onClick handler"); } }); } else { @@ -482,14 +490,16 @@ export class ConnectedDotsVisualization { if (dot.imageUrl || dot.title || dot.description) { this.showTooltip(dot, x, y); } - // Click event for navigation - if (dot.link) { + // Click event for navigation or custom function + if (dot.link || dot.onClick) { circle.addEventListener("click", () => { - if (dot.link) { + if (dot.onClick) { + dot.onClick(); + } else if (dot.link) { window.location.href = dot.link; } else { - console.error("Dot has no link"); - throw new Error("Dot has no link"); + console.error("Dot has no link or onClick handler"); + throw new Error("Dot has no link or onClick handler"); } }); }