Compare commits

...

4 Commits

18 changed files with 427 additions and 301 deletions
Split View
  1. +1
    -0
      gca-admin-gurusoft-message-dashboard/.env
  2. +1
    -1
      gca-admin-gurusoft-message-dashboard/README.md
  3. +13
    -26
      gca-admin-gurusoft-message-dashboard/src/App.vue
  4. +52
    -0
      gca-admin-gurusoft-message-dashboard/src/components/FakePage.vue
  5. +0
    -44
      gca-admin-gurusoft-message-dashboard/src/components/HelloWorld.vue
  6. +118
    -0
      gca-admin-gurusoft-message-dashboard/src/components/MarkedPopUp.vue
  7. +97
    -0
      gca-admin-gurusoft-message-dashboard/src/components/SystemLinks.vue
  8. +0
    -94
      gca-admin-gurusoft-message-dashboard/src/components/TheWelcome.vue
  9. +0
    -87
      gca-admin-gurusoft-message-dashboard/src/components/WelcomeItem.vue
  10. +0
    -7
      gca-admin-gurusoft-message-dashboard/src/components/icons/IconCommunity.vue
  11. +0
    -7
      gca-admin-gurusoft-message-dashboard/src/components/icons/IconDocumentation.vue
  12. +0
    -7
      gca-admin-gurusoft-message-dashboard/src/components/icons/IconEcosystem.vue
  13. +0
    -7
      gca-admin-gurusoft-message-dashboard/src/components/icons/IconSupport.vue
  14. +0
    -19
      gca-admin-gurusoft-message-dashboard/src/components/icons/IconTooling.vue
  15. +4
    -2
      gca-admin-gurusoft-message-dashboard/src/main.js
  16. +62
    -0
      gca-admin-gurusoft-message-dashboard/src/mocks/marketPopUpMockData.json
  17. +62
    -0
      gca-admin-gurusoft-message-dashboard/src/mocks/systemLinksMockData.json
  18. +17
    -0
      gca-admin-gurusoft-message-dashboard/src/router/index.js

+ 1
- 0
gca-admin-gurusoft-message-dashboard/.env View File

@ -0,0 +1 @@
VITE_USE_MOCK=true

+ 1
- 1
gca-admin-gurusoft-message-dashboard/README.md View File

@ -1,4 +1,4 @@
# gca-admin-gurusoft-message-dashboard
npm # gca-admin-gurusoft-message-dashboard
This template should help get you started developing with Vue 3 in Vite.

+ 13
- 26
gca-admin-gurusoft-message-dashboard/src/App.vue View File

@ -1,20 +1,20 @@
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'
</script>
import 'bootstrap/dist/css/bootstrap.min.css';
import SystemLinks from "@/components/SystemLinks.vue";
import {inject} from 'vue'
import FakePage from "@/components/FakePage.vue";
import MarkedPopUp from "@/components/MarkedPopUp.vue";
<template>
<header>
<img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />
const externalData = inject("externalData", {})
const useMockedData = import.meta.env.VITE_USE_MOCK === "true"
<div class="wrapper">
<HelloWorld msg="You did it!" />
</div>
</header>
<main>
<TheWelcome />
</main>
</script>
<template>
<div class="app">
<router-view/>
</div>
</template>
<style scoped>
@ -22,10 +22,6 @@ header {
line-height: 1.5;
}
.logo {
display: block;
margin: 0 auto 2rem;
}
@media (min-width: 1024px) {
header {
@ -34,14 +30,5 @@ header {
padding-right: calc(var(--section-gap) / 2);
}
.logo {
margin: 0 2rem 0 0;
}
header .wrapper {
display: flex;
place-items: flex-start;
flex-wrap: wrap;
}
}
</style>

+ 52
- 0
gca-admin-gurusoft-message-dashboard/src/components/FakePage.vue View File

@ -0,0 +1,52 @@
<script setup lang="ts">
import MarkedPopUp from "@/components/MarkedPopUp.vue";
// Define button styles with different colors
const buttons = [
{text: 'Google Search', url: 'https://www.google.com', class: 'btn-primary'},
{text: 'Google Maps', url: 'https://maps.google.com', class: 'btn-success'},
{text: 'Google Drive', url: 'https://drive.google.com', class: 'btn-warning'},
{text: 'Gmail', url: 'https://mail.google.com', class: 'btn-danger'}
];
// Lorem ipsum text for demonstration
const loremText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ".repeat(100);
</script>
<template>
<MarkedPopUp element-id="fake-page-popup" :use-mocked-data="true"/>
<div class="container p-2">
<h1 class="mb-4">Fake Page Example</h1>
<!-- Buttons section - now full width and above text -->
<div class="p-1">
<div class="card-header p-2">Google Services</div>
<div class="card-body p-2">
<div class="row">
<div v-for="(button, index) in buttons" :key="index" class="col-md-3 mb-2">
<a :href="button.url" class="btn w-100" :class="button.class" target="_blank">
{{ button.text }}
</a>
</div>
</div>
</div>
</div>
<!-- Text section - now without scrollable container -->
<div class="p-3 ">
<div class="card-header">Text Content</div>
<div class="card-body">
<p>{{ loremText }}</p>
</div>
</div>
</div>
</template>
<style scoped>
.card-header {
font-weight: bold;
background-color: #f8f9fa;
}
</style>

+ 0
- 44
gca-admin-gurusoft-message-dashboard/src/components/HelloWorld.vue View File

@ -1,44 +0,0 @@
<script setup>
defineProps({
msg: {
type: String,
required: true,
},
})
</script>
<template>
<div class="greetings">
<h1 class="green">{{ msg }}</h1>
<h3>
Youve successfully created a project with
<a href="https://vite.dev/" target="_blank" rel="noopener">Vite</a> +
<a href="https://vuejs.org/" target="_blank" rel="noopener">Vue 3</a>.
</h3>
</div>
</template>
<style scoped>
h1 {
font-weight: 500;
font-size: 2.6rem;
position: relative;
top: -10px;
}
h3 {
font-size: 1.2rem;
}
.greetings h1,
.greetings h3 {
text-align: center;
}
@media (min-width: 1024px) {
.greetings h1,
.greetings h3 {
text-align: left;
}
}
</style>

+ 118
- 0
gca-admin-gurusoft-message-dashboard/src/components/MarkedPopUp.vue View File

@ -0,0 +1,118 @@
<script setup>
import {ref, onMounted, defineProps} from 'vue';
import popupData from '@/mocks/marketPopUpMockData.json';
const props = defineProps({
elementId: {
type: String,
required: true
},
useMockedData: {
type: Boolean,
default: false
}
});
const popups = ref([]);
const currentPopup = ref(null);
const loading = ref(true);
const error = ref(null);
const showPopup = ref(false);
onMounted(async () => {
try {
if (props.useMockedData) {
// Use mock data
popups.value = popupData;
if (popups.value.length > 0) {
currentPopup.value = popups.value[4]; // Display first popup
}
loading.value = false;
} else {
// Fetch from API
const response = await fetch(`https://TODO-replace-with-API`);
if (!response.ok) {
throw new Error('Failed to fetch popup data');
}
popups.value = await response.json();
if (popups.value.length > 0) {
currentPopup.value = popups.value[0];
}
loading.value = false;
}
} catch (e) {
error.value = e.message;
loading.value = false;
}
});
const togglePopup = () => {
showPopup.value = !showPopup.value;
};
const closePopup = () => {
showPopup.value = false;
};
const handleAction = () => {
if (currentPopup.value?.url) {
window.open(currentPopup.value.url, '_blank');
}
closePopup();
};
</script>
<template>
<button v-if="!showPopup" @click="togglePopup" class="btn btn-primary">
Show Popup
</button>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error }}</div>
<div v-else-if="showPopup && currentPopup"
class="position-fixed bottom-0 end-0 m-4 shadow-lg p-3 bg-white rounded border"
style="z-index: 1080; max-width: 350px;">
<!-- Image section -->
<div v-if="currentPopup.image" class="mb-3">
<img :src="currentPopup.image" alt="Campaign image" class="img-fluid rounded popup-image">
</div>
<h4 class="mb-1 text fw-bold">{{ currentPopup.title }}</h4>
<!-- Added ingress field -->
<p v-if="currentPopup.ingress" class="mb-1 fw-bold small">
{{ currentPopup.ingress }}
</p>
<p class="mb-2 small">
{{ currentPopup.description }}
</p>
<div class="d-flex justify-content-end gap-2">
<button @click="closePopup" class="btn btn-outline-secondary btn-sm">Lukk</button>
<button @click="handleAction" class="btn btn-primary btn-sm">
{{ currentPopup.linkText || 'Se mer' }}
</button>
</div>
</div>
</template>
<style scoped>
.shadow-lg {
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;
}
.rounded {
border-radius: 0.375rem !important;
}
.popup-image {
width: 100%;
object-fit: cover;
max-height: 180px;
}
</style>

+ 97
- 0
gca-admin-gurusoft-message-dashboard/src/components/SystemLinks.vue View File

@ -0,0 +1,97 @@
<template>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error }}</div>
<div v-else class="container p-3 border overflow-auto" style="max-height: 340px; width: 420px;">
<div
v-for="(link, index) in links"
:key="index"
class="mb-2"
>
<a
:href="link.url"
class="btn d-flex align-items-center text-start w-100 px-4 py-3"
:class="getButtonClass(link.type)"
:style="{ borderRadius: buttonRadius }"
target="_blank"
>
<i :class="getIconClass(link.icon)" class="me-2"></i>
{{ link.text }}
</a>
</div>
</div>
</template>
<script setup>
import {ref, onMounted, defineProps} from 'vue';
import linkData from '@/mocks/systemLinksMockData.json';
const props = defineProps({
elementId: {
type: String,
required: true
},
metrics: {
type: [String, Object, Array],
default: null
},
buttonRadius: {
type: String,
default: '0.0rem'
},
useMockedData: {
type: Boolean,
default: true
}
});
const links = ref([]);
const loading = ref(true);
const error = ref(null);
const getButtonClass = (type) => {
switch (type?.toLowerCase()) {
case 'internal':
return 'btn-secondary opacity-75';
case 'external':
return 'btn-success opacity-75';
case 'admin':
return 'btn-warning opacity-75';
case 'system':
return 'btn-light opacity-75';
default:
return 'btn-info opacity-75';
}
};
const getIconClass = (icon) => `bi bi-${icon}`;
onMounted(async () => {
try {
if (props.useMockedData) {
// Use mock
links.value = linkData;
loading.value = false;
} else {
// Fetch from API
const response = await fetch(`https://TODO-replace-with-API`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
links.value = await response.json();
}
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
});
</script>
<style scoped>
.container {
background-color: #f8f9fa;
border: 1px solid #ddd;
overflow-y: auto;
}
</style>

+ 0
- 94
gca-admin-gurusoft-message-dashboard/src/components/TheWelcome.vue View File

@ -1,94 +0,0 @@
<script setup>
import WelcomeItem from './WelcomeItem.vue'
import DocumentationIcon from './icons/IconDocumentation.vue'
import ToolingIcon from './icons/IconTooling.vue'
import EcosystemIcon from './icons/IconEcosystem.vue'
import CommunityIcon from './icons/IconCommunity.vue'
import SupportIcon from './icons/IconSupport.vue'
const openReadmeInEditor = () => fetch('/__open-in-editor?file=README.md')
</script>
<template>
<WelcomeItem>
<template #icon>
<DocumentationIcon />
</template>
<template #heading>Documentation</template>
Vues
<a href="https://vuejs.org/" target="_blank" rel="noopener">official documentation</a>
provides you with all information you need to get started.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<ToolingIcon />
</template>
<template #heading>Tooling</template>
This project is served and bundled with
<a href="https://vite.dev/guide/features.html" target="_blank" rel="noopener">Vite</a>. The
recommended IDE setup is
<a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>
+
<a href="https://github.com/vuejs/language-tools" target="_blank" rel="noopener">Vue - Official</a>. If
you need to test your components and web pages, check out
<a href="https://vitest.dev/" target="_blank" rel="noopener">Vitest</a>
and
<a href="https://www.cypress.io/" target="_blank" rel="noopener">Cypress</a>
/
<a href="https://playwright.dev/" target="_blank" rel="noopener">Playwright</a>.
<br />
More instructions are available in
<a href="javascript:void(0)" @click="openReadmeInEditor"><code>README.md</code></a
>.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<EcosystemIcon />
</template>
<template #heading>Ecosystem</template>
Get official tools and libraries for your project:
<a href="https://pinia.vuejs.org/" target="_blank" rel="noopener">Pinia</a>,
<a href="https://router.vuejs.org/" target="_blank" rel="noopener">Vue Router</a>,
<a href="https://test-utils.vuejs.org/" target="_blank" rel="noopener">Vue Test Utils</a>, and
<a href="https://github.com/vuejs/devtools" target="_blank" rel="noopener">Vue Dev Tools</a>. If
you need more resources, we suggest paying
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">Awesome Vue</a>
a visit.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<CommunityIcon />
</template>
<template #heading>Community</template>
Got stuck? Ask your question on
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Vue Land</a>
(our official Discord server), or
<a href="https://stackoverflow.com/questions/tagged/vue.js" target="_blank" rel="noopener"
>StackOverflow</a
>. You should also follow the official
<a href="https://bsky.app/profile/vuejs.org" target="_blank" rel="noopener">@vuejs.org</a>
Bluesky account or the
<a href="https://x.com/vuejs" target="_blank" rel="noopener">@vuejs</a>
X account for latest news in the Vue world.
</WelcomeItem>
<WelcomeItem>
<template #icon>
<SupportIcon />
</template>
<template #heading>Support Vue</template>
As an independent project, Vue relies on community backing for its sustainability. You can help
us by
<a href="https://vuejs.org/sponsor/" target="_blank" rel="noopener">becoming a sponsor</a>.
</WelcomeItem>
</template>

+ 0
- 87
gca-admin-gurusoft-message-dashboard/src/components/WelcomeItem.vue View File

@ -1,87 +0,0 @@
<template>
<div class="item">
<i>
<slot name="icon"></slot>
</i>
<div class="details">
<h3>
<slot name="heading"></slot>
</h3>
<slot></slot>
</div>
</div>
</template>
<style scoped>
.item {
margin-top: 2rem;
display: flex;
position: relative;
}
.details {
flex: 1;
margin-left: 1rem;
}
i {
display: flex;
place-items: center;
place-content: center;
width: 32px;
height: 32px;
color: var(--color-text);
}
h3 {
font-size: 1.2rem;
font-weight: 500;
margin-bottom: 0.4rem;
color: var(--color-heading);
}
@media (min-width: 1024px) {
.item {
margin-top: 0;
padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
}
i {
top: calc(50% - 25px);
left: -26px;
position: absolute;
border: 1px solid var(--color-border);
background: var(--color-background);
border-radius: 8px;
width: 50px;
height: 50px;
}
.item:before {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
bottom: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:after {
content: ' ';
border-left: 1px solid var(--color-border);
position: absolute;
left: 0;
top: calc(50% + 25px);
height: calc(50% - 25px);
}
.item:first-of-type:before {
display: none;
}
.item:last-of-type:after {
display: none;
}
}
</style>

+ 0
- 7
gca-admin-gurusoft-message-dashboard/src/components/icons/IconCommunity.vue View File

@ -1,7 +0,0 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
/>
</svg>
</template>

+ 0
- 7
gca-admin-gurusoft-message-dashboard/src/components/icons/IconDocumentation.vue View File

@ -1,7 +0,0 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
<path
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
/>
</svg>
</template>

+ 0
- 7
gca-admin-gurusoft-message-dashboard/src/components/icons/IconEcosystem.vue View File

@ -1,7 +0,0 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
<path
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
/>
</svg>
</template>

+ 0
- 7
gca-admin-gurusoft-message-dashboard/src/components/icons/IconSupport.vue View File

@ -1,7 +0,0 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
/>
</svg>
</template>

+ 0
- 19
gca-admin-gurusoft-message-dashboard/src/components/icons/IconTooling.vue View File

@ -1,19 +0,0 @@
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--mdi"
width="24"
height="24"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
>
<path
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
fill="currentColor"
></path>
</svg>
</template>

+ 4
- 2
gca-admin-gurusoft-message-dashboard/src/main.js View File

@ -1,6 +1,8 @@
import './assets/main.css'
import 'bootstrap/dist/css/bootstrap.min.css'
import { createApp } from 'vue'
import {createApp} from 'vue'
import App from './App.vue'
import router from "./router";
createApp(App).mount('#app')
createApp(App).use(router).mount('#app')

+ 62
- 0
gca-admin-gurusoft-message-dashboard/src/mocks/marketPopUpMockData.json View File

@ -0,0 +1,62 @@
[
{
"title": "Sommertilbud!",
"ingress": "Få opptil 50% rabatt",
"description": "Spar stort på sommerens mest populære varer. Tilbudet varer ut uken.Spar stort på sommerens mest populære varer. Tilbudet varer ut ukenSpar stort på sommerens mest populære varer. Tilbudet varer ut ukenSpar stort på sommerens mest populære varer. Tilbudet varer ut ukenSpar stort på sommerens mest populære varer. Tilbudet varer ut ukenSpar stort på sommerens mest populære varer. Tilbudet varer ut ukenSpar stort på sommerens mest populære varer. Tilbudet varer ut uken",
"url": "https://google.com",
"linkText": "Les mer",
"image": "https://yavuzceliker.github.io/sample-images/image-92.jpg",
"type": "campaign",
"date": "2025-06-27"
},
{
"title": "Ny funksjon i appen",
"ingress": "Chat med oss direkte",
"description": "Vi har lansert en ny chat-funksjon hvor du kan få hjelp på sekunder.",
"url": "https://example.com/chat-funksjon",
"linkText": "Se hvordan",
"image": "https://yavuzceliker.github.io/sample-images/image-632.jpg",
"type": "feature",
"date": "2025-06-26"
},
{
"title": "Viktig informasjon",
"ingress": "Endringer i bruksvilkår",
"description": "Vi har oppdatert våre vilkår og personvernregler. Les mer om endringene her.",
"url": "https://example.com/vilkar",
"linkText": "Les nye vilkår",
"image": "https://yavuzceliker.github.io/sample-images/image-1.jpg",
"type": "notice",
"date": "2025-06-25"
},
{
"title": "Bli med på undersøkelse",
"ingress": "Hjelp oss å bli bedre",
"description": "Ta vår 2-minutters undersøkelse og vær med i trekningen av gavekort.",
"url": "https://example.com/undersokelse",
"linkText": "Svar nå",
"image": "https://yavuzceliker.github.io/sample-images/image-312.jpg",
"type": "survey",
"date": "2025-06-24"
},
{
"title": "Vi er her for deg",
"ingress": "Ny kundeserviceportal",
"description": "Oppdag vårt nye hjelpesenter med artikler, guider og live-hjelp.",
"url": "https://example.com/hjelp",
"linkText": "Gå til hjelpesenter",
"image": "https://yavuzceliker.github.io/sample-images/image-460.jpg",
"type": "support",
"date": "2025-06-23"
},
{
"title": "Eksklusivt webinartilbud",
"ingress": "Lær av ekspertene",
"description": "Bli med på vårt gratis webinar om digital markedsføring. Begrenset med plasser.",
"url": "https://example.com/webinar",
"linkText": "Meld deg på",
"image": "https://yavuzceliker.github.io/sample-images/image-699.jpg",
"type": "event",
"date": "2025-06-22"
}
]

+ 62
- 0
gca-admin-gurusoft-message-dashboard/src/mocks/systemLinksMockData.json View File

@ -0,0 +1,62 @@
[
{
"url": "https://report.gurusoft.no/",
"text": "Gurusoft hjemmeside",
"type": "admin",
"icon": "dashboard"
},
{
"url": "https://www.gurusoft.no/ta-kontakt?utm_term=gurusoft&utm_campaign=Search+-+Gurusoft+-+Brand&utm_source=adwords&utm_medium=ppc&hsa_acc=1671275617&hsa_cam=21429497412&hsa_grp=164723437872&hsa_ad=704644852789&hsa_src=g&hsa_tgt=kwd-357983112442&hsa_kw=gurusoft&hsa_mt=b&hsa_net=adwords&hsa_ver=3&gad_source=1&gad_campaignid=21429497412&gbraid=0AAAAAC6-h5QA-Uem3fnf9a8Q7l0FhCFkF&gclid=CjwKCAjw3_PCBhA2EiwAkH_j4oYc5_RLO87_7JXoxRBwBR3sR7mHymCM5WRcyM_ORAb7kcmDvoi-HBoCxR4QAvD_BwE",
"text": "Kontakt oss",
"type": "internal",
"icon": "book"
},
{
"url": "https://open.spotify.com/show/4iPq4aLAWHbsXpg0dKSGnY?si=c9ae69117a5740fd&nd=1&dlsi=328d8504668c4558",
"text": "Musikk innslag",
"type": "internal",
"icon": "support"
},
{
"url": "https://www.company.com/privacy-policy",
"text": "Privacy Policy",
"type": "external",
"icon": "policy"
},
{
"url": "https://www.company.com/terms-of-service",
"text": "Terms of Service",
"type": "what",
"icon": "terms"
},
{
"url": "https://intranet.company.local/dashboard",
"text": "Admin Dashboard",
"type": "admin",
"icon": "dashboard"
},
{
"url": "https://google.com",
"text": "Knowledge Base",
"type": "internal",
"icon": "book"
},
{
"url": "https://intranet.company.local/support",
"text": "Support",
"type": "internal",
"icon": "support"
},
{
"url": "https://www.company.com/privacy-policy",
"text": "Privacy Policy",
"type": "external",
"icon": "policy"
},
{
"url": "https://www.company.com/terms-of-service",
"text": "Terms of Service",
"type": "what",
"icon": "terms"
}
]

+ 17
- 0
gca-admin-gurusoft-message-dashboard/src/router/index.js View File

@ -0,0 +1,17 @@
import {createRouter, createWebHistory} from 'vue-router'
import FakePage from '../components/FakePage.vue'
import SystemLinks from '../components/SystemLinks.vue'
import MarkedPopUp from '../components/MarkedPopUp.vue'
const routes = [
{path: '/', name: 'Home', component: FakePage},
{path: '/system-links', name: 'SystemLinks', component: SystemLinks},
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router

Loading…
Cancel
Save