Merge remote-tracking branch 'origin/main'
# Conflicts: # src/App.vue # src/router/router.js
208
package-lock.json
generated
@@ -30,7 +30,8 @@
|
|||||||
"eslint-plugin-vue": "^9.22.0",
|
"eslint-plugin-vue": "^9.22.0",
|
||||||
"postcss": "^8.4.35",
|
"postcss": "^8.4.35",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"vite": "^5.2.11"
|
"vite": "^5.2.11",
|
||||||
|
"vite-svg-loader": "^5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@alloc/quick-lru": {
|
"node_modules/@alloc/quick-lru": {
|
||||||
@@ -994,6 +995,16 @@
|
|||||||
"tailwindcss": ">=2.0.0"
|
"tailwindcss": ">=2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@trysound/sax": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||||
@@ -1692,6 +1703,50 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/css-select": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^1.0.0",
|
||||||
|
"css-what": "^6.1.0",
|
||||||
|
"domhandler": "^5.0.2",
|
||||||
|
"domutils": "^3.0.1",
|
||||||
|
"nth-check": "^2.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-tree": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mdn-data": "2.0.30",
|
||||||
|
"source-map-js": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/css-what": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cssesc": {
|
"node_modules/cssesc": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
@@ -1703,6 +1758,42 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/csso": {
|
||||||
|
"version": "5.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
|
||||||
|
"integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"css-tree": "~2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/csso/node_modules/css-tree": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mdn-data": "2.0.28",
|
||||||
|
"source-map-js": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/csso/node_modules/mdn-data": {
|
||||||
|
"version": "2.0.28",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
|
||||||
|
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "CC0-1.0"
|
||||||
|
},
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
@@ -1776,6 +1867,65 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dom-serializer": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.2",
|
||||||
|
"entities": "^4.2.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/domelementtype": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/domhandler": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/domutils": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"dom-serializer": "^2.0.0",
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.3"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eastasianwidth": {
|
"node_modules/eastasianwidth": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||||
@@ -2887,6 +3037,13 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdn-data": {
|
||||||
|
"version": "2.0.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
|
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "CC0-1.0"
|
||||||
|
},
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
@@ -3931,6 +4088,42 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svgo": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@trysound/sax": "0.2.0",
|
||||||
|
"commander": "^7.2.0",
|
||||||
|
"css-select": "^5.1.0",
|
||||||
|
"css-tree": "^2.3.1",
|
||||||
|
"css-what": "^6.1.0",
|
||||||
|
"csso": "^5.0.5",
|
||||||
|
"picocolors": "^1.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"svgo": "bin/svgo"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/svgo"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/svgo/node_modules/commander": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "3.4.10",
|
"version": "3.4.10",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz",
|
||||||
@@ -4193,6 +4386,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vite-svg-loader": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vite-svg-loader/-/vite-svg-loader-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-M/wqwtOEjgb956/+m5ZrYT/Iq6Hax0OakWbokj8+9PXOnB7b/4AxESHieEtnNEy7ZpjsjYW1/5nK8fATQMmRxw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"svgo": "^3.0.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": ">=3.2.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vue": {
|
"node_modules/vue": {
|
||||||
"version": "3.4.38",
|
"version": "3.4.38",
|
||||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.38.tgz",
|
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.38.tgz",
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
"eslint-plugin-vue": "^9.22.0",
|
"eslint-plugin-vue": "^9.22.0",
|
||||||
"postcss": "^8.4.35",
|
"postcss": "^8.4.35",
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"vite": "^5.2.11"
|
"vite": "^5.2.11",
|
||||||
|
"vite-svg-loader": "^5.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 1000 1000">
|
|
||||||
<defs>
|
|
||||||
<style>
|
|
||||||
.cls-1 {
|
|
||||||
stroke: #000;
|
|
||||||
stroke-width: 1px;
|
|
||||||
stroke-dasharray: 4 2;
|
|
||||||
fill-rule: evenodd;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<path id="Social_x_-2_1" data-name="Social x -2 1" class="cls-1" d="M208.568,8c149.2,0.331,300.422,2.648,449.617,2.979,86.663,0,162.7-4.391,218.357,25.818,41.312,22.424,77.08,62.95,94.291,109.23,20.963,56.368,12.9,149.956,12.9,225.411V674.3c0,48.187,7.128,109.475-3.97,150.936-13.034,48.693-38.509,94.2-74.44,120.153-24.954,18.023-55.528,34.237-90.321,41.706-23.029,4.944-51.493,2.979-78.41,2.979H318.739c-46.8,0-103.154,5.907-144.909-2.979-60.19-12.809-108.811-49.038-136.97-94.335C2.042,836.752,11.055,767.026,11.055,675.3c0-117.493.992-362.125,0.992-479.618C12.047,63.677,151.59,8,208.568,8Zm10.918,201.579-2.977,1.986L436.851,500.528c-4.6,17.548-37.928,43.94-49.627,58.586L271.1,694.162c-11.979,15.019-36.369,30.637-42.679,49.65l89.328-.993,158.805-183.7c5.547,0.3,5.794,1.012,8.933,2.979,9.391,25.049,36.577,46.289,51.611,67.524,19.634,27.733,42.32,53.1,61.537,80.433,7.99,11.363,14.845,25.453,25.806,33.762H754.461c12.721,0,40.162,4,48.634-1.986L633.372,516.416c-12.208-17.35-56.689-63.437-60.544-81.426L767.364,211.565v-0.993l-3.97-.993-84.365.993L576.8,326.753c-13.733,17.111-28.64,40.051-46.649,52.629h-1.985L400.127,210.572Zm126.052,49.65,29.776,1.986L695.9,685.225l-0.993,5.958-46.649-.993q-30.765-40.212-61.537-80.433l-184.611-241.3L343.553,292c-5.976-8.018-22.454-20.757-20.843-31.776Z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
21
src/App.vue
@@ -1,26 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app>
|
<v-app>
|
||||||
<div class="m-0 flex flex-column h-screen">
|
|
||||||
<!-- <Header class="fixed w-full z-50 top-0 p-2"></Header>-->
|
<Header class="fixed w-full z-50 p-2 h-16"></Header>
|
||||||
<div class="flex flex-row relative">
|
|
||||||
<div
|
<div class="flex flex-row mt-16">
|
||||||
class="fixed h-full w-2 z-20"
|
|
||||||
style="background: transparent;"
|
|
||||||
></div>
|
|
||||||
|
|
||||||
<transition name="slide-fade">
|
<transition name="slide-fade">
|
||||||
<div v-show="sideBarStore.visible"
|
<div v-show="sideBarStore.visible"
|
||||||
class=" fixed h-full min-w-60 border-r-2 bg-white z-30 transition-transform duration-700">
|
class="fixed h-full min-w-60 border-r-2 z-30 ">
|
||||||
<SideBar></SideBar>
|
<side-bar></side-bar>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
<div class="flex flex-col w-full" style="background-color: #f4f4f4">
|
<div class="flex flex-col w-full min-h-screen bg-amber">
|
||||||
<RouterView></RouterView>
|
<RouterView></RouterView>
|
||||||
<!-- <Footer></Footer>-->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</v-app>
|
</v-app>
|
||||||
|
|
||||||
<size-indicator></size-indicator>
|
<size-indicator></size-indicator>
|
||||||
|
|||||||
1
src/assets/icons/facebook.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64h98.2V334.2H109.4V256h52.8V222.3c0-87.1 39.4-127.5 125-127.5c16.2 0 44.2 3.2 55.7 6.4V172c-6-.6-16.5-1-29.6-1c-42 0-58.2 15.9-58.2 57.2V256h83.6l-14.4 78.2H255V480H384c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64z"/></svg>
|
||||||
|
After Width: | Height: | Size: 498 B |
1
src/assets/icons/instagram.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M194.4 211.7a53.3 53.3 0 1 0 59.3 88.7 53.3 53.3 0 1 0 -59.3-88.7zm142.3-68.4c-5.2-5.2-11.5-9.3-18.4-12c-18.1-7.1-57.6-6.8-83.1-6.5c-4.1 0-7.9 .1-11.2 .1c-3.3 0-7.2 0-11.4-.1c-25.5-.3-64.8-.7-82.9 6.5c-6.9 2.7-13.1 6.8-18.4 12s-9.3 11.5-12 18.4c-7.1 18.1-6.7 57.7-6.5 83.2c0 4.1 .1 7.9 .1 11.1s0 7-.1 11.1c-.2 25.5-.6 65.1 6.5 83.2c2.7 6.9 6.8 13.1 12 18.4s11.5 9.3 18.4 12c18.1 7.1 57.6 6.8 83.1 6.5c4.1 0 7.9-.1 11.2-.1c3.3 0 7.2 0 11.4 .1c25.5 .3 64.8 .7 82.9-6.5c6.9-2.7 13.1-6.8 18.4-12s9.3-11.5 12-18.4c7.2-18 6.8-57.4 6.5-83c0-4.2-.1-8.1-.1-11.4s0-7.1 .1-11.4c.3-25.5 .7-64.9-6.5-83l0 0c-2.7-6.9-6.8-13.1-12-18.4zm-67.1 44.5A82 82 0 1 1 178.4 324.2a82 82 0 1 1 91.1-136.4zm29.2-1.3c-3.1-2.1-5.6-5.1-7.1-8.6s-1.8-7.3-1.1-11.1s2.6-7.1 5.2-9.8s6.1-4.5 9.8-5.2s7.6-.4 11.1 1.1s6.5 3.9 8.6 7s3.2 6.8 3.2 10.6c0 2.5-.5 5-1.4 7.3s-2.4 4.4-4.1 6.2s-3.9 3.2-6.2 4.2s-4.8 1.5-7.3 1.5l0 0c-3.8 0-7.5-1.1-10.6-3.2zM448 96c0-35.3-28.7-64-64-64H64C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V96zM357 389c-18.7 18.7-41.4 24.6-67 25.9c-26.4 1.5-105.6 1.5-132 0c-25.6-1.3-48.3-7.2-67-25.9s-24.6-41.4-25.8-67c-1.5-26.4-1.5-105.6 0-132c1.3-25.6 7.1-48.3 25.8-67s41.5-24.6 67-25.8c26.4-1.5 105.6-1.5 132 0c25.6 1.3 48.3 7.1 67 25.8s24.6 41.4 25.8 67c1.5 26.3 1.5 105.4 0 131.9c-1.3 25.6-7.1 48.3-25.8 67z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
1
src/assets/icons/x.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 32C28.7 32 0 60.7 0 96V416c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64H64zm297.1 84L257.3 234.6 379.4 396H283.8L209 298.1 123.3 396H75.8l111-126.9L69.7 116h98l67.7 89.5L313.6 116h47.5zM323.3 367.6L153.4 142.9H125.1L296.9 367.6h26.3z"/></svg>
|
||||||
|
After Width: | Height: | Size: 493 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 276 B |
@@ -9,16 +9,6 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"allRightsReserved": "All rights reserved"
|
"allRightsReserved": "All rights reserved"
|
||||||
},
|
},
|
||||||
"sitemenu": {
|
|
||||||
"HelpUs": "Help us",
|
|
||||||
"About": "About",
|
|
||||||
"ContentPolicy": "Content Policy",
|
|
||||||
"CreatorGuide": "Creator Guide",
|
|
||||||
"FAQ": "FAQ",
|
|
||||||
"HelpAndContact": "Help and Contact",
|
|
||||||
"Pricing": "Pricing",
|
|
||||||
"TermsAndConditions": "Terms and conditions"
|
|
||||||
},
|
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"subscriptionTitle": "Subscription"
|
"subscriptionTitle": "Subscription"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,16 +9,6 @@
|
|||||||
"footer": {
|
"footer": {
|
||||||
"allRightsReserved": "Tout droits réservés"
|
"allRightsReserved": "Tout droits réservés"
|
||||||
},
|
},
|
||||||
"sitemenu": {
|
|
||||||
"HelpUs": "Aidez-nous",
|
|
||||||
"About": "À propos",
|
|
||||||
"ContentPolicy": "Politique de contenu",
|
|
||||||
"CreatorGuide": "Guide pour les créateurs",
|
|
||||||
"FAQ": "FAQ",
|
|
||||||
"HelpAndContact": "Aide & Contact",
|
|
||||||
"Pricing": "Frais",
|
|
||||||
"TermsAndConditions": "Conditions générales"
|
|
||||||
},
|
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"subscriptionTitle": "Abonnements"
|
"subscriptionTitle": "Abonnements"
|
||||||
},
|
},
|
||||||
|
|||||||
12
src/main.js
@@ -11,8 +11,9 @@ import * as directives from 'vuetify/directives'
|
|||||||
import vueGoogleOauth from 'vue3-google-login'
|
import vueGoogleOauth from 'vue3-google-login'
|
||||||
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
||||||
import {useAuthStore} from "@/stores/authStore.js";
|
import {useAuthStore} from "@/stores/authStore.js";
|
||||||
import {useUserStore} from "@/stores/userStore.js";
|
|
||||||
import i18n from './i18n.js';
|
import i18n from './i18n.js';
|
||||||
|
import {useUserProfileStore} from "@/stores/userProfileStore.js";
|
||||||
|
import {useCreatorProfileStore} from "@/stores/creatorProfileStore.js";
|
||||||
|
|
||||||
const vuetify = createVuetify({
|
const vuetify = createVuetify({
|
||||||
components,
|
components,
|
||||||
@@ -31,9 +32,10 @@ const app = createApp(App)
|
|||||||
// Make $t globally available
|
// Make $t globally available
|
||||||
app.config.globalProperties.$t = i18n.global.t;
|
app.config.globalProperties.$t = i18n.global.t;
|
||||||
|
|
||||||
// this force the creation of the stores
|
// this force the creation and initialization of the stores
|
||||||
const subscriptionStore = useSubscriptionStore()
|
useSubscriptionStore()
|
||||||
const authStore = useAuthStore()
|
useAuthStore()
|
||||||
const userStore = useUserStore()
|
useUserProfileStore()
|
||||||
|
useCreatorProfileStore()
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
|
|||||||
@@ -14,34 +14,25 @@ import Register from '../views/main/Register.vue'
|
|||||||
import Home from '../views/main/Home.vue'
|
import Home from '../views/main/Home.vue'
|
||||||
import Wallet from '../views/main/Wallet.vue'
|
import Wallet from '../views/main/Wallet.vue'
|
||||||
import ProfilePage from '@/views/profile/ProfilePage.vue'
|
import ProfilePage from '@/views/profile/ProfilePage.vue'
|
||||||
import CreatorList from '@/views/creators/CreatorList.vue'
|
import CreatorList from '@/views/browser/CreatorList.vue'
|
||||||
import CreatorPage from "@/views/creators/CreatorPage.vue";
|
|
||||||
import ContentPage from "@/views/contents/ContentPage.vue";
|
|
||||||
import PostContent from "@/views/contents/PostContent.vue";
|
import PostContent from "@/views/contents/PostContent.vue";
|
||||||
import Explorer from "@/views/explorer/explorer.vue";
|
import Explorer from "@/views/explorer/explorer.vue";
|
||||||
import {useAuthStore} from "@/stores/authStore.js";
|
import {useAuthStore} from "@/stores/authStore.js";
|
||||||
import ForYouPage from "@/views/profile/ForYouPage.vue";
|
import ForYouPage from "@/views/profile/ForYouPage.vue";
|
||||||
import CreatorPresentation from "@/views/creators/CreatorPresentation.vue";
|
|
||||||
import CreatorExclusiveContent from "@/views/creators/CreatorExclusiveContent.vue";
|
import CreatorLayout from "@/views/creators/CreatorLayout.vue";
|
||||||
import CTA01 from "@/views/CTA01.vue";
|
import ContentPage from "@/views/contents/ContentPage.vue";
|
||||||
|
import CreatorContent from "@/views/creators/CreatorContent.vue";
|
||||||
|
import CreatorNews from "@/views/creators/CreatorNews.vue";
|
||||||
|
import CreatorHome from "@/views/creators/CreatorHome.vue";
|
||||||
|
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
|
||||||
path: '/CTA01',
|
|
||||||
component: CTA01,
|
|
||||||
meta: { hideSideBar: true }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: Home,
|
component: Home,
|
||||||
meta: {hideSideBar: true}
|
meta: {hideSideBar: true}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/presentation/@:creator',
|
|
||||||
component: CreatorPresentation,
|
|
||||||
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/browse',
|
path: '/browse',
|
||||||
component: CreatorList
|
component: CreatorList
|
||||||
@@ -52,17 +43,29 @@ const routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/@:creator',
|
path: '/@:creator',
|
||||||
component: CreatorPage
|
component: CreatorLayout,
|
||||||
|
meta: {
|
||||||
|
requiresAuth: true,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: CreatorHome,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'news',
|
||||||
|
component: CreatorNews,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'content',
|
||||||
|
component: CreatorContent
|
||||||
|
},
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/content/post',
|
path: '/content/post',
|
||||||
component: PostContent,
|
component: PostContent,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/@:creator/exclusivecontent',
|
|
||||||
component: CreatorExclusiveContent
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/helpandcontact',
|
path: '/helpandcontact',
|
||||||
component: HelpAndContact,
|
component: HelpAndContact,
|
||||||
@@ -128,7 +131,7 @@ const routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/paymentcompleted',
|
path: '/paymentcompleted',
|
||||||
name: 'PayementCompleted',
|
name: 'PaymentCompleted',
|
||||||
component: PaymentCompleted,
|
component: PaymentCompleted,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -153,7 +156,6 @@ const routes = [
|
|||||||
path: '/feed',
|
path: '/feed',
|
||||||
name: 'feed',
|
name: 'feed',
|
||||||
component: ForYouPage,
|
component: ForYouPage,
|
||||||
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -162,7 +164,7 @@ const router = createRouter({
|
|||||||
routes
|
routes
|
||||||
})
|
})
|
||||||
|
|
||||||
// Navigation gards
|
// Navigation guards
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
|
|||||||
@@ -63,12 +63,12 @@ export const useAuthStore = defineStore(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loginGoogle(accessToken) {
|
async function loginWithGoogle(accessToken) {
|
||||||
try {
|
try {
|
||||||
const response = await clientApi.post(
|
const response = await clientApi.post(
|
||||||
'api/google/sign-in',
|
'api/users/login-with-google',
|
||||||
{
|
{
|
||||||
accessToken: accessToken
|
token: accessToken
|
||||||
})
|
})
|
||||||
updateTokens(response.data)
|
updateTokens(response.data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -95,6 +95,6 @@ export const useAuthStore = defineStore(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {accessToken, refreshToken, isAuthenticated, userId, login, loginGoogle, logout}
|
return {accessToken, refreshToken, isAuthenticated, userId, login, loginWithGoogle, logout}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
53
src/stores/brandingStore.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import {defineStore} from 'pinia'
|
||||||
|
import {useClient} from "@/plugins/api.js";
|
||||||
|
import {useSessionStorage} from "@vueuse/core";
|
||||||
|
import {onBeforeMount, ref, watch} from "vue";
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
|
||||||
|
export const useBrandingStore = defineStore(
|
||||||
|
'branding',
|
||||||
|
() => {
|
||||||
|
|
||||||
|
const currentBrand = ref('')
|
||||||
|
|
||||||
|
const value = useSessionStorage(
|
||||||
|
'branding',
|
||||||
|
{},
|
||||||
|
{writeDefaults: false})
|
||||||
|
|
||||||
|
const loading = ref(true)
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
onBeforeMount(async () => await fetchCreatorData(route.params.creator))
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.params.creator,
|
||||||
|
async () => {
|
||||||
|
console.log(`creator: ${route.params.creator}`)
|
||||||
|
console.log(`currentBrand: ${currentBrand.value}`)
|
||||||
|
if (route.params.creator !== currentBrand.value) {
|
||||||
|
await fetchCreatorData(route.params.creator);
|
||||||
|
currentBrand.value = route.params.creator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const fetchCreatorData = async (creatorAlias) => {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const client = useClient()
|
||||||
|
const response = await client.get(`/api/creators/@${creatorAlias}`)
|
||||||
|
value.value = response.data
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error fetching content: ${error}`)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
loading
|
||||||
|
}
|
||||||
|
})
|
||||||
47
src/stores/creatorProfileStore.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import {computed, watch} from 'vue'
|
||||||
|
import {defineStore} from 'pinia'
|
||||||
|
import {useAuthStore} from "@/stores/authStore.js";
|
||||||
|
import {useClient} from "@/plugins/api.js";
|
||||||
|
import {useSessionStorage} from "@vueuse/core";
|
||||||
|
|
||||||
|
export const useCreatorProfileStore = defineStore(
|
||||||
|
'creator-profile',
|
||||||
|
() => {
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
|
const authWatcher = watch(
|
||||||
|
() => authStore.isAuthenticated,
|
||||||
|
async (newValue) => {
|
||||||
|
if (newValue) {
|
||||||
|
await fetchCurrentCreatorProfile()
|
||||||
|
} else {
|
||||||
|
value.value = undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const value = useSessionStorage(
|
||||||
|
'creator-profile',
|
||||||
|
{},
|
||||||
|
{writeDefaults: false})
|
||||||
|
|
||||||
|
const hasCreator = computed(() =>
|
||||||
|
value.value
|
||||||
|
&& Object.getOwnPropertyNames(value.value).length >= 1)
|
||||||
|
|
||||||
|
const client = useClient()
|
||||||
|
|
||||||
|
async function fetchCurrentCreatorProfile() {
|
||||||
|
try {
|
||||||
|
const creatorResponse = await client.get(`/api/creators/profile`)
|
||||||
|
value.value = creatorResponse.data
|
||||||
|
// TODO: no cache-busting ???
|
||||||
|
} catch (error) {
|
||||||
|
value.value = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
creator: value,
|
||||||
|
hasCreator
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -4,38 +4,30 @@ import {useAuthStore} from "@/stores/authStore.js";
|
|||||||
import {useClient} from "@/plugins/api.js";
|
import {useClient} from "@/plugins/api.js";
|
||||||
import {useSessionStorage} from "@vueuse/core";
|
import {useSessionStorage} from "@vueuse/core";
|
||||||
|
|
||||||
export const useUserStore = defineStore(
|
export const useUserProfileStore = defineStore(
|
||||||
'user',
|
'user-profile',
|
||||||
() => {
|
() => {
|
||||||
|
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
const authWatcher = watch(
|
const authWatcher = watch(
|
||||||
() => authStore.isAuthenticated,
|
() => authStore.isAuthenticated,
|
||||||
async (newValue) => {
|
async (newValue) => {
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
await fetchCurrentUserProfile()
|
await fetchCurrentUserProfile()
|
||||||
await fetchCurrentCreatorProfile()
|
|
||||||
} else {
|
} else {
|
||||||
user.value = undefined
|
value.value = undefined
|
||||||
creator.value = undefined
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const user = useSessionStorage(
|
const value = useSessionStorage(
|
||||||
'user-user',
|
'user-profile',
|
||||||
{},
|
{},
|
||||||
{writeDefaults: false})
|
{writeDefaults: false})
|
||||||
const creator = useSessionStorage(
|
|
||||||
'user-creator',
|
|
||||||
{},
|
|
||||||
{writeDefaults: false})
|
|
||||||
|
|
||||||
const hasCreator = computed(() =>
|
|
||||||
creator.value
|
|
||||||
&& Object.getOwnPropertyNames(creator.value).length >= 1)
|
|
||||||
|
|
||||||
const fullname = computed(() => {
|
const fullname = computed(() => {
|
||||||
if (user.value) {
|
if (value.value) {
|
||||||
const {firstname, lastname} = user.value;
|
const {firstname, lastname} = value.value;
|
||||||
|
|
||||||
if (firstname && lastname) {
|
if (firstname && lastname) {
|
||||||
return `${lastname}, ${firstname}`;
|
return `${lastname}, ${firstname}`;
|
||||||
@@ -49,38 +41,29 @@ export const useUserStore = defineStore(
|
|||||||
})
|
})
|
||||||
|
|
||||||
const alias = computed(() => {
|
const alias = computed(() => {
|
||||||
if (user.value) {
|
if (value.value) {
|
||||||
return user.value.alias || `${user.value.firstname || ''} ${user.value.lastname || ''}`.trim() || 'Anonyme'
|
return value.value.alias || `${value.value.firstname || ''} ${value.value.lastname || ''}`.trim() || 'Anonyme'
|
||||||
}
|
}
|
||||||
return 'Anonyme';
|
return 'Anonyme';
|
||||||
})
|
})
|
||||||
|
|
||||||
const portraitUrl = computed(() => {
|
const portraitUrl = computed(() => {
|
||||||
return user.value && user.value.portraitUrl
|
return value.value && value.value.portraitUrl
|
||||||
? user.value.portraitUrl
|
? value.value.portraitUrl
|
||||||
: '/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png'
|
: '/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png'
|
||||||
})
|
})
|
||||||
|
|
||||||
const client = useClient()
|
|
||||||
|
|
||||||
async function fetchCurrentUserProfile() {
|
async function fetchCurrentUserProfile() {
|
||||||
try {
|
try {
|
||||||
|
const client = useClient()
|
||||||
const userResponse = await client.get("/api/users/profile");
|
const userResponse = await client.get("/api/users/profile");
|
||||||
user.value = userResponse.data
|
value.value = userResponse.data
|
||||||
// Cache-busting only if portraitUrl exists
|
// Cache-busting only if portraitUrl exists
|
||||||
if (user.value.portraitUrl) {
|
if (value.value.portraitUrl) {
|
||||||
user.value.portraitUrl = `${user.value.portraitUrl}?${Date.now()}`;
|
value.value.portraitUrl = `${value.value.portraitUrl}?${Date.now()}`;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
user.value = undefined;
|
value.value = undefined;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchCurrentCreatorProfile() {
|
|
||||||
try {
|
|
||||||
const creatorResponse = await client.get(`/api/creators/profile`)
|
|
||||||
creator.value = creatorResponse.data
|
|
||||||
} catch (error) {
|
|
||||||
creator.value = undefined
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,8 +75,8 @@ export const useUserStore = defineStore(
|
|||||||
firstname: firstname,
|
firstname: firstname,
|
||||||
lastname: lastname
|
lastname: lastname
|
||||||
})
|
})
|
||||||
user.value.firstname = firstname;
|
value.value.firstname = firstname;
|
||||||
user.value.lastname = lastname;
|
value.value.lastname = lastname;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -106,7 +89,7 @@ export const useUserStore = defineStore(
|
|||||||
{
|
{
|
||||||
alias: alias
|
alias: alias
|
||||||
})
|
})
|
||||||
user.value.alias = alias;
|
value.value.alias = alias;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -119,7 +102,7 @@ export const useUserStore = defineStore(
|
|||||||
{
|
{
|
||||||
birthdate: birthdate
|
birthdate: birthdate
|
||||||
})
|
})
|
||||||
user.value.birthDate = birthdate;
|
value.value.birthDate = birthdate;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -132,7 +115,7 @@ export const useUserStore = defineStore(
|
|||||||
{
|
{
|
||||||
phoneNumber: phoneNumber
|
phoneNumber: phoneNumber
|
||||||
})
|
})
|
||||||
user.value.phoneNumber = phoneNumber;
|
value.value.phoneNumber = phoneNumber;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -145,7 +128,7 @@ export const useUserStore = defineStore(
|
|||||||
{
|
{
|
||||||
email: email
|
email: email
|
||||||
})
|
})
|
||||||
user.value.email = email;
|
value.value.email = email;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -158,7 +141,7 @@ export const useUserStore = defineStore(
|
|||||||
{
|
{
|
||||||
address: address
|
address: address
|
||||||
})
|
})
|
||||||
user.value.address = address;
|
value.value.address = address;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -173,17 +156,15 @@ export const useUserStore = defineStore(
|
|||||||
`/api/users/portrait`,
|
`/api/users/portrait`,
|
||||||
formData)
|
formData)
|
||||||
|
|
||||||
user.value.portraitUrl = `${response.data.blobUrl}?${Date.now()}` // the Date.now() is for cache-busting
|
value.value.portraitUrl = `${response.data.blobUrl}?${Date.now()}` // the Date.now() is for cache-busting
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user,
|
user: value,
|
||||||
creator,
|
|
||||||
alias,
|
alias,
|
||||||
hasCreator,
|
|
||||||
fullname,
|
fullname,
|
||||||
portraitUrl,
|
portraitUrl,
|
||||||
changeFullname,
|
changeFullname,
|
||||||
@@ -192,7 +173,6 @@ export const useUserStore = defineStore(
|
|||||||
changePhone,
|
changePhone,
|
||||||
changeEmail,
|
changeEmail,
|
||||||
changeAddress,
|
changeAddress,
|
||||||
changePortrait,
|
changePortrait
|
||||||
fetchCurrentCreatorProfile
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -14,11 +14,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<selected-footer></selected-footer>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
import LoginForm from "@/views/main/LoginForm.vue";
|
import LoginForm from "@/views/main/LoginForm.vue";
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
<RouterLink v-for="(creator, index) in creators"
|
<RouterLink v-for="(creator, index) in creators"
|
||||||
:key="index"
|
:key="index"
|
||||||
:to="creator.routerLink">
|
:to="creator.routerLink">
|
||||||
<CreatorCard :creator="creator"
|
<creator-card :creator="creator"
|
||||||
class="m-2">
|
class="m-2">
|
||||||
</CreatorCard>
|
</creator-card>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -27,6 +27,6 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import CreatorCard from "@/views/creators/CreatorCard.vue";
|
import CreatorCard from "@/views/browser/CreatorCard.vue";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -72,13 +72,7 @@
|
|||||||
{{ messageCount }}
|
{{ messageCount }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<donation-button :color-border="colorMenu"
|
<donation-button></donation-button>
|
||||||
:color-accent="colorAccent"
|
|
||||||
:creator-id="creatorId"
|
|
||||||
:creator-name="creatorName"
|
|
||||||
:creator-logo="creatorLogo"
|
|
||||||
iconColorClass="text-black"
|
|
||||||
></donation-button>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<v-infinite-scroll :items="contents"
|
<div>
|
||||||
:onLoad="fetchContents"
|
|
||||||
class="md:gap-2">
|
|
||||||
|
|
||||||
|
<v-infinite-scroll :items="contents"
|
||||||
|
:onLoad="fetchContents">
|
||||||
|
|
||||||
|
<!-- TODO: the -mt-4 is necessary because the v-infinite-scroll has some 'top' panel offsetting the list -->
|
||||||
|
<div class="flex flex-column gap-4 -mt-4">
|
||||||
<template v-for="content in contents" :key="content.id">
|
<template v-for="content in contents" :key="content.id">
|
||||||
<component
|
<component
|
||||||
:is="isSmallScreen ? ContentCardSm : ContentCardNormal"
|
:is="isSmallScreen ? ContentCardSm : ContentCardNormal"
|
||||||
@@ -11,6 +14,7 @@
|
|||||||
@content-deleted="onContentDeleted"
|
@content-deleted="onContentDeleted"
|
||||||
></component>
|
></component>
|
||||||
</template>
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
<template v-slot:empty>
|
<template v-slot:empty>
|
||||||
Il n'y a pas plus de contenus
|
Il n'y a pas plus de contenus
|
||||||
@@ -22,8 +26,13 @@
|
|||||||
|
|
||||||
</v-infinite-scroll>
|
</v-infinite-scroll>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {useClient} from '@/plugins/api.js';
|
import {useClient} from '@/plugins/api.js';
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useClient} from '@/plugins/api.js';
|
import {useClient} from '@/plugins/api.js';
|
||||||
import {ref} from 'vue';
|
import {ref} from 'vue';
|
||||||
import {useUserStore} from '@/stores/userStore.js';
|
|
||||||
import {v7} from 'uuid';
|
import {v7} from 'uuid';
|
||||||
|
import {useCreatorProfileStore} from "@/stores/creatorProfileStore.js";
|
||||||
|
import {useUserProfileStore} from "@/stores/userProfileStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
creator: {type: Object, required: true},
|
creator: {type: Object, required: true},
|
||||||
@@ -10,7 +11,8 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emits = defineEmits(['content-posted'])
|
const emits = defineEmits(['content-posted'])
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userProfileStore = useUserProfileStore()
|
||||||
|
const creatorProfileStore = useCreatorProfileStore()
|
||||||
|
|
||||||
const isDialogActive = ref(false);
|
const isDialogActive = ref(false);
|
||||||
|
|
||||||
@@ -31,7 +33,7 @@ const removeUrl = (index) => {
|
|||||||
async function publishPost() {
|
async function publishPost() {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('id', v7());
|
formData.append('id', v7());
|
||||||
formData.append('creatorId', userStore.user.id);
|
formData.append('creatorId', creatorProfileStore.value.id);
|
||||||
formData.append('title', title.value);
|
formData.append('title', title.value);
|
||||||
formData.append('description', message.value);
|
formData.append('description', message.value);
|
||||||
files.value.forEach(file => {
|
files.value.forEach(file => {
|
||||||
@@ -73,7 +75,7 @@ const closeDialog = () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
v-if="creator && userStore.user && creator.id === userStore.user.id"
|
v-if="creator && userProfileStore.value && creator.id === userProfileStore.value.id"
|
||||||
class="flex items-center text-white transform transition-transform duration-200 hover:text-gray-300 hover:scale-125 px-4"
|
class="flex items-center text-white transform transition-transform duration-200 hover:text-gray-300 hover:scale-125 px-4"
|
||||||
@click="isDialogActive = true">
|
@click="isDialogActive = true">
|
||||||
<v-icon style="font-size: 35px; height: 35px; width: 55px;">mdi-text-box-plus-outline</v-icon>
|
<v-icon style="font-size: 35px; height: 35px; width: 55px;">mdi-text-box-plus-outline</v-icon>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useUserStore } from "@/stores/userStore.js";
|
|
||||||
import { REACTIONS } from "@/Constants/Reactions.js";
|
import { REACTIONS } from "@/Constants/Reactions.js";
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import { useClient } from "@/plugins/api.js";
|
import { useClient } from "@/plugins/api.js";
|
||||||
import {useAuthStore} from "@/stores/authStore.js"
|
import {useAuthStore} from "@/stores/authStore.js"
|
||||||
import MustBeLogged from "@/views/MustBeLogged.vue";
|
import MustBeLogged from "@/views/MustBeLogged.vue";
|
||||||
|
import {useUserProfileStore} from "@/stores/userProfileStore.js";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userProfileStore = useUserProfileStore();
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -49,8 +49,8 @@ async function reactToContent(reaction) {
|
|||||||
const request = {
|
const request = {
|
||||||
ContentId: contentId.value,
|
ContentId: contentId.value,
|
||||||
reaction: reaction,
|
reaction: reaction,
|
||||||
userId: userStore.user.id,
|
userId: userProfileStore.value.id,
|
||||||
userName: `${userStore.user.firstName} ${userStore.user.lastName}`,
|
userName: `${userProfileStore.value.firstName} ${userProfileStore.value.lastName}`,
|
||||||
};
|
};
|
||||||
adjustReactionCount(reaction);
|
adjustReactionCount(reaction);
|
||||||
await client.post("/api/content/reaction/", request);
|
await client.post("/api/content/reaction/", request);
|
||||||
@@ -61,8 +61,8 @@ async function reactToContent(reaction) {
|
|||||||
const requestAdd = {
|
const requestAdd = {
|
||||||
ContentId: contentId.value,
|
ContentId: contentId.value,
|
||||||
reaction: reaction,
|
reaction: reaction,
|
||||||
userId: userStore.user.id,
|
userId: userProfileStore.value.id,
|
||||||
userName: `${userStore.user.firstName} ${userStore.user.lastName}`,
|
userName: `${userProfileStore.value.firstName} ${userProfileStore.value.lastName}`,
|
||||||
};
|
};
|
||||||
adjustReactionCount(reaction);
|
adjustReactionCount(reaction);
|
||||||
await client.post("/api/content/reaction/", requestAdd);
|
await client.post("/api/content/reaction/", requestAdd);
|
||||||
@@ -71,7 +71,7 @@ async function reactToContent(reaction) {
|
|||||||
} else {
|
} else {
|
||||||
const requestRemove = {
|
const requestRemove = {
|
||||||
ContentId: contentId.value,
|
ContentId: contentId.value,
|
||||||
userId: userStore.user.id,
|
userId: userProfileStore.value.id,
|
||||||
};
|
};
|
||||||
adjustReactionCount(reaction);
|
adjustReactionCount(reaction);
|
||||||
await client.post("/api/content/reaction/remove", requestRemove);
|
await client.post("/api/content/reaction/remove", requestRemove);
|
||||||
@@ -168,7 +168,7 @@ function adjustReactionCount(newReaction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initializeReactions() {
|
function initializeReactions() {
|
||||||
const userReaction = props.content.reactions.find((x) => x.userId === userStore.user.id);
|
const userReaction = props.content.reactions.find((x) => x.userId === userProfileStore.value.id);
|
||||||
if (userReaction) {
|
if (userReaction) {
|
||||||
currentReaction.value = userReaction.reaction;
|
currentReaction.value = userReaction.reaction;
|
||||||
hasReacted.value = true;
|
hasReacted.value = true;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="shadow-md rounded-2xl bg-gray-50 border custom-border w-full mb-2 ">
|
<div class="shadow-md rounded-2xl bg-gray-50 border custom-border w-full">
|
||||||
<div>
|
<div>
|
||||||
<v-card-title>
|
<v-card-title>
|
||||||
<div class="flex flex-row justify-between items-center">
|
<div class="flex flex-row justify-between items-center">
|
||||||
@@ -72,13 +72,7 @@
|
|||||||
{{ messageCount }}
|
{{ messageCount }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<donation-button :color-border="colorMenu"
|
<donation-button></donation-button>
|
||||||
:color-accent="colorAccent"
|
|
||||||
:creator-id="creatorId"
|
|
||||||
:creator-name="creatorName"
|
|
||||||
:creator-logo="creatorLogo"
|
|
||||||
iconColorClass="text-black"
|
|
||||||
></donation-button>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -161,10 +155,6 @@ const emits = defineEmits(['content-deleted'])
|
|||||||
|
|
||||||
const contentId = computed(() => props.content.id)
|
const contentId = computed(() => props.content.id)
|
||||||
const creatorId = computed(() => props.content.createdBy)
|
const creatorId = computed(() => props.content.createdBy)
|
||||||
const creatorName = computed(() => props.content.createdByName)
|
|
||||||
const creatorLogo = computed(() => props.content.createdByPortraitUrl)
|
|
||||||
const colorMenu = computed(() => props.content.colorMenu)
|
|
||||||
const colorAccent = computed(() => props.content.colorAccent)
|
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const messageStore = useMessageStore();
|
const messageStore = useMessageStore();
|
||||||
|
|||||||
@@ -72,13 +72,7 @@
|
|||||||
{{ messageCount }}
|
{{ messageCount }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<donation-button :color-border="colorMenu"
|
<donation-button></donation-button>
|
||||||
:color-accent="colorAccent"
|
|
||||||
:creator-id="creatorId"
|
|
||||||
:creator-name="creatorName"
|
|
||||||
:creator-logo="creatorLogo"
|
|
||||||
iconColorClass="text-black"
|
|
||||||
></donation-button>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -161,10 +155,6 @@ const emits = defineEmits(['content-deleted'])
|
|||||||
|
|
||||||
const contentId = computed(() => props.content.id)
|
const contentId = computed(() => props.content.id)
|
||||||
const creatorId = computed(() => props.content.createdBy)
|
const creatorId = computed(() => props.content.createdBy)
|
||||||
const creatorName = computed(() => props.content.createdByName)
|
|
||||||
const creatorLogo = computed(() => props.content.createdByPortraitUrl)
|
|
||||||
const colorMenu = computed(() => props.content.colorMenu)
|
|
||||||
const colorAccent = computed(() => props.content.colorAccent)
|
|
||||||
|
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
const creatorIsCurrentUser = computed(() => authStore.isAuthenticated && authStore.userId === creatorId.value)
|
const creatorIsCurrentUser = computed(() => authStore.isAuthenticated && authStore.userId === creatorId.value)
|
||||||
|
|||||||
@@ -53,14 +53,7 @@
|
|||||||
<div class="flex justify-around py-2">
|
<div class="flex justify-around py-2">
|
||||||
<Reaction v-if="data" :content="data"></Reaction>
|
<Reaction v-if="data" :content="data"></Reaction>
|
||||||
|
|
||||||
<donation-button v-if="data"
|
<donation-button v-if="data"></donation-button>
|
||||||
:color-border="data.colorMenu"
|
|
||||||
:color-accent="data.colorAccent"
|
|
||||||
:creator-id="data.createdBy"
|
|
||||||
:creator-name="data.createdByName"
|
|
||||||
:creator-logo="data.createdByPortraitUrl"
|
|
||||||
iconColorClass="text-black"
|
|
||||||
></donation-button>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -45,27 +45,21 @@
|
|||||||
<div class="flex flex-col p-6 bg-white overflow-y-auto max-h-screen">
|
<div class="flex flex-col p-6 bg-white overflow-y-auto max-h-screen">
|
||||||
|
|
||||||
<div class="border-b-2 p-6 font-sans space-y-2">
|
<div class="border-b-2 p-6 font-sans space-y-2">
|
||||||
|
|
||||||
<div class="flex flex-row align-center" v-if="data && data.createdByName">
|
<div class="flex flex-row align-center" v-if="data && data.createdByName">
|
||||||
<img :src="data.createdByPortraitUrl" class="rounded-full w-9" alt="">
|
<img :src="data.createdByPortraitUrl" class="rounded-full w-9" alt="">
|
||||||
<p class="ml-2 capitalize ">{{ data.createdByName }}</p>
|
<p class="ml-2 capitalize ">{{ data.createdByName }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="data && data.description">
|
<div v-if="data && data.description">
|
||||||
Description: {{ data.description }}
|
Description: {{ data.description }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-around py-2">
|
<div v-if="data" class="flex justify-around py-2">
|
||||||
<Reaction v-if="data" :content="data"></Reaction>
|
<reaction :content="data"></reaction>
|
||||||
|
<donation-button></donation-button>
|
||||||
<donation-button v-if="data"
|
|
||||||
:color-border="data.colorMenu"
|
|
||||||
:color-accent="data.colorAccent"
|
|
||||||
:creator-id="data.createdBy"
|
|
||||||
:creator-name="data.createdByName"
|
|
||||||
:creator-logo="data.createdByPortraitUrl"
|
|
||||||
iconColorClass="text-black"
|
|
||||||
></donation-button>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-b-2 p-6">
|
<div class="border-b-2 p-6">
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
class="flex items-center text-white transform transition-transform duration-200 hover:text-gray-300 hover:scale-125 "
|
|
||||||
@click="AboutUs = true"
|
|
||||||
>
|
|
||||||
<v-icon style="font-size: 30px; height: 30px; width: 55px;">
|
|
||||||
mdi-information
|
|
||||||
</v-icon>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<v-dialog v-model="AboutUs" max-width="500px">
|
|
||||||
<v-form>
|
|
||||||
<v-card class="text-center rounded-xl"
|
|
||||||
:style="{
|
|
||||||
border: `3px solid ${creator.colors.menu}`
|
|
||||||
}">
|
|
||||||
|
|
||||||
<div class="flex items-center justify-between py-4 text-2xl font-bold border-b mb-2">
|
|
||||||
<div class="flex-1 text-center">
|
|
||||||
{{ creator.about.title }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<v-btn icon @click="AboutUs = false" class="ml-auto mr-2" variant="text">
|
|
||||||
<v-icon>mdi-close</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<v-card-text class="scrollable-content">
|
|
||||||
{{ creator.about.description }}
|
|
||||||
</v-card-text>
|
|
||||||
|
|
||||||
<div class="p-4">
|
|
||||||
<v-btn variant="outlined" text class=" w-full" @click="AboutUs = false" :style="{ borderColor: creator.colors.menu, color: creator.colors.menu }">Fermer</v-btn>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</v-card>
|
|
||||||
</v-form>
|
|
||||||
</v-dialog>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import {ref} from 'vue';
|
|
||||||
|
|
||||||
const AboutUs = ref(false);
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
creator: {type: Object, required: true},
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.scrollable-content {
|
|
||||||
max-height: 600px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.scrollable-content::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -1,17 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="shadow-lg rounded-2xl" :style="{ backgroundColor: creator.colors.bannerBottom}">
|
<div class="shadow-lg rounded-2xl"
|
||||||
|
:style="{ backgroundColor: branding.value.colors.secondary}">
|
||||||
<div class="relative z-20">
|
<div class="relative z-20">
|
||||||
<div class="py-4 min-h-9 md:rounded-t-2xl"
|
|
||||||
:style="{ backgroundColor: creator.colors.bannerTop || '#6B0065' }">
|
|
||||||
</div>
|
|
||||||
<div class="h-1" :style="{ backgroundColor: creator.colors.accent || '#6B0065' }"> </div>
|
|
||||||
|
|
||||||
<!--Banner-->
|
<!--Banner-->
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<div>
|
<div>
|
||||||
<img
|
<img
|
||||||
class="w-full drop-shadow-[0_10px_6px_rgba(0,0,0,0.25)]"
|
class="w-full drop-shadow-[0_10px_6px_rgba(0,0,0,0.25)]"
|
||||||
:src="creator.images.banner ? creator.images.banner : '/images/placeholders/banner.png'"
|
:src="branding.value.images.banner ? branding.value.images.banner : '/images/placeholders/banner.png'"
|
||||||
alt="Profile Banner"
|
alt="Profile Banner"
|
||||||
style="max-height: 425px"
|
style="max-height: 425px"
|
||||||
>
|
>
|
||||||
@@ -19,24 +16,16 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="h-1" :style="{ backgroundColor: creator.colors.accent || '#6B0065' }"></div>
|
|
||||||
<!--actions - Lowerpart-->
|
<!--actions - Lowerpart-->
|
||||||
<banner-actions :creator="creator" @content-posted="addContent"></banner-actions>
|
<banner-actions></banner-actions>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import BannerActions from "@/views/creators/banner/bannerlower/BannerActions.vue";
|
import BannerActions from "@/views/creators/banner/bannerlower/BannerActions.vue";
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const branding = useBrandingStore()
|
||||||
creator: {type: Object, required: true},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emits = defineEmits(['content-posted'])
|
|
||||||
|
|
||||||
function addContent(content) {
|
|
||||||
emits('content-posted', content)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
29
src/views/creators/CreatorContent.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="brandingStore.value.loading">
|
||||||
|
<v-progress-linear indeterminate></v-progress-linear>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else>
|
||||||
|
<div class="w-full h-full pr-4">
|
||||||
|
<content-list :creator-id="brandingStore.value.id"
|
||||||
|
:contents="news"
|
||||||
|
></content-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script async setup>
|
||||||
|
import { ref} from 'vue';
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
import ContentList from "@/views/contents/ContentList.vue";
|
||||||
|
|
||||||
|
const brandingStore = useBrandingStore()
|
||||||
|
|
||||||
|
const contents = ref([])
|
||||||
|
function contentPosted(content) {
|
||||||
|
contents.value.unshift(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :style="{ backgroundColor: '#2D2728' }">
|
|
||||||
<div class="mt-10" v-if="creator && creator.id">
|
|
||||||
<div class="max-w-[1500px] mx-auto">
|
|
||||||
<creator-banner :creator="creator"
|
|
||||||
@content-posted="contentPosted"
|
|
||||||
></creator-banner>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else>
|
|
||||||
<div v-if="loading">
|
|
||||||
<v-progress-linear indeterminate></v-progress-linear>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<v-card>
|
|
||||||
<v-card-text style="text-align: center;">
|
|
||||||
Aucun créateur au nom de {{ route.params.creator }}
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-row max-w-[1500px] mx-auto justify-center mt-8">
|
|
||||||
<div>
|
|
||||||
<div class="flex flex-column px-2 max-w-[1200px]">
|
|
||||||
<exclusive-content-container :creator="creator"></exclusive-content-container>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-80 hidden xl:block">
|
|
||||||
<!-- Rewards component will be visible only on xl screens -->
|
|
||||||
<rewards :creator="creator"></rewards>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<script async setup>
|
|
||||||
import {watch, ref, onBeforeMount} from 'vue';
|
|
||||||
import {useRoute} from 'vue-router';
|
|
||||||
import {useClient} from "@/plugins/api.js";
|
|
||||||
import CreatorBanner from "@/views/creators/CreatorBanner.vue";
|
|
||||||
import Creatornewssummary from "@/views/creators/CreatorNewsSummary.vue";
|
|
||||||
import Rewards from "@/views/creators/Rewards.vue";
|
|
||||||
import ExclusiveContentContainer from "@/views/creators/ExclusiveContentContainer.vue";
|
|
||||||
|
|
||||||
|
|
||||||
const creator = ref(null)
|
|
||||||
const loading = ref(true)
|
|
||||||
const contents = ref([])
|
|
||||||
|
|
||||||
const client = useClient()
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
function contentPosted(content) {
|
|
||||||
contents.value.unshift(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount(async () => await fetchCreatorData(route.params.creator))
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => route.params.creator,
|
|
||||||
async () => await fetchCreatorData(route.params.creator)
|
|
||||||
)
|
|
||||||
|
|
||||||
const fetchCreatorData = async (creatorAlias) => {
|
|
||||||
try {
|
|
||||||
loading.value = true
|
|
||||||
const response = await client.get(`/api/creators/@${creatorAlias}`)
|
|
||||||
creator.value = response.data
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error fetching content: ${error}`)
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
27
src/views/creators/CreatorHome.vue
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-row">
|
||||||
|
|
||||||
|
<div class="max-w-80">
|
||||||
|
<creator-news-summary></creator-news-summary>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="px-4" :style="{ color: brandingStore.value.colors.onBackground}">
|
||||||
|
<h1>TEST</h1>
|
||||||
|
<p>GET ME AN EDITOR NOW!</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
import CreatorNewsSummary from "@/views/creators/CreatorNewsSummary.vue"
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
|
const brandingStore = useBrandingStore()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
49
src/views/creators/CreatorLayout.vue
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<template>
|
||||||
|
<div :style="{ backgroundColor: brandingStore.value.colors.background }">
|
||||||
|
<div class="max-w-[1500px] mx-auto">
|
||||||
|
|
||||||
|
<div v-if="brandingStore.value && brandingStore.value.id">
|
||||||
|
<creator-banner></creator-banner>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div v-if="loading">
|
||||||
|
<v-progress-linear indeterminate></v-progress-linear>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<v-card>
|
||||||
|
<v-card-text style="text-align: center;">
|
||||||
|
Aucun créateur au nom de {{ route.params.creator }}
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-row justify-center py-10">
|
||||||
|
|
||||||
|
<div class="w-full">
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="max-w-80">
|
||||||
|
<rewards></rewards>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Footer></Footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script async setup>
|
||||||
|
import {watch, ref, onBeforeMount} from 'vue';
|
||||||
|
import {useRoute} from 'vue-router';
|
||||||
|
import {useClient} from "@/plugins/api.js";
|
||||||
|
import CreatorBanner from "@/views/creators/CreatorBanner.vue";
|
||||||
|
import Rewards from "@/views/creators/Rewards.vue";
|
||||||
|
import Footer from "@/views/main/Footer.vue";
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
|
const brandingStore = useBrandingStore()
|
||||||
|
</script>
|
||||||
29
src/views/creators/CreatorNews.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<div v-if="brandingStore.value.loading">
|
||||||
|
<v-progress-linear indeterminate></v-progress-linear>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else>
|
||||||
|
<div class="w-full h-full pr-4">
|
||||||
|
<news-list :creator-id="brandingStore.value.id"
|
||||||
|
:news="news"
|
||||||
|
></news-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script async setup>
|
||||||
|
import {ref} from 'vue';
|
||||||
|
import NewsList from "@/views/news/NewsList.vue";
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
|
const brandingStore = useBrandingStore()
|
||||||
|
|
||||||
|
const news = ref([])
|
||||||
|
function newsPosted(content) {
|
||||||
|
news.value.unshift(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -1,30 +1,49 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="overflow-hidden relative" @wheel="handleScroll">
|
<div class="text-center rounded-t-lg p-4 tracking-widest uppercase"
|
||||||
<div class="text-center text-white rounded-t-lg mb-1 py-1"
|
:style="{ color: brandingStore.value.colors.onPrimary, backgroundColor: brandingStore.value.colors.primary}">
|
||||||
:style="{ backgroundColor: creator.colors.bannerTop, letterSpacing: '5px' }">
|
|
||||||
Actualité
|
Actualité
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Container that holds all the posts and allows dynamic scrolling -->
|
<div v-for="(item, index) in articles"
|
||||||
<div class="relative max-h-[1000px] overflow-hidden">
|
class="my-1 text-white"
|
||||||
<div class="transition-transform duration-500" :style="{ transform: `translateY(-${scrollPosition}px)` }">
|
:key="index"
|
||||||
<div v-for="(item, index) in actualites" :key="index" class="my-1 text-white"
|
:style="{ backgroundColor: brandingStore.value.colors.primary }">
|
||||||
:style="{ backgroundColor: creator.colors.bannerTop }">
|
|
||||||
<div class="flex justify-between items-center border-b-2 border-white p-3 mx-2">
|
<div class="flex justify-between items-center border-b-2 border-white p-2 mx-2">
|
||||||
<p v-if="item.type === 'nouvelle'" class="text-xl" :style="{ letterSpacing: '8px' }">Nouvelle</p>
|
<p class="text-xl tracking-[8px]">
|
||||||
<p v-if="item.type === 'contenu'" class="text-xl" :style="{ letterSpacing: '8px' }">Contenu</p>
|
<span v-if="item.type === 'nouvelle'">
|
||||||
|
Nouvelle
|
||||||
|
</span>
|
||||||
|
<span v-if="item.type === 'contenu'">
|
||||||
|
Contenu
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
<p class="text-xs">{{ item.date }}</p>
|
<p class="text-xs">{{ item.date }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-3">
|
<div class="p-4">
|
||||||
<div class="text-lg" style="letter-spacing: 2px">{{ item.title }}</div>
|
<div class="text-lg tracking-[2px]">
|
||||||
<p v-if="item.description" class="text-gray-300 text-sm text-justify mt-1 py-1">{{ item.description }}</p>
|
{{ item.title }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p v-if="item.description"
|
||||||
|
class="text-gray-300 text-sm text-justify mt-1 py-1">
|
||||||
|
{{ item.description }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<div v-if="item.rating" class="stars flex justify-end">
|
<div v-if="item.rating" class="stars flex justify-end">
|
||||||
{{ item.rating }} ★
|
{{ item.rating }} ★
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<img v-if="item.photo" :src="item.photo" class="w-full h-auto my-2"/>
|
<img v-if="item.photo"
|
||||||
|
:src="item.photo"
|
||||||
|
class="w-full h-auto my-2"/>
|
||||||
|
|
||||||
|
<video v-if="item.video"
|
||||||
|
controls
|
||||||
|
:src="item.video"
|
||||||
|
class="w-full h-auto my-2">
|
||||||
|
</video>
|
||||||
|
|
||||||
<div class="flex justify-evenly">
|
<div class="flex justify-evenly">
|
||||||
<v-btn icon variant="plain">
|
<v-btn icon variant="plain">
|
||||||
@@ -37,35 +56,19 @@
|
|||||||
<v-icon>mdi-gift-outline</v-icon>
|
<v-icon>mdi-gift-outline</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
<video v-if="item.video" controls :src="item.video" class="w-full h-auto my-2"></video>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Navigation Buttons directly below the content -->
|
|
||||||
<div class="flex justify-center mt-2 space-x-2" v-if="showNavigationButtons">
|
|
||||||
<v-btn variant="text" class="text-white" height="42" @click="scrollUp">
|
|
||||||
<v-icon size="40">mdi-arrow-up-drop-circle-outline</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-btn variant="text" class="text-white" height="42" @click="scrollDown">
|
|
||||||
<v-icon size="40">mdi-arrow-down-drop-circle-outline</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, defineProps } from 'vue';
|
import {ref} from 'vue';
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
creator: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const actualites = ref([
|
const articles = ref([
|
||||||
{
|
{
|
||||||
type: 'nouvelle',
|
type: 'nouvelle',
|
||||||
title: 'La visite du studio',
|
title: 'La visite du studio',
|
||||||
@@ -113,45 +116,4 @@ const actualites = ref([
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const startIndex = ref(0);
|
|
||||||
const cardsPerPage = 3;
|
|
||||||
|
|
||||||
// Gestion de la position du scroll
|
|
||||||
const scrollPosition = ref(0);
|
|
||||||
const cardHeight = 250; // Hauteur approximative d'une carte en pixels
|
|
||||||
|
|
||||||
// Calculer l'index final
|
|
||||||
const endIndex = computed(() => startIndex.value + cardsPerPage);
|
|
||||||
const visibleCards = computed(() => actualites.value.slice(startIndex.value, endIndex.value));
|
|
||||||
|
|
||||||
// Calculer si les boutons doivent être affichés
|
|
||||||
const showNavigationButtons = computed(() => {
|
|
||||||
const totalHeight = actualites.value.length * cardHeight;
|
|
||||||
const containerHeight = cardsPerPage * cardHeight;
|
|
||||||
return totalHeight > containerHeight; // Afficher les boutons seulement si le contenu dépasse la hauteur du conteneur
|
|
||||||
});
|
|
||||||
|
|
||||||
function scrollDown() {
|
|
||||||
if (endIndex.value < actualites.value.length) {
|
|
||||||
startIndex.value += 1; // Défiler d'une carte à la fois
|
|
||||||
scrollPosition.value += cardHeight; // Augmenter la position de défilement
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function scrollUp() {
|
|
||||||
if (startIndex.value > 0) {
|
|
||||||
startIndex.value -= 1; // Défiler d'une carte à la fois
|
|
||||||
scrollPosition.value -= cardHeight; // Diminuer la position de défilement
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle scroll wheel event to scroll up or down
|
|
||||||
function handleScroll(event) {
|
|
||||||
event.preventDefault(); // Empêche le défilement de la page
|
|
||||||
if (event.deltaY < 0) {
|
|
||||||
scrollUp(); // Défilement vers le haut
|
|
||||||
} else if (event.deltaY > 0) {
|
|
||||||
scrollDown(); // Défilement vers le bas
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :style="{ backgroundColor: '#2D2728' }">
|
|
||||||
<div class="mt-10" v-if="creator && creator.id">
|
|
||||||
<div class="max-w-[1500px] mx-auto">
|
|
||||||
<creator-banner :creator="creator"
|
|
||||||
@content-posted="contentPosted"
|
|
||||||
></creator-banner>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="max-w-[800px] mx-auto">
|
|
||||||
<div class="w-full h-full ">
|
|
||||||
<content-list :creator-id="creator.id"
|
|
||||||
:contents="contents"
|
|
||||||
></content-list>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else>
|
|
||||||
<div v-if="loading">
|
|
||||||
<v-progress-linear indeterminate></v-progress-linear>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<v-card>
|
|
||||||
<v-card-text style="text-align: center;">
|
|
||||||
Aucun créateur au nom de {{ route.params.creator }}
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script async setup>
|
|
||||||
import {watch, ref, onBeforeMount} from 'vue';
|
|
||||||
import {useRoute} from 'vue-router';
|
|
||||||
import {useClient} from "@/plugins/api.js";
|
|
||||||
import CreatorBanner from "@/views/creators/CreatorBanner.vue";
|
|
||||||
import ContentList from "@/views/contents/ContentList.vue";
|
|
||||||
|
|
||||||
const creator = ref(null)
|
|
||||||
const loading = ref(true)
|
|
||||||
const contents = ref([])
|
|
||||||
|
|
||||||
const client = useClient()
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
function contentPosted(content) {
|
|
||||||
contents.value.unshift(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount(async () => await fetchCreatorData(route.params.creator))
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => route.params.creator,
|
|
||||||
async () => await fetchCreatorData(route.params.creator)
|
|
||||||
)
|
|
||||||
|
|
||||||
const fetchCreatorData = async (creatorAlias) => {
|
|
||||||
try {
|
|
||||||
loading.value = true
|
|
||||||
const response = await client.get(`/api/creators/@${creatorAlias}`)
|
|
||||||
creator.value = response.data
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error fetching content: ${error}`)
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div :style="{ backgroundColor: '#2D2728' }">
|
|
||||||
<div class="mt-10" v-if="creator && creator.id">
|
|
||||||
<div class="max-w-[1500px] mx-auto">
|
|
||||||
<creator-banner :creator="creator"
|
|
||||||
@content-posted="contentPosted"
|
|
||||||
></creator-banner>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else>
|
|
||||||
<div v-if="loading">
|
|
||||||
<v-progress-linear indeterminate></v-progress-linear>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<v-card>
|
|
||||||
<v-card-text style="text-align: center;">
|
|
||||||
Aucun créateur au nom de {{ route.params.creator }}
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-row max-w-[1500px] mx-auto justify-center mt-8">
|
|
||||||
<div>
|
|
||||||
|
|
||||||
<!-- Actualité feed-->
|
|
||||||
<div class="flex flex-column px-2 max-w-80">
|
|
||||||
<Creatornewssummary :creator="creator"></Creatornewssummary>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="min-w-[875px]"></div>
|
|
||||||
<div class="max-w-80">
|
|
||||||
<rewards :creator="creator"></rewards>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script async setup>
|
|
||||||
import {watch, ref, onBeforeMount} from 'vue';
|
|
||||||
import {useRoute} from 'vue-router';
|
|
||||||
import {useClient} from "@/plugins/api.js";
|
|
||||||
import CreatorBanner from "@/views/creators/CreatorBanner.vue";
|
|
||||||
import Creatornewssummary from "@/views/creators/CreatorNewsSummary.vue";
|
|
||||||
import Rewards from "@/views/creators/Rewards.vue";
|
|
||||||
|
|
||||||
|
|
||||||
const creator = ref(null)
|
|
||||||
const loading = ref(true)
|
|
||||||
const contents = ref([])
|
|
||||||
|
|
||||||
const client = useClient()
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
function contentPosted(content) {
|
|
||||||
contents.value.unshift(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeMount(async () => await fetchCreatorData(route.params.creator))
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => route.params.creator,
|
|
||||||
async () => await fetchCreatorData(route.params.creator)
|
|
||||||
)
|
|
||||||
|
|
||||||
const fetchCreatorData = async (creatorAlias) => {
|
|
||||||
try {
|
|
||||||
loading.value = true
|
|
||||||
const response = await client.get(`/api/creators/@${creatorAlias}`)
|
|
||||||
creator.value = response.data
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`Error fetching content: ${error}`)
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -6,20 +6,20 @@
|
|||||||
|
|
||||||
<v-dialog v-model="donationModal" max-width="500">
|
<v-dialog v-model="donationModal" max-width="500">
|
||||||
<v-form>
|
<v-form>
|
||||||
<v-card class="text-center rounded-xl" :style="{ border: `3px solid ${colorBorder}` }">
|
<v-card class="text-center rounded-xl" :style="{ border: `3px solid ${brandingStore.value.colors.primary}` }">
|
||||||
<div class="py-4 text-2xl font-bold border-b mb-2">
|
<div class="py-4 text-2xl font-bold border-b mb-2">
|
||||||
Je Soutiens!
|
Je Soutiens!
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row align-center px-3">
|
<div class="flex flex-row align-center px-3">
|
||||||
<img
|
<img
|
||||||
:src="creatorLogo"
|
:src="brandingStore.value.images.logo"
|
||||||
alt="Profile Image"
|
alt="Profile Image"
|
||||||
class="rounded-full"
|
class="rounded-full"
|
||||||
width="40"
|
width="40"
|
||||||
height="40"
|
height="40"
|
||||||
:style="{ border: `2px solid ${colorAccent}` }">
|
:style="{ border: `2px solid ${brandingStore.value.colors.secondary}` }">
|
||||||
<div class="capitalize px-2 text-2xl">{{ creatorName }}</div>
|
<div class="capitalize px-2 text-2xl">{{ brandingStore.value.name }}</div>
|
||||||
<v-btn icon @click="closeDonationDialog()" class="ml-auto" variant="text">
|
<v-btn icon @click="closeDonationDialog()" class="ml-auto" variant="text">
|
||||||
<v-icon>mdi-close</v-icon>
|
<v-icon>mdi-close</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -50,7 +50,8 @@
|
|||||||
clearable
|
clearable
|
||||||
></v-textarea>
|
></v-textarea>
|
||||||
|
|
||||||
<v-btn variant="outlined" :style="{ borderColor: colorBorder, color: colorBorder }"
|
<v-btn variant="outlined"
|
||||||
|
:style="{ borderColor: brandingStore.value.colors.primary, color: brandingStore.value.colors.primary }"
|
||||||
@click="goPay()" class="w-full mt-5">
|
@click="goPay()" class="w-full mt-5">
|
||||||
Envoyez
|
Envoyez
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -68,7 +69,10 @@
|
|||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn block class="ma-auto" style="width: 200px;" text @click="closeDialog()">Annuler</v-btn>
|
<v-btn block class="ma-auto"
|
||||||
|
style="width: 200px;"
|
||||||
|
@click="closeDialog()">Annuler
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
@@ -79,23 +83,15 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useClient} from '@/plugins/api.js';
|
import {useClient} from '@/plugins/api.js';
|
||||||
import {loadStripe} from '@stripe/stripe-js';
|
import {loadStripe} from '@stripe/stripe-js';
|
||||||
import {computed, onMounted, ref} from 'vue';
|
import {onMounted, ref} from 'vue';
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
|
const brandingStore = useBrandingStore()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
colorBorder: {required: true},
|
|
||||||
colorAccent: {required: true},
|
|
||||||
creatorId: {type: String, required: true},
|
|
||||||
creatorName: {type: String, required: true},
|
|
||||||
creatorLogo: {required: true},
|
|
||||||
iconColorClass: {default: 'text-black'}
|
iconColorClass: {default: 'text-black'}
|
||||||
});
|
});
|
||||||
|
|
||||||
const colorBorder = computed(() => props.colorBorder)
|
|
||||||
const colorAccent = computed(() => props.colorAccent)
|
|
||||||
const creatorId = computed(() => props.creatorId)
|
|
||||||
const creatorName = computed(() => props.creatorName)
|
|
||||||
const creatorLogo = computed(() => props.creatorLogo)
|
|
||||||
|
|
||||||
const donationModal = ref(false);
|
const donationModal = ref(false);
|
||||||
|
|
||||||
function openDonationDialog() {
|
function openDonationDialog() {
|
||||||
@@ -145,6 +141,7 @@ function closeDialog() {
|
|||||||
checkout.destroy();
|
checkout.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function goPay() {
|
async function goPay() {
|
||||||
isPaymentDialogActive.value = true;
|
isPaymentDialogActive.value = true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-btn :style="{
|
<v-btn :style="{
|
||||||
backgroundColor: colorBorder, color: 'white',
|
backgroundColor: brandingStore.value.colors.primary,
|
||||||
borderRadius: '8px', padding:'20px 24px',
|
color: 'white',
|
||||||
display: 'flex', alignItems: 'center',
|
borderRadius: '8px',
|
||||||
justifyContent: 'center' }" @click="openDonationDialog()">
|
padding:'20px 24px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center' }"
|
||||||
|
@click="openDonationDialog()">
|
||||||
<div class="font-bold"> Je soutiens</div>
|
<div class="font-bold"> Je soutiens</div>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<v-dialog v-model="donationModal" max-width="500">
|
<v-dialog v-model="donationModal" max-width="500">
|
||||||
<v-form>
|
<v-form>
|
||||||
<v-card class="text-center rounded-xl" :style="{ border: `3px solid ${colorBorder}` }">
|
<v-card class="text-center rounded-xl" :style="{ border: `3px solid ${brandingStore.value.colors.primary}` }">
|
||||||
<div class="py-4 text-2xl font-bold border-b mb-2">
|
<div class="py-4 text-2xl font-bold border-b mb-2">
|
||||||
Je Soutiens!
|
Je Soutiens!
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row align-center px-3">
|
<div class="flex flex-row align-center px-3">
|
||||||
<img
|
<img
|
||||||
:src="creatorLogo"
|
:src="brandingStore.value.images.logo"
|
||||||
alt="Profile Image"
|
alt="Profile Image"
|
||||||
class="rounded-full"
|
class="rounded-full"
|
||||||
width="40"
|
width="40"
|
||||||
height="40"
|
height="40"
|
||||||
:style="{ border: `2px solid ${colorAccent}` }">
|
:style="{ border: `2px solid ${brandingStore.value.colors.secondary}` }">
|
||||||
<div class="capitalize px-2 text-2xl">{{ creatorName }}</div>
|
<div class="capitalize px-2 text-2xl">{{ brandingStore.value.name }}</div>
|
||||||
<v-btn icon @click="closeDonationDialog()" class="ml-auto" variant="text">
|
<v-btn icon @click="closeDonationDialog()" class="ml-auto" variant="text">
|
||||||
<v-icon>mdi-close</v-icon>
|
<v-icon>mdi-close</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -58,7 +57,7 @@
|
|||||||
clearable
|
clearable
|
||||||
></v-textarea>
|
></v-textarea>
|
||||||
|
|
||||||
<v-btn variant="outlined" :style="{ borderColor: colorBorder, color: colorBorder }"
|
<v-btn variant="outlined" :style="{ borderColor: brandingStore.value.colors.primary, color: brandingStore.value.colors.primary }"
|
||||||
@click="goPay()" class="w-full mt-5">
|
@click="goPay()" class="w-full mt-5">
|
||||||
Envoyez
|
Envoyez
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -87,22 +86,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useClient} from '@/plugins/api.js';
|
import {useClient} from '@/plugins/api.js';
|
||||||
import {loadStripe} from '@stripe/stripe-js';
|
import {loadStripe} from '@stripe/stripe-js';
|
||||||
import {computed, onMounted, ref} from 'vue';
|
import {onMounted, ref} from 'vue';
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
colorBorder: {required: true},
|
|
||||||
colorAccent: {required: true},
|
|
||||||
creatorId: {type: String, required: true},
|
|
||||||
creatorName: {type: String, required: true},
|
|
||||||
creatorLogo: {required: true},
|
|
||||||
iconColorClass: {default: 'text-black'}
|
|
||||||
});
|
|
||||||
|
|
||||||
const colorBorder = computed(() => props.colorBorder)
|
|
||||||
const colorAccent = computed(() => props.colorAccent)
|
|
||||||
const creatorId = computed(() => props.creatorId)
|
|
||||||
const creatorName = computed(() => props.creatorName)
|
|
||||||
const creatorLogo = computed(() => props.creatorLogo)
|
|
||||||
|
|
||||||
const donationModal = ref(false);
|
const donationModal = ref(false);
|
||||||
|
|
||||||
@@ -114,7 +101,6 @@ function closeDonationDialog() {
|
|||||||
donationModal.value = false
|
donationModal.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const isPaymentDialogActive = ref(false);
|
const isPaymentDialogActive = ref(false);
|
||||||
|
|
||||||
const tipAmount = ref(0);
|
const tipAmount = ref(0);
|
||||||
@@ -153,6 +139,7 @@ function closeDialog() {
|
|||||||
checkout.destroy();
|
checkout.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function goPay() {
|
async function goPay() {
|
||||||
isPaymentDialogActive.value = true;
|
isPaymentDialogActive.value = true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-btn :style="{
|
<v-btn :style="{
|
||||||
backgroundColor: colorBorder, color: 'white',
|
backgroundColor: brandingStore.value.colors.primary,
|
||||||
borderRadius: '8px', padding:'0px 24px',
|
color: 'white',
|
||||||
display: 'flex', alignItems: 'center',
|
borderRadius: '8px',
|
||||||
justifyContent: 'center' }" @click="openDonationDialog()">
|
padding:'0px 24px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center' }"
|
||||||
|
@click="openDonationDialog()">
|
||||||
<div class="font-bold">Je soutiens</div>
|
<div class="font-bold">Je soutiens</div>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<v-dialog v-model="donationModal" max-width="500">
|
<v-dialog v-model="donationModal" max-width="500">
|
||||||
<v-form>
|
<v-form>
|
||||||
<v-card class="text-center rounded-xl" :style="{ border: `3px solid ${colorBorder}` }">
|
<v-card class="text-center rounded-xl" :style="{ border: `3px solid ${brandingStore.value.colors.primary}` }">
|
||||||
<div class="py-4 text-2xl font-bold border-b mb-2">
|
<div class="py-4 text-2xl font-bold border-b mb-2">
|
||||||
Je Soutiens!
|
Je Soutiens!
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row align-center px-3">
|
<div class="flex flex-row align-center px-3">
|
||||||
<img
|
<img
|
||||||
:src="creatorLogo"
|
:src="brandingStore.value.images.logo"
|
||||||
alt="Profile Image"
|
alt="Profile Image"
|
||||||
class="rounded-full"
|
class="rounded-full"
|
||||||
width="40"
|
width="40"
|
||||||
height="40"
|
height="40"
|
||||||
:style="{ border: `2px solid ${colorAccent}` }">
|
:style="{ border: `2px solid ${brandingStore.value.colors.secondary}` }">
|
||||||
<div class="capitalize px-2 text-2xl">{{ creatorName }}</div>
|
<div class="capitalize px-2 text-2xl">{{ brandingStore.value.name }}</div>
|
||||||
<v-btn icon @click="closeDonationDialog()" class="ml-auto" variant="text">
|
<v-btn icon @click="closeDonationDialog()" class="ml-auto" variant="text">
|
||||||
<v-icon>mdi-close</v-icon>
|
<v-icon>mdi-close</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -58,7 +57,8 @@
|
|||||||
clearable
|
clearable
|
||||||
></v-textarea>
|
></v-textarea>
|
||||||
|
|
||||||
<v-btn variant="outlined" :style="{ borderColor: colorBorder, color: colorBorder }"
|
<v-btn variant="outlined"
|
||||||
|
:style="{ borderColor: brandingStore.value.colors.primary, color: brandingStore.value.colors.primary }"
|
||||||
@click="goPay()" class="w-full mt-5">
|
@click="goPay()" class="w-full mt-5">
|
||||||
Envoyez
|
Envoyez
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn block class="ma-auto" style="width: 200px;" text @click="closeDialog()">Annuler</v-btn>
|
<v-btn block class="ma-auto" style="width: 200px;" @click="closeDialog()">Annuler</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
@@ -87,22 +87,10 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useClient} from '@/plugins/api.js';
|
import {useClient} from '@/plugins/api.js';
|
||||||
import {loadStripe} from '@stripe/stripe-js';
|
import {loadStripe} from '@stripe/stripe-js';
|
||||||
import {computed, onMounted, ref} from 'vue';
|
import {onMounted, ref} from 'vue';
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
colorBorder: {required: true},
|
|
||||||
colorAccent: {required: true},
|
|
||||||
creatorId: {type: String, required: true},
|
|
||||||
creatorName: {type: String, required: true},
|
|
||||||
creatorLogo: {required: true},
|
|
||||||
iconColorClass: {default: 'text-black'}
|
|
||||||
});
|
|
||||||
|
|
||||||
const colorBorder = computed(() => props.colorBorder)
|
|
||||||
const colorAccent = computed(() => props.colorAccent)
|
|
||||||
const creatorId = computed(() => props.creatorId)
|
|
||||||
const creatorName = computed(() => props.creatorName)
|
|
||||||
const creatorLogo = computed(() => props.creatorLogo)
|
|
||||||
|
|
||||||
const donationModal = ref(false);
|
const donationModal = ref(false);
|
||||||
|
|
||||||
@@ -153,6 +141,7 @@ function closeDialog() {
|
|||||||
checkout.destroy();
|
checkout.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function goPay() {
|
async function goPay() {
|
||||||
isPaymentDialogActive.value = true;
|
isPaymentDialogActive.value = true;
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,22 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
|
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
creator: {type: Object, required: true},
|
|
||||||
colorBorder: {required: true},
|
|
||||||
});
|
|
||||||
|
|
||||||
const colorBorder = computed(() => props.colorBorder);
|
|
||||||
|
|
||||||
const subscriptionStore = useSubscriptionStore();
|
const subscriptionStore = useSubscriptionStore();
|
||||||
|
|
||||||
const isSubscribe = computed(() => !subscriptionStore.isSubscribeTo(props.creator.id));
|
const isSubscribe = computed(() => !subscriptionStore.isSubscribeTo(brandingStore.value.id));
|
||||||
|
|
||||||
function subscribeToCreator() {
|
function subscribeToCreator() {
|
||||||
subscriptionStore.subscribeTo(props.creator.id);
|
subscriptionStore.subscribeTo(brandingStore.value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Référence pour contrôler l'affichage du modal
|
// Référence pour contrôler l'affichage du modal
|
||||||
const showUnsubscribeModal = ref(false);
|
const showUnsubscribeModal = ref(false);
|
||||||
|
|
||||||
function unsubscribeFromCreator() {
|
function unsubscribeFromCreator() {
|
||||||
subscriptionStore.unsubscribeFrom(props.creator.id);
|
subscriptionStore.unsubscribeFrom(brandingStore.value.id);
|
||||||
// Fermer le modal après désabonnement
|
// Fermer le modal après désabonnement
|
||||||
showUnsubscribeModal.value = false;
|
showUnsubscribeModal.value = false;
|
||||||
}
|
}
|
||||||
@@ -33,7 +28,7 @@ function unsubscribeFromCreator() {
|
|||||||
:style="{
|
:style="{
|
||||||
width: '150px',
|
width: '150px',
|
||||||
height: '28px',
|
height: '28px',
|
||||||
backgroundColor: colorBorder,
|
backgroundColor: brandingStore.value.colors.secondary,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
borderRadius: '8px 0 0 8px',
|
borderRadius: '8px 0 0 8px',
|
||||||
padding: '10px 24px',
|
padding: '10px 24px',
|
||||||
@@ -53,7 +48,7 @@ function unsubscribeFromCreator() {
|
|||||||
:style="{
|
:style="{
|
||||||
width: '150px',
|
width: '150px',
|
||||||
height: '28px',
|
height: '28px',
|
||||||
backgroundColor: colorBorder,
|
backgroundColor: brandingStore.value.colors.secondary,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
borderRadius: '8px 0 0 8px',
|
borderRadius: '8px 0 0 8px',
|
||||||
padding: '10px 24px',
|
padding: '10px 24px',
|
||||||
@@ -70,7 +65,7 @@ function unsubscribeFromCreator() {
|
|||||||
|
|
||||||
<v-dialog v-model="showUnsubscribeModal" max-width="500">
|
<v-dialog v-model="showUnsubscribeModal" max-width="500">
|
||||||
<v-card class="text-center rounded-xl"
|
<v-card class="text-center rounded-xl"
|
||||||
:style="{ border: `3px solid ${creator.colors.menu}` }">
|
:style="{ border: `3px solid ${brandingStore.value.colors.secondary}` }">
|
||||||
|
|
||||||
<div class="flex items-center justify-between py-4 text-2xl font-bold border-b mb-2">
|
<div class="flex items-center justify-between py-4 text-2xl font-bold border-b mb-2">
|
||||||
<div class="flex-1 text-center">
|
<div class="flex-1 text-center">
|
||||||
@@ -87,9 +82,10 @@ function unsubscribeFromCreator() {
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-btn class="flex-grow-1"
|
<v-btn class="flex-grow-1"
|
||||||
:style="{ borderColor: creator.colors.menu, color: creator.colors.menu }" variant="outlined"
|
:style="{ borderColor: brandingStore.value.colors.secondary, color: brandingStore.value.colors.secondary }"
|
||||||
|
variant="outlined"
|
||||||
@click="showUnsubscribeModal = false">
|
@click="showUnsubscribeModal = false">
|
||||||
<div :style="{ color: creator.colors.menu }">Non</div>
|
<div :style="{ color: brandingStore.value.colors.secondary }">Non</div>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|||||||
@@ -1,52 +1,41 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="overflow-hidden relative" @wheel="handleScroll">
|
<div class="text-center rounded-t-lg p-4 tracking-widest uppercase"
|
||||||
|
:style="{ color: brandingStore.value.colors.onPrimary, backgroundColor: brandingStore.value.colors.primary}">
|
||||||
|
Récompenses
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="text-center text-white rounded-t-lg py-1 mb-1" :style="{ backgroundColor: creator.colors.bannerTop, letterSpacing: '5px' }">Récompenses</div>
|
<div v-for="(item, index) in rewards"
|
||||||
|
class="my-1 text-white"
|
||||||
|
:key="index"
|
||||||
|
:style="{ backgroundColor: brandingStore.value.colors.primary }">
|
||||||
|
|
||||||
<!-- Container that holds all the posts and allows dynamic scrolling -->
|
<div class="flex justify-center border-b-2 border-white p-3 mx-2 text-xl tracking-[4px]">
|
||||||
<div class="relative h-[1000px] max-h-[1000px] overflow-hidden">
|
{{ item.title }}
|
||||||
<div class="transition-transform duration-500" :style="{ transform: `translateY(-${scrollPosition}px)` }">
|
|
||||||
<div v-for="(item, index) in actualites" :key="index" class="my-1 text-white p-4" :style="{ backgroundColor: creator.colors.bannerTop }">
|
|
||||||
<div class="flex justify-center items-center border-b-2 border-white p-3 mx-2">
|
|
||||||
<div class="text-xl align-center" style="letter-spacing: 4px">{{ item.title }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-3">
|
<div class="p-3">
|
||||||
<p v-if="item.description" class="text-gray-300 text-sm text-justify mt-1 py-1">{{ item.description }}</p>
|
<p v-if="item.description" class="text-gray-300 text-sm text-justify mt-1 py-1">
|
||||||
|
{{ item.description }}
|
||||||
|
</p>
|
||||||
|
|
||||||
<div v-if="item.amount" class="flex flex-row justify-end space-x-2">
|
<div v-if="item.amount" class="flex flex-row justify-end space-x-2">
|
||||||
<div class="text-right text-white">{{ item.amount }}$</div>
|
<div class="text-right text-white">{{ item.amount }}$</div>
|
||||||
<div>|</div>
|
<div>|</div>
|
||||||
<div v-if="item.quantity"> Quantité: {{ item.quantity }}</div>
|
<div v-if="item.quantity"> Quantité: {{ item.quantity }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Navigation Buttons directly below the content -->
|
|
||||||
<div v-if="showNavigationButtons" class="flex justify-center mt-2 py-2">
|
|
||||||
<v-btn variant="text" class="text-white" height="42" @click="scrollUp">
|
|
||||||
<v-icon size="40">mdi-arrow-up-drop-circle-outline</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-btn variant="text" class="text-white" height="42" @click="scrollDown">
|
|
||||||
<v-icon size="40">mdi-arrow-down-drop-circle-outline</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, defineProps } from 'vue';
|
import {ref} from 'vue';
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
creator: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const actualites = ref([
|
const rewards = ref([
|
||||||
{
|
{
|
||||||
title: 'Hoodie',
|
title: 'Hoodie',
|
||||||
description: 'Je suis fier de vous montrer les installations sur lesquelles nous avons travaillé si fort.',
|
description: 'Je suis fier de vous montrer les installations sur lesquelles nous avons travaillé si fort.',
|
||||||
@@ -91,45 +80,5 @@ const actualites = ref([
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const startIndex = ref(0);
|
|
||||||
const cardsPerPage = 3;
|
|
||||||
const scrollPosition = ref(0);
|
|
||||||
const cardHeight = 250;
|
|
||||||
|
|
||||||
const endIndex = computed(() => startIndex.value + cardsPerPage);
|
|
||||||
const visibleCards = computed(() => actualites.value.slice(startIndex.value, endIndex.value));
|
|
||||||
|
|
||||||
// Calculate whether navigation buttons should be shown
|
|
||||||
const showNavigationButtons = computed(() => {
|
|
||||||
const totalHeight = actualites.value.length * cardHeight;
|
|
||||||
const containerHeight = cardsPerPage * cardHeight;
|
|
||||||
return totalHeight > containerHeight; // Only show buttons if content exceeds the container
|
|
||||||
});
|
|
||||||
|
|
||||||
function scrollUp() {
|
|
||||||
if (startIndex.value > 0) {
|
|
||||||
startIndex.value -= 1;
|
|
||||||
scrollPosition.value -= cardHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function scrollDown() {
|
|
||||||
const totalHeight = actualites.value.length * cardHeight;
|
|
||||||
const containerHeight = cardsPerPage * cardHeight;
|
|
||||||
|
|
||||||
if (scrollPosition.value + containerHeight < totalHeight) {
|
|
||||||
startIndex.value += 1;
|
|
||||||
scrollPosition.value += cardHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle scroll wheel event to scroll up or down
|
|
||||||
function handleScroll(event) {
|
|
||||||
event.preventDefault(); // Empêche le défilement de la page
|
|
||||||
if (event.deltaY < 0) {
|
|
||||||
scrollUp(); // Défilement vers le haut
|
|
||||||
} else if (event.deltaY > 0) {
|
|
||||||
scrollDown(); // Défilement vers le bas
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +1,22 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
creator: {type: Object, required: true},
|
const subscriptionStore = useSubscriptionStore()
|
||||||
colorBorder: {required: true},
|
|
||||||
});
|
|
||||||
|
|
||||||
const colorBorder = computed(() => props.colorBorder);
|
const isSubscribe = computed(() => !subscriptionStore.isSubscribeTo(brandingStore.value.id));
|
||||||
|
|
||||||
const subscriptionStore = useSubscriptionStore();
|
|
||||||
|
|
||||||
const isSubscribe = computed(() => !subscriptionStore.isSubscribeTo(props.creator.id));
|
|
||||||
|
|
||||||
function subscribeToCreator() {
|
function subscribeToCreator() {
|
||||||
subscriptionStore.subscribeTo(props.creator.id);
|
subscriptionStore.subscribeTo(brandingStore.value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Référence pour contrôler l'affichage du modal
|
// Référence pour contrôler l'affichage du modal
|
||||||
const showUnsubscribeModal = ref(false);
|
const showUnsubscribeModal = ref(false);
|
||||||
|
|
||||||
function unsubscribeFromCreator() {
|
function unsubscribeFromCreator() {
|
||||||
subscriptionStore.unsubscribeFrom(props.creator.id);
|
subscriptionStore.unsubscribeFrom(brandingStore.value.id);
|
||||||
// Fermer le modal après désabonnement
|
// Fermer le modal après désabonnement
|
||||||
showUnsubscribeModal.value = false;
|
showUnsubscribeModal.value = false;
|
||||||
}
|
}
|
||||||
@@ -33,7 +28,7 @@ function unsubscribeFromCreator() {
|
|||||||
:style="{
|
:style="{
|
||||||
width: '150px',
|
width: '150px',
|
||||||
height: '28px',
|
height: '28px',
|
||||||
backgroundColor: colorBorder,
|
backgroundColor: brandingStore.value.colors.secondary,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
borderRadius: '0 8px 8px 0',
|
borderRadius: '0 8px 8px 0',
|
||||||
padding: '10px 24px',
|
padding: '10px 24px',
|
||||||
@@ -44,7 +39,7 @@ function unsubscribeFromCreator() {
|
|||||||
}"
|
}"
|
||||||
@click="subscribeToCreator"
|
@click="subscribeToCreator"
|
||||||
>
|
>
|
||||||
<div>{{ $t('subscribebutton.subscribe') }}</div>
|
{{ $t('subscribebutton.subscribe') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -53,7 +48,7 @@ function unsubscribeFromCreator() {
|
|||||||
:style="{
|
:style="{
|
||||||
width: '150px',
|
width: '150px',
|
||||||
height: '28px',
|
height: '28px',
|
||||||
backgroundColor: colorBorder,
|
backgroundColor: brandingStore.value.colors.secondary,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
borderRadius: '0 8px 8px 0',
|
borderRadius: '0 8px 8px 0',
|
||||||
padding: '10px 24px',
|
padding: '10px 24px',
|
||||||
@@ -70,7 +65,7 @@ function unsubscribeFromCreator() {
|
|||||||
|
|
||||||
<v-dialog v-model="showUnsubscribeModal" max-width="500">
|
<v-dialog v-model="showUnsubscribeModal" max-width="500">
|
||||||
<v-card class="text-center rounded-xl"
|
<v-card class="text-center rounded-xl"
|
||||||
:style="{ border: `3px solid ${creator.colors.menu}` }">
|
:style="{ border: `3px solid ${brandingStore.value.colors.secondary}` }">
|
||||||
|
|
||||||
<div class="flex items-center justify-between py-4 text-2xl font-bold border-b mb-2">
|
<div class="flex items-center justify-between py-4 text-2xl font-bold border-b mb-2">
|
||||||
<div class="flex-1 text-center">
|
<div class="flex-1 text-center">
|
||||||
@@ -87,9 +82,10 @@ function unsubscribeFromCreator() {
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-btn class="flex-grow-1"
|
<v-btn class="flex-grow-1"
|
||||||
:style="{ borderColor: creator.colors.menu, color: creator.colors.menu }" variant="outlined"
|
:style="{ borderColor: brandingStore.value.colors.secondary, color: brandingStore.value.colors.secondary }"
|
||||||
|
variant="outlined"
|
||||||
@click="showUnsubscribeModal = false">
|
@click="showUnsubscribeModal = false">
|
||||||
<div :style="{ color: creator.colors.menu }">Non</div>
|
<div :style="{ color: brandingStore.value.colors.secondary }">Non</div>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|||||||
@@ -1,28 +1,21 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
|
||||||
import {computed, ref} from "vue";
|
import {computed, ref} from "vue";
|
||||||
|
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
creator: {type: Object, required: true},
|
|
||||||
colorBorder: {required: true},
|
|
||||||
});
|
|
||||||
|
|
||||||
const colorBorder = computed(() => props.colorBorder);
|
|
||||||
|
|
||||||
const subscriptionStore = useSubscriptionStore();
|
const subscriptionStore = useSubscriptionStore();
|
||||||
|
|
||||||
const isSubscribe = computed(() => !subscriptionStore.isSubscribeTo(props.creator.id));
|
const isSubscribe = computed(() => !subscriptionStore.isSubscribeTo(brandingStore.value.id));
|
||||||
|
|
||||||
function subscribeToCreator() {
|
function subscribeToCreator() {
|
||||||
subscriptionStore.subscribeTo(props.creator.id);
|
subscriptionStore.subscribeTo(brandingStore.value.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const showUnsubscribeModal = ref(false);
|
const showUnsubscribeModal = ref(false);
|
||||||
|
|
||||||
function unsubscribeFromCreator() {
|
function unsubscribeFromCreator() {
|
||||||
subscriptionStore.unsubscribeFrom(props.creator.id);
|
subscriptionStore.unsubscribeFrom(brandingStore.value.id);
|
||||||
|
|
||||||
showUnsubscribeModal.value = false;
|
showUnsubscribeModal.value = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -32,7 +25,7 @@ function unsubscribeFromCreator() {
|
|||||||
<v-btn
|
<v-btn
|
||||||
class="mr-4"
|
class="mr-4"
|
||||||
:style="{
|
:style="{
|
||||||
backgroundColor: colorBorder,
|
backgroundColor: brandingStore.value.colors.secondary,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
padding: '0px 24px',
|
padding: '0px 24px',
|
||||||
@@ -51,7 +44,7 @@ function unsubscribeFromCreator() {
|
|||||||
<v-btn
|
<v-btn
|
||||||
class="mr-4"
|
class="mr-4"
|
||||||
:style="{
|
:style="{
|
||||||
backgroundColor: colorBorder,
|
backgroundColor: brandingStore.value.colors.secondary,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
padding: '0px 24px',
|
padding: '0px 24px',
|
||||||
@@ -68,7 +61,7 @@ function unsubscribeFromCreator() {
|
|||||||
|
|
||||||
<v-dialog v-model="showUnsubscribeModal" max-width="500">
|
<v-dialog v-model="showUnsubscribeModal" max-width="500">
|
||||||
<v-card class="text-center rounded-xl"
|
<v-card class="text-center rounded-xl"
|
||||||
:style="{ border: `3px solid ${creator.colors.menu}` }">
|
:style="{ border: `3px solid ${brandingStore.value.colors.primary}` }">
|
||||||
|
|
||||||
<div class="flex items-center justify-between py-4 text-2xl font-bold border-b mb-2">
|
<div class="flex items-center justify-between py-4 text-2xl font-bold border-b mb-2">
|
||||||
<div class="flex-1 text-center">
|
<div class="flex-1 text-center">
|
||||||
@@ -85,9 +78,10 @@ function unsubscribeFromCreator() {
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
<v-btn class="flex-grow-1"
|
<v-btn class="flex-grow-1"
|
||||||
:style="{ borderColor: creator.colors.menu, color: creator.colors.menu }" variant="outlined"
|
:style="{ borderColor: brandingStore.value.colors.primary, color: brandingStore.value.colors.primary }"
|
||||||
|
variant="outlined"
|
||||||
@click="showUnsubscribeModal = false">
|
@click="showUnsubscribeModal = false">
|
||||||
<div :style="{ color: creator.colors.menu }">Non</div>
|
<div :style="{ color: brandingStore.value.colors.primary }">Non</div>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ const subscriptionStore = useSubscriptionStore()
|
|||||||
<RouterLink class="capitalize" :to="`/@${subscription.creatorName}`">
|
<RouterLink class="capitalize" :to="`/@${subscription.creatorName}`">
|
||||||
|
|
||||||
<div class="flex items-center content-center font-sans font-semibold pt-2 ">
|
<div class="flex items-center content-center font-sans font-semibold pt-2 ">
|
||||||
<img :src="subscription.creatorPortraitUrl ? subscription.creatorPortraitUrl: '/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png' "
|
<img
|
||||||
|
:src="subscription.creatorPortraitUrl ? subscription.creatorPortraitUrl: '/images/usersmedia/anonyme/profilepictures/profileAnonymeSquare.png' "
|
||||||
alt="Profile Image"
|
alt="Profile Image"
|
||||||
class="rounded-full mx-2"
|
class="rounded-full mx-2"
|
||||||
width="32px"
|
width="32px"
|
||||||
@@ -26,9 +27,7 @@ const subscriptionStore = useSubscriptionStore()
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<slot>
|
|
||||||
<span>No subscriptions</span>
|
<span>No subscriptions</span>
|
||||||
</slot>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@@ -4,31 +4,21 @@ import BannerActionsSm from "@/views/creators/banner/bannerlower/BannerActionsSm
|
|||||||
import BannerActionsLg from "@/views/creators/banner/bannerlower/BannerActionsLg.vue";
|
import BannerActionsLg from "@/views/creators/banner/bannerlower/BannerActionsLg.vue";
|
||||||
import BannerActionsXl from "@/views/creators/banner/bannerlower/BannerActionsXl.vue";
|
import BannerActionsXl from "@/views/creators/banner/bannerlower/BannerActionsXl.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
creator: { type: Object, required: true }
|
|
||||||
});
|
|
||||||
|
|
||||||
const emits = defineEmits(['content-posted']);
|
|
||||||
|
|
||||||
function addContent(content) {
|
|
||||||
emits('content-posted', content);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<banner-actions-sm class="d-sm-none" :creator="creator" @content-posted="addContent"></banner-actions-sm>
|
<banner-actions-sm class="d-sm-none"
|
||||||
|
></banner-actions-sm>
|
||||||
|
|
||||||
<div class="d-none d-sm-flex d-md-none">
|
<banner-actions-md class="d-none d-sm-flex d-md-none"
|
||||||
<banner-actions-md :creator="creator" @content-posted="addContent"></banner-actions-md>
|
></banner-actions-md>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="d-none d-md-flex d-lg-none">
|
<banner-actions-lg class="d-none d-md-flex d-lg-none"
|
||||||
<banner-actions-lg :creator="creator" @content-posted="addContent"></banner-actions-lg>
|
></banner-actions-lg>
|
||||||
</div>
|
|
||||||
|
<banner-actions-xl class="d-none d-lg-flex"
|
||||||
|
></banner-actions-xl>
|
||||||
|
|
||||||
<div class="d-none d-lg-flex">
|
|
||||||
<banner-actions-xl :creator="creator" @content-posted="addContent"></banner-actions-xl>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative w-full">
|
<div class="relative w-full">
|
||||||
<div ref="mainContainer" class="rounded-b-2xl pt-2 pb-1"
|
<div ref="mainContainer" class="rounded-b-2xl pt-2 pb-1"
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom || '#A30E79', borderBottom: '5px inset' + (creator.colors.menu || '#000') }">
|
:style="{ backgroundColor: brandingStore.value.colors.bannerBottom, borderBottom: '5px inset' + (brandingStore.value.colors.menu || '#000') }">
|
||||||
|
|
||||||
<!-- Logo & User Info -->
|
<!-- Logo & User Info -->
|
||||||
<div class="relative z-20">
|
<div class="relative z-20">
|
||||||
@@ -9,36 +9,21 @@
|
|||||||
<div>
|
<div>
|
||||||
<img
|
<img
|
||||||
class="shadow-2xl rounded-full border-solid border-4 absolute z-20 max-w-[190px] ml-15 -mt-32"
|
class="shadow-2xl rounded-full border-solid border-4 absolute z-20 max-w-[190px] ml-15 -mt-32"
|
||||||
:src="creator.images.logo ? creator.images.logo : '/images/placeholders/logo.png'"
|
:src="brandingStore.value.images.logo ? brandingStore.value.images.logo : '/images/placeholders/logo.png'"
|
||||||
alt="Profile Picture"
|
alt="Profile Picture"
|
||||||
:style="{ borderColor: creator.colors.accent || '#A30E79', height: '190px'}"
|
:style="{ borderColor: brandingStore.value.colors.accent, height: '190px'}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-72 text-white mr-10">
|
|
||||||
<p class="capitalize text-4xl font-bold">{{ creator.name }}</p>
|
|
||||||
<div class="text-2xl text-white flex flex-row align-center">
|
|
||||||
{{ creator.about.title }}
|
|
||||||
<creator-about class="px-2" :creator="creator"></creator-about>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row ml-auto space-x-2.5">
|
<div class="flex flex-row ml-auto space-x-2.5">
|
||||||
<donation-button-banner
|
<donation-button-banner></donation-button-banner>
|
||||||
:color-border="creator.colors.menu"
|
|
||||||
:color-accent="creator.colors.accent"
|
|
||||||
:creator-id="creator.id"
|
|
||||||
:creator-name="creator.name"
|
|
||||||
:creator-logo="creator.images.logo"
|
|
||||||
iconColorClass="text-white">
|
|
||||||
</donation-button-banner>
|
|
||||||
<div class="flex flex-column">
|
<div class="flex flex-column">
|
||||||
<!-- Bouton abonnement affiché seulement si non abonné -->
|
<!-- Bouton abonnement affiché seulement si non abonné -->
|
||||||
<subscribe-button
|
<subscribe-button></subscribe-button>
|
||||||
|
|
||||||
:creator="creator"
|
|
||||||
:color-border="creator.colors.menu">
|
|
||||||
</subscribe-button>
|
|
||||||
<div class="font-bold text-white flex justify-end mr-5 py-1.5">
|
<div class="font-bold text-white flex justify-end mr-5 py-1.5">
|
||||||
{{ creator.subscriberCount }} {{ $t('banner.subscription') }}
|
{{ brandingStore.value.subscriberCount }} {{ $t('banner.subscription') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,36 +33,27 @@
|
|||||||
|
|
||||||
<!-- Conteneur sticky -->
|
<!-- Conteneur sticky -->
|
||||||
<div v-show="isSticky" class=" sticky-header fixed top-14 left-0 right-0 w-full z-20"
|
<div v-show="isSticky" class=" sticky-header fixed top-14 left-0 right-0 w-full z-20"
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom || '#A30E79', borderBottom: '5px inset' + (creator.colors.menu || '#000') }">
|
:style="{ backgroundColor: brandingStore.value.colors.bannerBottom , borderBottom: '5px inset' + (brandingStore.value.colors.menu || '#000') }">
|
||||||
<div class="shadow-3xl flex flex-row items-center py-2 px-2">
|
<div class="shadow-3xl flex flex-row items-center py-2 px-2">
|
||||||
<div>
|
<div>
|
||||||
<img
|
<img
|
||||||
class="max-w-[40px] max-h-[40px] ml-5 rounded-full"
|
class="max-w-[40px] max-h-[40px] ml-5 rounded-full"
|
||||||
:src="creator.images.logo ? creator.images.logo : '/images/placeholders/logo.png'"
|
:src="brandingStore.value.images.logo ? brandingStore.value.images.logo : '/images/placeholders/logo.png'"
|
||||||
alt="Profile Picture"
|
alt="Profile Picture"
|
||||||
:style="{ borderColor: creator.colors.accent || '#A30E79', height: '190px'}"
|
:style="{ borderColor: brandingStore.value.colors.accent, height: '190px'}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-5 text-white">
|
<div class="ml-5 text-white">
|
||||||
<p class="capitalize text-2xl font-bold">{{ creator.name }}</p>
|
<p class="capitalize text-2xl font-bold">{{ brandingStore.value.name }}</p>
|
||||||
|
<p class="capitalize text-xl mt-1">{{ brandingStore.value.title }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-auto flex flex-row space-x-2.5 mr-3 ">
|
<div class="ml-auto flex flex-row space-x-2.5 mr-3 ">
|
||||||
|
|
||||||
<donation-button-banner-slim
|
<donation-button-banner-slim></donation-button-banner-slim>
|
||||||
class=""
|
|
||||||
:color-border="creator.colors.menu"
|
|
||||||
:color-accent="creator.colors.accent"
|
|
||||||
:creator-id="creator.id"
|
|
||||||
:creator-name="creator.name"
|
|
||||||
:creator-logo="creator.images.logo"
|
|
||||||
>
|
|
||||||
</donation-button-banner-slim>
|
|
||||||
|
|
||||||
<!-- Afficher le bouton d'abonnement seulement si l'utilisateur n'est pas abonné -->
|
<!-- Afficher le bouton d'abonnement seulement si l'utilisateur n'est pas abonné -->
|
||||||
<subscribe-button-slim
|
<subscribe-button-slim
|
||||||
v-if="!isSubscribed"
|
v-if="!isSubscribed">
|
||||||
:creator="creator"
|
|
||||||
:color-border="creator.colors.menu">
|
|
||||||
</subscribe-button-slim>
|
</subscribe-button-slim>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -89,21 +65,18 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref, onMounted, computed} from 'vue';
|
import {ref, onMounted, computed} from 'vue';
|
||||||
import { useSubscriptionStore } from "@/stores/subscriptionStore.js";
|
|
||||||
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
||||||
import DonationButtonBanner from "@/views/creators/DonationButtonBanner.vue";
|
import DonationButtonBanner from "@/views/creators/DonationButtonBanner.vue";
|
||||||
import CreatorAbout from "@/views/creators/CreatorAbout.vue";
|
|
||||||
import SubscribeButtonSlim from "@/views/creators/SubscribeButtonSlim.vue";
|
import SubscribeButtonSlim from "@/views/creators/SubscribeButtonSlim.vue";
|
||||||
import DonationButtonBannerSlim from "@/views/creators/DonationButtonBannerSlim.vue";
|
import DonationButtonBannerSlim from "@/views/creators/DonationButtonBannerSlim.vue";
|
||||||
|
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
creator: { type: Object, required: true }
|
const subscriptionStore = useSubscriptionStore()
|
||||||
});
|
|
||||||
|
|
||||||
const subscriptionStore = useSubscriptionStore();
|
|
||||||
|
|
||||||
// Calculer si l'utilisateur est abonné
|
// Calculer si l'utilisateur est abonné
|
||||||
const isSubscribed = computed(() => subscriptionStore.isSubscribeTo(props.creator.id));
|
const isSubscribed = computed(() => subscriptionStore.isSubscribeTo(brandingStore.value.id));
|
||||||
|
|
||||||
const isSticky = ref(false);
|
const isSticky = ref(false);
|
||||||
const mainContainer = ref(null);
|
const mainContainer = ref(null);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div class="rounded-b-2xl"
|
<div class="rounded-b-2xl"
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom || '#A30E79' }">
|
:style="{ backgroundColor: brandingStore.value.colors.bannerBottom }">
|
||||||
<div>
|
<div>
|
||||||
|
|
||||||
<!-- Logo-Name-Followers -->
|
<!-- Logo-Name-Followers -->
|
||||||
@@ -9,37 +9,27 @@
|
|||||||
<div>
|
<div>
|
||||||
<img
|
<img
|
||||||
class="absolute rounded-full border-solid border-2 max-w-[140px] h-auto ml-3 -mt-3"
|
class="absolute rounded-full border-solid border-2 max-w-[140px] h-auto ml-3 -mt-3"
|
||||||
:src="creator.images.logo ? creator.images.logo : '/images/placeholders/logo.png'"
|
:src="brandingStore.value.images.logo ? brandingStore.value.images.logo : '/images/placeholders/logo.png'"
|
||||||
alt="Profile Picture"
|
alt="Profile Picture"
|
||||||
:style="{ borderColor: creator.colors.accent || '#A30E79', height: '150px'}"
|
:style="{ borderColor: brandingStore.value.colors.accent, height: '150px'}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-column text-white cap px-2 mt-1 w-full ml-40">
|
<div class="flex flex-column text-white cap px-2 mt-1 w-full ml-40">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p class="capitalize text-2xl font-bold">{{ creator.name }}</p>
|
<p class="capitalize text-2xl font-bold">{{ brandingStore.value.name }}</p>
|
||||||
<div>{{ creator.subscriberCount }} {{ $t('banner.subscription') }}</div>
|
<p class="capitalize text-xl mt-1">{{ brandingStore.value.title }}</p>
|
||||||
|
<div>{{ brandingStore.value.subscriberCount }} {{ $t('banner.subscription') }}</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="mt-1">{{ creator.about.title }}</div>
|
|
||||||
<creator-about :creator="creator"></creator-about>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-between mt-2">
|
<div class="flex justify-between mt-2">
|
||||||
<subscribe-button :creator="creator"></subscribe-button>
|
<subscribe-button></subscribe-button>
|
||||||
<div class="flex space-x-2">
|
<div class="flex space-x-2">
|
||||||
<publish-content-button :creator="creator"
|
<donation-button iconColorClass="text-white"
|
||||||
@content-posted="addContent"
|
|
||||||
></publish-content-button>
|
|
||||||
<donation-button :color-border="creator.colors.menu"
|
|
||||||
:color-accent="creator.colors.accent"
|
|
||||||
:creator-id="creator.id"
|
|
||||||
:creator-name="creator.name"
|
|
||||||
:creator-logo="creator.images.logo"
|
|
||||||
iconColorClass="text-white"
|
|
||||||
></donation-button>
|
></donation-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,17 +44,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
||||||
import PublishContentButton from "@/views/contents/PublishContentButton.vue";
|
|
||||||
import DonationButton from "@/views/creators/DonationButton.vue";
|
import DonationButton from "@/views/creators/DonationButton.vue";
|
||||||
import CreatorAbout from "@/views/creators/CreatorAbout.vue";
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
creator: {type: Object, required: true}
|
|
||||||
});
|
|
||||||
|
|
||||||
const emits = defineEmits(['content-posted']);
|
|
||||||
|
|
||||||
function addContent(content) {
|
|
||||||
emits('content-posted', content);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,32 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<div
|
<div
|
||||||
:style="{
|
:style="{backgroundColor: brandingStore.value.colors.bannerBottom, borderBottom: `2px solid ${brandingStore.value.colors.accent}`}">
|
||||||
backgroundColor: creator.colors.bannerBottom || '#A30E79',
|
|
||||||
borderBottom: `2px solid ${creator.colors.accent || '#000000'}`
|
|
||||||
}">
|
|
||||||
<div>
|
<div>
|
||||||
<!-- Logo-Name-Followers-->
|
<!-- Logo-Name-Followers-->
|
||||||
<div class="flex flex-row relative z-20">
|
<div class="flex flex-row relative z-20">
|
||||||
<div>
|
|
||||||
<!-- bug space-->
|
|
||||||
<!-- <img-->
|
|
||||||
<!-- -->
|
|
||||||
<!-- class="rounded-full border-solid border-2 -mt-4 max-w-[80px] h-auto ml-2"-->
|
|
||||||
<!-- :src="creator.images.logo ? creator.images.logo : '/images/placeholders/logo.png'"-->
|
|
||||||
<!-- alt="Profile Picture"-->
|
|
||||||
<!-- :style="{ borderColor: creator.colors.accent || '#A30E79', height: '150px'}"-->
|
|
||||||
<!-- />-->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-column text-white capitalize px-2 mt-1">
|
<div class="flex flex-column text-white capitalize px-2 mt-1">
|
||||||
<p class="capitalize text-2xl font-bold">{{ creator.name }}</p>
|
<p class="capitalize text-2xl font-bold">{{ brandingStore.value.name }}</p>
|
||||||
<div>{{ creator.subscriberCount }} {{ $t('banner.subscription')}}</div>
|
<div>{{ brandingStore.value.subscriberCount }} {{ $t('banner.subscription') }}</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex ml-auto text-right text-white text-lg px-3 mt-2">
|
|
||||||
<div class="mt-1">{{ creator.about.title }}</div>
|
|
||||||
<creator-about :creator="creator"></creator-about>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -35,20 +17,11 @@
|
|||||||
<div class="flex flex-row items-center justify-between w-full px-4">
|
<div class="flex flex-row items-center justify-between w-full px-4">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<subscribe-button :creator="creator"></subscribe-button>
|
<subscribe-button></subscribe-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex ml-auto space-x-4">
|
<div class="flex ml-auto space-x-4">
|
||||||
<publish-content-button :creator="creator"
|
<donation-button iconColorClass="text-white"
|
||||||
@content-posted="addContent"
|
|
||||||
></publish-content-button>
|
|
||||||
|
|
||||||
<donation-button :color-border="creator.colors.menu"
|
|
||||||
:color-accent="creator.colors.accent"
|
|
||||||
:creator-id="creator.id"
|
|
||||||
:creator-name="creator.name"
|
|
||||||
:creator-logo="creator.images.logo"
|
|
||||||
iconColorClass="text-white"
|
|
||||||
></donation-button>
|
></donation-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -62,17 +35,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
||||||
import PublishContentButton from "@/views/contents/PublishContentButton.vue";
|
|
||||||
import DonationButton from "@/views/creators/DonationButton.vue";
|
import DonationButton from "@/views/creators/DonationButton.vue";
|
||||||
import CreatorAbout from "@/views/creators/CreatorAbout.vue";
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
const props = defineProps({
|
const brandingStore = useBrandingStore()
|
||||||
creator: {type: Object, required: true}
|
|
||||||
});
|
|
||||||
|
|
||||||
const emits = defineEmits(['content-posted']);
|
|
||||||
|
|
||||||
function addContent(content) {
|
|
||||||
emits('content-posted', content);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
<div class="flex flex-column w-full">
|
<div class="flex flex-column w-full">
|
||||||
|
|
||||||
<div class="relative w-full shadow-xl rounded-2xl">
|
<div class="relative w-full shadow-xl rounded-2xl">
|
||||||
|
|
||||||
<div ref="mainContainer" class="rounded-b-2xl shadow-2xl"
|
<div ref="mainContainer" class="rounded-b-2xl shadow-2xl"
|
||||||
:style="{ backgroundColor: creator.colors.bannerTop || '#A30E79', boxShadow: '0 5px 10px rgba(0, 0, 0, 0.3)' }">
|
:style="{ backgroundColor: brandingStore.value.colors.primary, boxShadow: '0 5px 10px rgba(0, 0, 0, 0.3)' }">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
@@ -12,19 +13,17 @@
|
|||||||
<div class="absolute">
|
<div class="absolute">
|
||||||
<div>
|
<div>
|
||||||
<img
|
<img
|
||||||
class="shadow-2xl rounded-full border-solid border-2 absolute z-20 max-w-[190px] ml-10 -mt-10"
|
class="shadow-2xl rounded-full border-solid border-102 absolute z-20 max-w-[190px] ml-10 -mt-10"
|
||||||
:src="creator.images.logo ? creator.images.logo : '/images/placeholders/logo.png'"
|
:src="brandingStore.value.images.logo ? brandingStore.value.images.logo : '/images/placeholders/logo.png'"
|
||||||
alt="Profile Picture"
|
alt="Profile Picture"
|
||||||
:style="{ borderColor: creator.colors.accent || '#A30E79', height: '190px'}"
|
:style="{ borderColor: brandingStore.value.colors.secondary, height: '190px'}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-64 text-white w-25 min-w-60">
|
<div class="ml-64 text-white w-25 min-w-60">
|
||||||
<p class="capitalize text-2xl mt-1">{{ creator.name }}</p>
|
<p class="capitalize text-2xl mt-1">{{ brandingStore.value.name }}</p>
|
||||||
<div class="text-md py-1">
|
<p class="capitalize text-xl mt-1">{{ brandingStore.value.title }}</p>
|
||||||
{{ creator.about.title }}
|
|
||||||
</div>
|
|
||||||
<div class="text-xs">
|
<div class="text-xs">
|
||||||
105 Followers - {{ creator.subscriberCount }} {{ $t('banner.subscription') }}
|
105 Followers - {{ brandingStore.value.subscriberCount }} {{ $t('banner.subscription') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,34 +50,30 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- Follow and Subscribe Buttons -->
|
<!-- Follow and Subscribe Buttons -->
|
||||||
<div class="flex flex-row space-x-1 justify-center mt-3 mb-2">
|
<div class="flex flex-row space-x-1 justify-center mt-3 mb-2">
|
||||||
<follow-button
|
<follow-button></follow-button>
|
||||||
:creator="creator"
|
<subscribe-button></subscribe-button>
|
||||||
:color-border="creator.colors.menu">
|
|
||||||
</follow-button>
|
|
||||||
<subscribe-button
|
|
||||||
:creator="creator"
|
|
||||||
:color-border="creator.colors.menu">
|
|
||||||
</subscribe-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="absolute bottom-6 right-24 z-30 shadow-2xl rounded-md text-white"
|
<div class="absolute bottom-6 right-24 z-30 shadow-2xl rounded-md text-white"
|
||||||
:style="{ backgroundColor: creator.colors.bannerTop}">
|
:style="{ backgroundColor: brandingStore.value.colors.background}">
|
||||||
|
|
||||||
<div class="w-96 h-28 flex flex-col">
|
<div class="w-96 h-28 flex flex-col">
|
||||||
<!-- Section 3 et 4 - Prend 2/3 de la hauteur -->
|
<!-- Section 3 et 4 - Prend 2/3 de la hauteur -->
|
||||||
<div class="flex flex-row flex-grow-[2] min-h-20">
|
<div class="flex flex-row flex-grow-[2] min-h-20">
|
||||||
<div class="rounded-tl-md w-1/2 flex items-center justify-center"
|
<div class="rounded-tl-md w-1/2 flex items-center justify-center"
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom, opacity: 0.20 }">
|
:style="{ backgroundColor: brandingStore.value.colors.primary, opacity: 0.20 }">
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-tr-md w-1/2 bg-cyan-100 flex items-center justify-center text-xl"
|
<div class="rounded-tr-md w-1/2 bg-cyan-100 flex items-center justify-center text-xl"
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom}">
|
:style="{ backgroundColor: brandingStore.value.colors.secondary}">
|
||||||
<div class="absolute left-1">
|
<div class="absolute left-1">
|
||||||
<div class="flex flex-row items-center justify-center space-x-5">
|
<div class="flex flex-row items-center justify-center space-x-5">
|
||||||
<div class="flex flex-row items-center">
|
<div class="flex flex-row items-center">
|
||||||
<div style="display: flex; align-items: center;">
|
<div style="display: flex; align-items: center;">
|
||||||
<textarea class="text-3xl" rows="1" cols="6" style="border: none; resize: none; text-align: right; outline: none;" placeholder="0"></textarea>
|
<textarea class="text-3xl" rows="1" cols="6"
|
||||||
|
style="border: none; resize: none; text-align: right; outline: none;"
|
||||||
|
placeholder="0"></textarea>
|
||||||
<div class="px-1">$</div>
|
<div class="px-1">$</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -86,11 +81,11 @@
|
|||||||
|
|
||||||
<div class="flex flex-col items-center space-y-2">
|
<div class="flex flex-col items-center space-y-2">
|
||||||
<v-btn
|
<v-btn
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom, fontSize: '20px', height: '30px', width: '30px', padding: '0', minWidth: '25px', minHeight: '25px' }"
|
:style="{ backgroundColor: brandingStore.value.colors.secondary, fontSize: '20px', height: '30px', width: '30px', padding: '0', minWidth: '25px', minHeight: '25px' }"
|
||||||
variant="tonal">+
|
variant="tonal">+
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom, fontSize: '20px', height: '30px', width: '30px', padding: '0', minWidth: '25px', minHeight: '25px' }"
|
:style="{ backgroundColor: brandingStore.value.colors.secondary, fontSize: '20px', height: '30px', width: '30px', padding: '0', minWidth: '25px', minHeight: '25px' }"
|
||||||
variant="tonal">-
|
variant="tonal">-
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
@@ -107,15 +102,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-grow bg-gray-300 flex items-center justify-center rounded-b-md"
|
<div class="flex-grow bg-gray-300 flex items-center justify-center rounded-b-md"
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom,opacity: 0.80 }">
|
:style="{ backgroundColor: brandingStore.value.colors.secondary, opacity: 0.80 }">
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
|
|
||||||
rows="1"
|
rows="1"
|
||||||
placeholder="Message facultatif"
|
placeholder="Message facultatif"
|
||||||
class="w-full p-2 border border-gray-300 rounded-b-md resize-none"
|
class="w-full p-2 border border-gray-300 rounded-b-md resize-none"
|
||||||
style="max-height: 300px; overflow-y: hidden; outline: none;"
|
style="max-height: 300px; overflow-y: hidden; outline: none;"
|
||||||
oninput="this.style.height = ''; this.style.height = Math.min(this.scrollHeight, 300) + 'px'"></textarea>
|
oninput="this.style.height = ''; this.style.height = Math.min(this.scrollHeight, 300) + 'px'"
|
||||||
|
></textarea>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -124,12 +119,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="rounded-b-2xl min-h-10 px-36 flex flex-col items-center justify-center"
|
<div class="rounded-b-2xl h-12 px-36 flex flex-col items-center justify-center"
|
||||||
:style="{ backgroundColor: creator.colors.bannerBottom, boxShadow: '0 5px 20px rgba(0, 0, 0, 0.3)' }">
|
:style="{ backgroundColor: brandingStore.value.colors.secondary, boxShadow: '0 5px 20px rgba(0, 0, 0, 0.3)' }">
|
||||||
<div class="flex justify-evenly w-full">
|
<div class="flex justify-evenly w-full">
|
||||||
<v-btn variant="text" class="text-white">Présentation</v-btn>
|
<RouterLink class="nav-button"
|
||||||
<v-btn variant="text" class="text-white">Actualité</v-btn>
|
:to="`/@${brandingStore.value.name}`">
|
||||||
<v-btn variant="text" class="text-white">Exclusivité</v-btn>
|
Présentation
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink class="nav-button text-white hover:bg-gray-700"
|
||||||
|
:to="`/@${brandingStore.value.name}/news`">
|
||||||
|
Actualité
|
||||||
|
</RouterLink>
|
||||||
|
<RouterLink class="nav-button text-white hover:bg-gray-700"
|
||||||
|
:to="`/@${brandingStore.value.name}/content`">
|
||||||
|
Exclusivité
|
||||||
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -137,82 +141,81 @@
|
|||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<style scoped>
|
||||||
import {ref, onMounted, computed} from 'vue';
|
.nav-button {
|
||||||
import {useSubscriptionStore} from "@/stores/subscriptionStore.js";
|
@apply rounded flex justify-center font-sans py-1 text-white tracking-widest p-4
|
||||||
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
}
|
||||||
import DonationButtonBanner from "@/views/creators/DonationButtonBanner.vue";
|
|
||||||
import CreatorAbout from "@/views/creators/CreatorAbout.vue";
|
|
||||||
import SubscribeButtonSlim from "@/views/creators/SubscribeButtonSlim.vue";
|
|
||||||
import DonationButtonBannerSlim from "@/views/creators/DonationButtonBannerSlim.vue";
|
|
||||||
import FollowButton from "@/views/creators/FollowButton.vue";
|
|
||||||
|
|
||||||
|
.nav-button:hover {
|
||||||
|
@apply bg-purple-800;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {ref, onMounted} from 'vue';
|
||||||
|
import SubscribeButton from "@/views/creators/SubscribeButton.vue";
|
||||||
|
import FollowButton from "@/views/creators/FollowButton.vue";
|
||||||
|
import {useBrandingStore} from "@/stores/brandingStore.js";
|
||||||
|
|
||||||
|
const brandingStore = useBrandingStore()
|
||||||
|
|
||||||
function GetSocialsUrls() {
|
function GetSocialsUrls() {
|
||||||
|
|
||||||
const socials = [];
|
const socials = [];
|
||||||
|
|
||||||
if (props.creator.socials.facebookUrl !== null) {
|
if (brandingStore.value.socials.facebookUrl !== null) {
|
||||||
socials.push({
|
socials.push({
|
||||||
icon: "mdi-facebook",
|
icon: "mdi-facebook",
|
||||||
url: props.creator.socials.facebookUrl
|
url: brandingStore.value.socials.facebookUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (props.creator.socials.instagramUrl !== null) {
|
if (brandingStore.value.socials.instagramUrl !== null) {
|
||||||
socials.push({
|
socials.push({
|
||||||
icon: "mdi-instagram",
|
icon: "mdi-instagram",
|
||||||
url: props.creator.socials.instagramUrl
|
url: brandingStore.value.socials.instagramUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (props.creator.socials.xUrl !== null) {
|
if (brandingStore.value.socials.xUrl !== null) {
|
||||||
socials.push({
|
socials.push({
|
||||||
icon: "mdi-twitter",
|
icon: "mdi-twitter",
|
||||||
url: props.creator.socials.xUrl
|
url: brandingStore.value.socials.xUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (props.creator.socials.linkedInUrl !== null) {
|
if (brandingStore.value.socials.linkedInUrl !== null) {
|
||||||
socials.push({
|
socials.push({
|
||||||
icon: 'mdi-linkedin',
|
icon: 'mdi-linkedin',
|
||||||
url: props.creator.socials.linkedInUrl
|
url: brandingStore.value.socials.linkedInUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (props.creator.socials.tikTokUrl !== null) {
|
if (brandingStore.value.socials.tikTokUrl !== null) {
|
||||||
socials.push({
|
socials.push({
|
||||||
icon: '/images/socials/tiktok-white.png',
|
icon: '/images/socials/tiktok-white.png',
|
||||||
url: props.creator.socials.tikTokUrl
|
url: brandingStore.value.socials.tikTokUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (props.creator.socials.youtubeUrl !== null) {
|
if (brandingStore.value.socials.youtubeUrl !== null) {
|
||||||
socials.push({
|
socials.push({
|
||||||
icon: 'mdi-youtube',
|
icon: 'mdi-youtube',
|
||||||
url: props.creator.socials.youtubeUrl
|
url: brandingStore.value.socials.youtubeUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (props.creator.socials.redditUrl !== null) {
|
if (brandingStore.value.socials.redditUrl !== null) {
|
||||||
socials.push({
|
socials.push({
|
||||||
icon: 'mdi-reddit',
|
icon: 'mdi-reddit',
|
||||||
url: props.creator.socials.redditUrl
|
url: brandingStore.value.socials.redditUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (props.creator.socials.websiteUrl !== null) {
|
if (brandingStore.value.socials.websiteUrl !== null) {
|
||||||
socials.push({
|
socials.push({
|
||||||
icon: 'mdi-web',
|
icon: 'mdi-web',
|
||||||
url: props.creator.socials.websiteUrl
|
url: brandingStore.value.socials.websiteUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return socials;
|
return socials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
creator: {type: Object, required: true}
|
|
||||||
});
|
|
||||||
|
|
||||||
const subscriptionStore = useSubscriptionStore();
|
|
||||||
|
|
||||||
// Calculer si l'utilisateur est abonné
|
// Calculer si l'utilisateur est abonné
|
||||||
const isSubscribed = computed(() => subscriptionStore.isSubscribeTo(props.creator.id));
|
|
||||||
const isSticky = ref(false);
|
const isSticky = ref(false);
|
||||||
const mainContainer = ref(null);
|
const mainContainer = ref(null);
|
||||||
|
|
||||||
|
|||||||
@@ -128,14 +128,8 @@
|
|||||||
d’Hutopy votre utopie. Merci de faire partie de notre histoire.
|
d’Hutopy votre utopie. Merci de faire partie de notre histoire.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<selected-footer></selected-footer>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import '@/cssstyle/tosstyle.css';
|
@import '@/cssstyle/tosstyle.css';
|
||||||
</style>
|
</style>
|
||||||
<script setup lang="ts">
|
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
</script>
|
|
||||||
@@ -123,14 +123,8 @@
|
|||||||
Si vous avez des questions sur cette politique de contenu ou sur la manière dont nous l'appliquons, veuillez contacter notre équipe d'assistance à <a href="mailto:support@hutopy.com">support@hutopy.com</a>.
|
Si vous avez des questions sur cette politique de contenu ou sur la manière dont nous l'appliquons, veuillez contacter notre équipe d'assistance à <a href="mailto:support@hutopy.com">support@hutopy.com</a>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<selected-footer></selected-footer>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import '@/cssstyle/tosstyle.css';
|
@import '@/cssstyle/tosstyle.css';
|
||||||
</style>
|
</style>
|
||||||
<script setup lang="ts">
|
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
</script>
|
|
||||||
@@ -38,14 +38,8 @@
|
|||||||
<li class="text-justify p-tos">Continuez à Apprendre : Utilisez le Centre de Ressources Éducatives d’Hutopy pour améliorer vos compétences et rester à jour sur les tendances du secteur. (À venir)</li>
|
<li class="text-justify p-tos">Continuez à Apprendre : Utilisez le Centre de Ressources Éducatives d’Hutopy pour améliorer vos compétences et rester à jour sur les tendances du secteur. (À venir)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<selected-footer></selected-footer>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import '@/cssstyle/tosstyle.css';
|
@import '@/cssstyle/tosstyle.css';
|
||||||
</style>
|
</style>
|
||||||
<script setup lang="ts">
|
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
</script>
|
|
||||||
@@ -80,8 +80,6 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<selected-footer></selected-footer>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -91,6 +89,3 @@
|
|||||||
@apply m-2 text-red-500 my-4;
|
@apply m-2 text-red-500 my-4;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script setup lang="ts">
|
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
</script>
|
|
||||||
@@ -34,14 +34,8 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<selected-footer></selected-footer>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import '@/cssstyle/tosstyle.css';
|
@import '@/cssstyle/tosstyle.css';
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -21,14 +21,9 @@
|
|||||||
Hutopy est plus qu'une plateforme ; c'est une communauté où la transformation de la passion en profit devient réalité, grâce au soutien indéfectible d'une équipe dévouée à enrichir votre parcours. Nous vous invitons à nous rejoindre pour explorer ensemble les avenues de succès, tout en vous garantissant une part conséquente de vos revenus. Embarquez dans une aventure où votre présence en ligne ne connaît pas de limites, soutenue par Hutopy, votre allié dans la quête du succès.
|
Hutopy est plus qu'une plateforme ; c'est une communauté où la transformation de la passion en profit devient réalité, grâce au soutien indéfectible d'une équipe dévouée à enrichir votre parcours. Nous vous invitons à nous rejoindre pour explorer ensemble les avenues de succès, tout en vous garantissant une part conséquente de vos revenus. Embarquez dans une aventure où votre présence en ligne ne connaît pas de limites, soutenue par Hutopy, votre allié dans la quête du succès.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<selected-footer></selected-footer>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import '@/cssstyle/tosstyle.css';
|
@import '@/cssstyle/tosstyle.css';
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
</script>
|
|
||||||
|
|||||||
@@ -63,13 +63,8 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<selected-footer></selected-footer>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import '@/cssstyle/tosstyle.css';
|
@import '@/cssstyle/tosstyle.css';
|
||||||
</style>
|
</style>
|
||||||
<script setup lang="ts">
|
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
</script>
|
|
||||||
@@ -1,9 +1,85 @@
|
|||||||
<template>
|
<script setup>
|
||||||
|
import XIcon from '@/assets/icons/x.svg'
|
||||||
|
import FacebookIcon from '@/assets/icons/facebook.svg'
|
||||||
|
import InstagramIcon from '@/assets/icons/instagram.svg'
|
||||||
|
</script>
|
||||||
|
|
||||||
<footer>
|
<template>
|
||||||
<div class="p-4 text-center font-sans">
|
|
||||||
|
<footer class="py-8 flex flex-col gap-8">
|
||||||
|
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<router-link to="/">
|
||||||
|
<img src="/images/hutopymedia/banners/hutopy.png" alt="hutopy"
|
||||||
|
width="300px"
|
||||||
|
height="64px">
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-row justify-center gap-10">
|
||||||
|
<a href="https://www.facebook.com/profile.php?id=61556819217561">
|
||||||
|
<facebook-icon class="icon"></facebook-icon>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="https://www.instagram.com/hutopy.inc/">
|
||||||
|
<instagram-icon class="icon"></instagram-icon>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="https://x.com/Hutopyinc/">
|
||||||
|
<x-icon class="icon"></x-icon>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-row flex-wrap justify-center gap-4">
|
||||||
|
<router-link to="/helpandcontact">
|
||||||
|
Aide & Contact
|
||||||
|
</router-link>
|
||||||
|
<router-link to="/faq">
|
||||||
|
FAQ
|
||||||
|
</router-link>
|
||||||
|
<router-link to="/guideforcreators">
|
||||||
|
Guide pour les créateurs
|
||||||
|
</router-link>
|
||||||
|
<router-link to="/termsandconditions">
|
||||||
|
Termes et Conditions
|
||||||
|
</router-link>
|
||||||
|
<router-link to="/contentpolicy">
|
||||||
|
Politique de Contenu
|
||||||
|
</router-link>
|
||||||
|
<router-link to="/about">
|
||||||
|
À Propos
|
||||||
|
</router-link>
|
||||||
|
<router-link to="/pricing">
|
||||||
|
Frais
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-center base-text">
|
||||||
Hutopy ©{{ new Date().getFullYear() }} - {{ $t('footer.allRightsReserved') }}
|
Hutopy ©{{ new Date().getFullYear() }} - {{ $t('footer.allRightsReserved') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
fill: #6a0065;
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-text {
|
||||||
|
@apply text-gray-600 tracking-widest font-sans text-sm uppercase
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
@apply base-text
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
@apply text-gray-400
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -97,10 +97,10 @@
|
|||||||
<template v-slot:activator="{ props }">
|
<template v-slot:activator="{ props }">
|
||||||
<div v-bind="props" class="flex align-center font-sans py-1 px-2 rounded-lg hover:bg-gray-100">
|
<div v-bind="props" class="flex align-center font-sans py-1 px-2 rounded-lg hover:bg-gray-100">
|
||||||
<span class="max-w-xs hidden md:block capitalize">
|
<span class="max-w-xs hidden md:block capitalize">
|
||||||
{{ userStore.alias }}
|
{{ userProfileStore.alias }}
|
||||||
</span>
|
</span>
|
||||||
<img
|
<img
|
||||||
:src="userStore.portraitUrl"
|
:src="userProfileStore.portraitUrl"
|
||||||
alt="Profile Image"
|
alt="Profile Image"
|
||||||
class="ml-2 rounded-full"
|
class="ml-2 rounded-full"
|
||||||
width="32"
|
width="32"
|
||||||
@@ -119,13 +119,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<v-list-item v-if="userStore.creator && Object.keys(userStore.creator).length > 0" class="nav-button">
|
<v-list-item v-if="creatorProfileStore.value && Object.keys(creatorProfileStore.value).length > 0" class="nav-button">
|
||||||
<router-link :to="`/@${userStore.creator.name}`">
|
<router-link :to="`/@${creatorProfileStore.value.name}`">
|
||||||
<v-btn class="w-100" variant="plain">@{{ userStore.creator.name }}</v-btn>
|
<v-btn class="w-100" variant="plain">@{{ creatorProfileStore.value.name }}</v-btn>
|
||||||
</router-link>
|
</router-link>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
|
|
||||||
<v-list-item v-if="!userStore.hasCreator" class="nav-button">
|
<v-list-item v-if="!creatorProfileStore.hasCreator" class="nav-button">
|
||||||
<router-link to="/profile?target=CreatorPage">
|
<router-link to="/profile?target=CreatorPage">
|
||||||
<v-btn class="w-100" variant="plain">Activer votre page</v-btn>
|
<v-btn class="w-100" variant="plain">Activer votre page</v-btn>
|
||||||
</router-link>
|
</router-link>
|
||||||
@@ -158,12 +158,16 @@
|
|||||||
import { ref, onBeforeUnmount, onBeforeMount, watch } from "vue";
|
import { ref, onBeforeUnmount, onBeforeMount, watch } from "vue";
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useSideBarStore } from '@/stores/sideBarStore.js';
|
import { useSideBarStore } from '@/stores/sideBarStore.js';
|
||||||
import { useUserStore } from "@/stores/userStore.js";
|
|
||||||
import { useAuthStore } from "@/stores/authStore.js";
|
import { useAuthStore } from "@/stores/authStore.js";
|
||||||
import { useDisplay } from 'vuetify';
|
import { useDisplay } from 'vuetify';
|
||||||
|
import {useUserProfileStore} from "@/stores/userProfileStore.js";
|
||||||
|
import {useCreatorProfileStore} from "@/stores/creatorProfileStore.js";
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const userStore = useUserStore();
|
const userProfileStore = useUserProfileStore();
|
||||||
|
const creatorProfileStore = useCreatorProfileStore();
|
||||||
|
|
||||||
const sideBarStore = useSideBarStore();
|
const sideBarStore = useSideBarStore();
|
||||||
const { smAndDown } = useDisplay();
|
const { smAndDown } = useDisplay();
|
||||||
|
|
||||||
|
|||||||
@@ -8,34 +8,44 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mx-auto flex justify-center pt-10 max-w-[980px]">
|
<div class="mx-auto flex justify-center pt-10 max-w-[980px]">
|
||||||
<img src="/images/hutopymedia/homepage/bannierehomepage.png" alt="Create CallToAction" class="max-w-full block rounded-none md:rounded-2xl">
|
<img src="/images/hutopymedia/homepage/bannierehomepage.png" alt="Create CallToAction"
|
||||||
|
class="max-w-full block rounded-none md:rounded-2xl">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="mx-auto flex flex-col md:flex-row justify-center max-w-[1000px] space-y-2 md:space-x-4 md:space-y-0 py-5">
|
<div
|
||||||
|
class="mx-auto flex flex-col md:flex-row justify-center max-w-[1000px] space-y-2 md:space-x-4 md:space-y-0 py-5">
|
||||||
<div class="relative group w-full max-w-[250px] md:max-w-[306px] rounded-2xl overflow-hidden mx-auto">
|
<div class="relative group w-full max-w-[250px] md:max-w-[306px] rounded-2xl overflow-hidden mx-auto">
|
||||||
<img src="/images/hutopymedia/homepage/creer.png" alt="Create CallToAction" class="w-full rounded-2xl">
|
<img src="/images/hutopymedia/homepage/creer.png" alt="Create CallToAction" class="w-full rounded-2xl">
|
||||||
<div class="absolute inset-0 bg-fuchsia-600 bg-opacity-0 group-hover:bg-opacity-80 flex items-center justify-center transition duration-300">
|
<div
|
||||||
|
class="absolute inset-0 bg-fuchsia-600 bg-opacity-0 group-hover:bg-opacity-80 flex items-center justify-center transition duration-300">
|
||||||
<p class="text-white text-lg opacity-0 group-hover:opacity-100 transition duration-300 m-3 text-justify">
|
<p class="text-white text-lg opacity-0 group-hover:opacity-100 transition duration-300 m-3 text-justify">
|
||||||
Libérez votre créativité sur Hutopy, où chaque idée trouve sa place et chaque créateur détient la clé d'un monde rempli de possibilités infinies. Rejoignez-nous et transformez votre passion en réalité.
|
Libérez votre créativité sur Hutopy, où chaque idée trouve sa place et chaque créateur détient la clé d'un
|
||||||
|
monde rempli de possibilités infinies. Rejoignez-nous et transformez votre passion en réalité.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative group w-full max-w-[250px] md:max-w-[306px] rounded-2xl overflow-hidden mx-auto">
|
<div class="relative group w-full max-w-[250px] md:max-w-[306px] rounded-2xl overflow-hidden mx-auto">
|
||||||
<img src="/images/hutopymedia/homepage/partager.png" alt="Share CallToAction" class="w-full rounded-2xl">
|
<img src="/images/hutopymedia/homepage/partager.png" alt="Share CallToAction" class="w-full rounded-2xl">
|
||||||
<div class="absolute inset-0 bg-fuchsia-600 bg-opacity-0 group-hover:bg-opacity-80 flex items-center justify-center transition duration-300">
|
<div
|
||||||
|
class="absolute inset-0 bg-fuchsia-600 bg-opacity-0 group-hover:bg-opacity-80 flex items-center justify-center transition duration-300">
|
||||||
<p class="text-white text-lg opacity-0 group-hover:opacity-100 transition duration-300 m-3 text-justify">
|
<p class="text-white text-lg opacity-0 group-hover:opacity-100 transition duration-300 m-3 text-justify">
|
||||||
Plongez dans l'univers Hutopy et découvrez un espace où profiter rime avec s'enrichir. Savourez des contenus uniques, des interactions authentiques et une expérience personnalisée conçue pour éveiller vos sens et enrichir votre quotidien.
|
Plongez dans l'univers Hutopy et découvrez un espace où profiter rime avec s'enrichir. Savourez des contenus
|
||||||
|
uniques, des interactions authentiques et une expérience personnalisée conçue pour éveiller vos sens et
|
||||||
|
enrichir votre quotidien.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="relative group w-full max-w-[250px] md:max-w-[306px] rounded-2xl overflow-hidden mx-auto">
|
<div class="relative group w-full max-w-[250px] md:max-w-[306px] rounded-2xl overflow-hidden mx-auto">
|
||||||
<img src="/images/hutopymedia/homepage/inspirer.png" alt="Inspire CallToAction" class="w-full rounded-2xl">
|
<img src="/images/hutopymedia/homepage/inspirer.png" alt="Inspire CallToAction" class="w-full rounded-2xl">
|
||||||
<div class="absolute inset-0 bg-fuchsia-600 bg-opacity-0 group-hover:bg-opacity-80 flex items-center justify-center transition duration-300">
|
<div
|
||||||
|
class="absolute inset-0 bg-fuchsia-600 bg-opacity-0 group-hover:bg-opacity-80 flex items-center justify-center transition duration-300">
|
||||||
<p class="text-white text-lg opacity-0 group-hover:opacity-100 transition duration-300 m-3 text-justify">
|
<p class="text-white text-lg opacity-0 group-hover:opacity-100 transition duration-300 m-3 text-justify">
|
||||||
Devenez une source d'inspiration sur Hutopy, en partageant votre vision, votre talent et vos histoires. Influencez positivement la communauté, éveillez la curiosité et inspirez les autres à poursuivre leurs rêves dans un cercle vertueux de créativité et d'inspiration.
|
Devenez une source d'inspiration sur Hutopy, en partageant votre vision, votre talent et vos histoires.
|
||||||
|
Influencez positivement la communauté, éveillez la curiosité et inspirez les autres à poursuivre leurs rêves
|
||||||
|
dans un cercle vertueux de créativité et d'inspiration.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -84,17 +94,20 @@
|
|||||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<div class="flex justify-center items-center">
|
<div class="flex justify-center items-center">
|
||||||
<RouterLink to="/@Hutopy">
|
<RouterLink to="/@Hutopy">
|
||||||
<img src="/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile02.png" alt="Profile Image" class="rounded-2xl shadow-lg">
|
<img src="/images/usersmedia/HutopyProfile/profilepictures/profileHutopyProfile02.png" alt="Profile Image"
|
||||||
|
class="rounded-2xl shadow-lg">
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center items-center">
|
<div class="flex justify-center items-center">
|
||||||
<RouterLink to="/@guillaumem">
|
<RouterLink to="/@guillaumem">
|
||||||
<img src="/images/usersmedia/guillaumeMousseau/profilepictures/profileGuillaumeMousseau01.jpg" alt="Profile Image" class="rounded-2xl shadow-lg">
|
<img src="/images/usersmedia/guillaumeMousseau/profilepictures/profileGuillaumeMousseau01.jpg"
|
||||||
|
alt="Profile Image" class="rounded-2xl shadow-lg">
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center items-center">
|
<div class="flex justify-center items-center">
|
||||||
<RouterLink to="/@chloebeaugrand">
|
<RouterLink to="/@chloebeaugrand">
|
||||||
<img src="/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand02.png" alt="Profile Image" class="rounded-2xl shadow-lg">
|
<img src="/images/usersmedia/chloebeaugrand/profilepictures/profileChloeBeaugrand02.png"
|
||||||
|
alt="Profile Image" class="rounded-2xl shadow-lg">
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -111,17 +124,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<selected-footer></selected-footer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
.overlay p {
|
.overlay p {
|
||||||
|
|||||||
@@ -16,11 +16,19 @@
|
|||||||
Utilisateur
|
Utilisateur
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<div v-if="showEmailForm" class="w-full mt-2">
|
<div v-if="showEmailForm" class="w-full mt-2">
|
||||||
<v-text-field v-model="email" label="Courriel" variant="outlined" dense prepend-inner-icon="mdi-email" color="transparent" class="text-black"></v-text-field>
|
<v-text-field v-model="email" label="Courriel" variant="outlined" dense prepend-inner-icon="mdi-email"
|
||||||
<v-text-field v-model="password" label="Mot de passe" :type="showPassword ? 'text' : 'password'" variant="outlined" dense prepend-inner-icon="mdi-lock" append-inner-icon="mdi-eye" @click:append-inner="showPassword = !showPassword" color="transparent" class="text-black"></v-text-field>
|
color="transparent" class="text-black"></v-text-field>
|
||||||
<v-btn class="w-full text-center text-white" :style="{ backgroundColor: '#A30E79' }" @click="login">Connecter</v-btn>
|
<v-text-field v-model="password" label="Mot de passe" :type="showPassword ? 'text' : 'password'"
|
||||||
<p class="mt-4 text-sm text-center">Si vous n'avez pas de compte, <a href="/register" class="text-blue-500">cliquez ici</a> pour en créer un.</p>
|
variant="outlined" dense prepend-inner-icon="mdi-lock" append-inner-icon="mdi-eye"
|
||||||
<div v-if="errorSnackBar" class="mb-4 text-red-600">Nom d'utilisateur ou mot de passe invalide. <button class="text-red-600 ml-4" @click="errorSnackBar = false">Fermer</button></div>
|
@click:append-inner="showPassword = !showPassword" color="transparent"
|
||||||
|
class="text-black"></v-text-field>
|
||||||
|
<v-btn class="w-full text-center text-white" :style="{ backgroundColor: '#A30E79' }" @click="login">Connecter
|
||||||
|
</v-btn>
|
||||||
|
<p class="mt-4 text-sm text-center">Si vous n'avez pas de compte, <a href="/register" class="text-blue-500">cliquez
|
||||||
|
ici</a> pour en créer un.</p>
|
||||||
|
<div v-if="errorSnackBar" class="mb-4 text-red-600">Nom d'utilisateur ou mot de passe invalide.
|
||||||
|
<button class="text-red-600 ml-4" @click="errorSnackBar = false">Fermer</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,7 +48,6 @@ const password = ref("");
|
|||||||
const errorSnackBar = ref(false);
|
const errorSnackBar = ref(false);
|
||||||
const showEmailForm = ref(false);
|
const showEmailForm = ref(false);
|
||||||
const showPassword = ref(false);
|
const showPassword = ref(false);
|
||||||
const googleCallback = ref('');
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
onSuccess: {
|
onSuccess: {
|
||||||
@@ -53,9 +60,18 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function googleCallback(token) {
|
||||||
|
const response = await authStore.loginWithGoogle(JSON.stringify(token));
|
||||||
|
handleResponse(response)
|
||||||
|
}
|
||||||
|
|
||||||
async function login() {
|
async function login() {
|
||||||
const result = await authStore.login(email.value, password.value);
|
const response = await authStore.login(email.value, password.value);
|
||||||
if (result === true) {
|
handleResponse(response)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleResponse(response) {
|
||||||
|
if (response === true) {
|
||||||
props.onSuccess();
|
props.onSuccess();
|
||||||
} else {
|
} else {
|
||||||
if (props.onFailure) {
|
if (props.onFailure) {
|
||||||
|
|||||||
@@ -10,14 +10,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<selected-footer></selected-footer>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import SelectedFooter from "@/views/main/SelectedFooter.vue";
|
|
||||||
import RegisterForm from "@/views/main/RegisterForm.vue";
|
import RegisterForm from "@/views/main/RegisterForm.vue";
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="flex justify-center items-center max-w-[300px] pt-28 mx-auto">
|
|
||||||
<router-link to="/">
|
|
||||||
<img src="/images/hutopymedia/banners/hutopy.png" alt="hutopy">
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-row justify-center space-x-10 py-10">
|
|
||||||
<a href="https://www.facebook.com/profile.php?id=61556819217561">
|
|
||||||
<v-icon size="40px" class="text-fuchsia-900">mdi-facebook</v-icon>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://www.instagram.com/hutopy.inc/">
|
|
||||||
<v-icon size="40px" class="text-fuchsia-900">mdi-instagram</v-icon>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://x.com/Hutopyinc/">
|
|
||||||
<img src="/images/hutopymedia/icons/x.svg" width="34px" height="34px" class="mt-1 filter-fushia ">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-row flex-wrap justify-center space-x-2 py-2 pb-6">
|
|
||||||
<router-link to="/helpandcontact">
|
|
||||||
<v-btn variant="plain"> Aide & Contact</v-btn>
|
|
||||||
</router-link>
|
|
||||||
<router-link to="/faq">
|
|
||||||
<v-btn variant="plain"> FAQ</v-btn>
|
|
||||||
</router-link>
|
|
||||||
<router-link to="/guideforcreators">
|
|
||||||
<v-btn variant="plain"> Guide pour les créateurs</v-btn>
|
|
||||||
</router-link>
|
|
||||||
<router-link to="/termsandconditions">
|
|
||||||
<v-btn variant="plain">Termes et Conditions </v-btn>
|
|
||||||
</router-link>
|
|
||||||
<router-link to="/contentpolicy">
|
|
||||||
<v-btn variant="plain"> Politique de Contenu </v-btn>
|
|
||||||
</router-link>
|
|
||||||
<router-link to="/about">
|
|
||||||
<v-btn variant="plain"> À Propos</v-btn>
|
|
||||||
</router-link>
|
|
||||||
<router-link to="/pricing">
|
|
||||||
<v-btn variant="plain"> Frais</v-btn>
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.filter-fushia{
|
|
||||||
filter: invert(14%) sepia(60%) saturate(4103%) hue-rotate(285deg) brightness(84%) contrast(93%);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import SiteMenu from "@/views/main/SiteMenu.vue";
|
|
||||||
import SubscriptionList from "@/views/creators/SubscriptionList.vue";
|
import SubscriptionList from "@/views/creators/SubscriptionList.vue";
|
||||||
import {useAuthStore} from "@/stores/authStore.js";
|
import {useAuthStore} from "@/stores/authStore.js";
|
||||||
import {useRouter} from 'vue-router';
|
import {useRouter} from 'vue-router';
|
||||||
@@ -37,9 +36,7 @@ initializeLocale();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<nav class="flex flex-col h-full overflow-y-auto custom-scrollbar">
|
<nav class="flex flex-col h-full overflow-y-auto custom-scrollbar bg-white">
|
||||||
<div class="mt-16"></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="flex justify-center py-3">
|
<div class="flex justify-center py-3">
|
||||||
<v-btn v-if="authStore.isAuthenticated" variant="plain" class="p-8" @click="feedHandler">
|
<v-btn v-if="authStore.isAuthenticated" variant="plain" class="p-8" @click="feedHandler">
|
||||||
@@ -66,9 +63,6 @@ initializeLocale();
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<subscription-list>
|
<subscription-list>
|
||||||
<template v-slot:default>
|
|
||||||
<span v-if="subscriptionListIsEmpty">Aucun abonnement</span>
|
|
||||||
</template>
|
|
||||||
</subscription-list>
|
</subscription-list>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -76,10 +70,6 @@ initializeLocale();
|
|||||||
<span>Connectez-vous</span>
|
<span>Connectez-vous</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="border-t w-full py-10 mt-auto">
|
|
||||||
<SiteMenu></SiteMenu>
|
|
||||||
</div>
|
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="flex flex-col">
|
|
||||||
|
|
||||||
<div class="flex flex-row justify-center pb-4 pt-2 py-4">
|
|
||||||
<!-- Facebook -->
|
|
||||||
<a href="https://www.facebook.com/profile.php?id=61556819217561" class="social">
|
|
||||||
<v-icon>mdi-facebook</v-icon>
|
|
||||||
</a>
|
|
||||||
<!-- Instagram -->
|
|
||||||
<a href="https://www.instagram.com/hutopy.inc/" class="social">
|
|
||||||
<v-icon>mdi-instagram</v-icon>
|
|
||||||
</a>
|
|
||||||
<!-- X / Twitter -->
|
|
||||||
<a href="https://twitter.com/Hutopyinc" class="social">
|
|
||||||
<img src="/images/hutopymedia/icons/x.svg" width="23px" height="23px" class="mb-5 mr-2">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center ">
|
|
||||||
<RouterLink class="nav-button" to="/helpandcontact">{{ $t('sitemenu.HelpAndContact') }}</RouterLink>
|
|
||||||
<RouterLink class="nav-button" to="/faq">{{ $t('sitemenu.FAQ') }}</RouterLink>
|
|
||||||
<RouterLink class="nav-button" to="/guideforcreators">{{ $t('sitemenu.CreatorGuide') }}</RouterLink>
|
|
||||||
<RouterLink class="nav-button" to="/termsandconditions">{{ $t('sitemenu.TermsAndConditions') }}</RouterLink>
|
|
||||||
<RouterLink class="nav-button" to="/contentpolicy">{{ $t('sitemenu.ContentPolicy') }}</RouterLink>
|
|
||||||
<RouterLink class="nav-button" to="/about">{{ $t('sitemenu.About') }}</RouterLink>
|
|
||||||
<RouterLink class="nav-button" to="/pricing">{{ $t('sitemenu.Pricing') }}</RouterLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.nav-button {
|
|
||||||
@apply rounded flex justify-center font-sans py-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-button:hover {
|
|
||||||
@apply text-purple-800 bg-gray-50;
|
|
||||||
}
|
|
||||||
|
|
||||||
.social {
|
|
||||||
@apply m-2 w-10 h-10;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -47,9 +47,9 @@
|
|||||||
<script async setup>
|
<script async setup>
|
||||||
import { onBeforeMount, ref, computed } from 'vue';
|
import { onBeforeMount, ref, computed } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import {useUserStore} from "@/stores/userStore.js";
|
import {useUserProfileStore} from "@/stores/userProfileStore.js";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userProfileStore = useUserProfileStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const userTransactions = ref([]);
|
const userTransactions = ref([]);
|
||||||
@@ -72,8 +72,8 @@ const transactionCount = computed(() => userTransactions.value.length);
|
|||||||
|
|
||||||
onBeforeMount( () => {
|
onBeforeMount( () => {
|
||||||
try {
|
try {
|
||||||
userTransactions.value = userStore.user.userTransactions;
|
userTransactions.value = userProfileStore.value.userTransactions;
|
||||||
totalBalance.value = userStore.user.totalBalance;
|
totalBalance.value = userProfileStore.value.totalBalance;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
navigateToHome();
|
navigateToHome();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,11 @@
|
|||||||
class="justify-items-center"
|
class="justify-items-center"
|
||||||
>
|
>
|
||||||
<template v-for="message in messages" :key="message">
|
<template v-for="message in messages" :key="message">
|
||||||
|
<div class="border-b">
|
||||||
<message :message="message"
|
<message :message="message"
|
||||||
@message-deleted="(messageId) => handleDeleteMessage(messageId)"
|
@message-deleted="(messageId) => handleDeleteMessage(messageId)"
|
||||||
class="border-b"
|
|
||||||
></message>
|
></message>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:load-more="{ props }">
|
<template v-slot:load-more="{ props }">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-column">
|
<div class="flex flex-column">
|
||||||
<div class="flex flex-row items-center ">
|
<div class="flex flex-row items-center ">
|
||||||
<img :src="userStore.portraitUrl" alt="Profile Image" class="rounded-full mr-2" width="32px" height="32px">
|
<img :src="userProfileStore.portraitUrl" alt="Profile Image" class="rounded-full mr-2" width="32px" height="32px">
|
||||||
<div class="flex-grow">
|
<div class="flex-grow">
|
||||||
<div class="flex flex-row bg-gray-100 rounded-2xl">
|
<div class="flex flex-row bg-gray-100 rounded-2xl">
|
||||||
<v-textarea
|
<v-textarea
|
||||||
@@ -36,14 +36,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<must-be-logged v-model="loginModal" message="Vous devez être connecté pour ajouter un commentaire."></must-be-logged>
|
<must-be-logged v-model="loginModal"
|
||||||
|
message="Vous devez être connecté pour ajouter un commentaire."
|
||||||
|
></must-be-logged>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from 'vue'
|
import {ref} from 'vue'
|
||||||
import {v7} from 'uuid'
|
import {v7} from 'uuid'
|
||||||
import {useClient} from '@/plugins/api.js'
|
import {useClient} from '@/plugins/api.js'
|
||||||
import {useUserStore} from "@/stores/userStore.js"
|
import {useUserProfileStore} from "@/stores/userProfileStore.js"
|
||||||
import {useAuthStore} from "@/stores/authStore.js"
|
import {useAuthStore} from "@/stores/authStore.js"
|
||||||
import MustBeLogged from "@/views/MustBeLogged.vue";
|
import MustBeLogged from "@/views/MustBeLogged.vue";
|
||||||
|
|
||||||
@@ -59,7 +62,7 @@ const emits = defineEmits(['message-posted'])
|
|||||||
const loginModal = ref(false);
|
const loginModal = ref(false);
|
||||||
const client = useClient()
|
const client = useClient()
|
||||||
const value = ref("")
|
const value = ref("")
|
||||||
const userStore = useUserStore()
|
const userProfileStore = useUserProfileStore()
|
||||||
const authStore = useAuthStore()
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
const publish = async () => {
|
const publish = async () => {
|
||||||
@@ -76,9 +79,9 @@ const publish = async () => {
|
|||||||
emits('message-posted', {
|
emits('message-posted', {
|
||||||
"id": messageId,
|
"id": messageId,
|
||||||
"subjectId": props.subjectId,
|
"subjectId": props.subjectId,
|
||||||
"createdBy": userStore.user.id,
|
"createdBy": userProfileStore.value.id,
|
||||||
"createdByName": userStore.alias,
|
"createdByName": userProfileStore.alias,
|
||||||
"createdByPortraitUrl": userStore.portraitUrl,
|
"createdByPortraitUrl": userProfileStore.portraitUrl,
|
||||||
"createdAt": new Date(Date.now()).toISOString(),
|
"createdAt": new Date(Date.now()).toISOString(),
|
||||||
"value": value.value,
|
"value": value.value,
|
||||||
"parentId": null
|
"parentId": null
|
||||||
|
|||||||
122
src/views/news/NewsList.vue
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<v-infinite-scroll :items="contents"
|
||||||
|
:onLoad="fetchContents">
|
||||||
|
|
||||||
|
<!-- TODO: the -mt-4 is necessary because the v-infinite-scroll has some 'top' panel offsetting the list -->
|
||||||
|
<div class="flex flex-column gap-4 -mt-4">
|
||||||
|
<template v-for="content in contents" :key="content.id">
|
||||||
|
<component
|
||||||
|
:is="isSmallScreen ? ContentCardSm : ContentCardNormal"
|
||||||
|
:content="content"
|
||||||
|
@content-deleted="onContentDeleted"
|
||||||
|
></component>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-slot:empty>
|
||||||
|
Il n'y a pas plus de contenus
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:error>
|
||||||
|
<v-alert type="error">{{ errorMessage }}</v-alert>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</v-infinite-scroll>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {useClient} from '@/plugins/api.js';
|
||||||
|
import {onBeforeUnmount, onMounted, ref, watch} from 'vue';
|
||||||
|
import ContentCardNormal from "@/views/contents/contentcards/NContentCard.vue";
|
||||||
|
import ContentCardSm from "@/views/contents/contentcards/SmContentCard.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
creatorId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
news: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const client = useClient()
|
||||||
|
const contents = ref(props.news)
|
||||||
|
const errorMessage = ref()
|
||||||
|
let last_id = null
|
||||||
|
|
||||||
|
const isSmallScreen = ref(false);
|
||||||
|
|
||||||
|
const updateScreenSize = () => {
|
||||||
|
isSmallScreen.value = window.matchMedia('(max-width: 600px)').matches;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateScreenSize();
|
||||||
|
window.addEventListener('resize', updateScreenSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener('resize', updateScreenSize);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function onContentDeleted(contentId) {
|
||||||
|
contents.value = contents.value.filter(c => c.id !== contentId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const creatorIdWatcher = watch(
|
||||||
|
() => props.creatorId,
|
||||||
|
(newCreatorId) => {
|
||||||
|
if (newCreatorId) {
|
||||||
|
contents.value = []
|
||||||
|
last_id = null
|
||||||
|
fetchContents({
|
||||||
|
done: () => {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
async function fetchContents({done, page_size = 10}) {
|
||||||
|
if (props.creatorId == null) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
let uri = `/api/contents/creator/${props.creatorId}?page_size=${page_size}`
|
||||||
|
if (last_id !== null) uri = uri + `&last_id=${last_id}`
|
||||||
|
|
||||||
|
const response = await client.get(uri)
|
||||||
|
|
||||||
|
if (response.status >= 200 && response.status < 300) {
|
||||||
|
|
||||||
|
const contentCount = response.data.length
|
||||||
|
|
||||||
|
if (contentCount > 0) {
|
||||||
|
contents.value.push(...response.data)
|
||||||
|
const [last_content] = response.data.slice(-1)
|
||||||
|
last_id = last_content.id
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentCount < page_size)
|
||||||
|
done('empty')
|
||||||
|
else
|
||||||
|
done('ok')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch posts", error);
|
||||||
|
errorMessage.value = error.message || "Failed to fetch contents";
|
||||||
|
done('error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<span class="value">Un portrait vous permet de personnaliser votre profil</span>
|
<span class="value">Un portrait vous permet de personnaliser votre profil</span>
|
||||||
<span>
|
<span>
|
||||||
<img
|
<img
|
||||||
:src="userStore.user.portraitUrl"
|
:src="userProfileStore.value.portraitUrl"
|
||||||
alt="Profile Image"
|
alt="Profile Image"
|
||||||
class="rounded-full"
|
class="rounded-full"
|
||||||
width="48px"
|
width="48px"
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
class="editableValue"
|
class="editableValue"
|
||||||
@click="openEditFullname">
|
@click="openEditFullname">
|
||||||
<span class="label">{{ $t('personnalinformation.fullname') }}</span>
|
<span class="label">{{ $t('personnalinformation.fullname') }}</span>
|
||||||
<span class="value">{{ userStore.fullname }}</span>
|
<span class="value">{{ userProfileStore.fullname }}</span>
|
||||||
<span><v-icon>mdi-chevron-right</v-icon></span>
|
<span><v-icon>mdi-chevron-right</v-icon></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
class="editableValue"
|
class="editableValue"
|
||||||
@click="openEditAlias">
|
@click="openEditAlias">
|
||||||
<span class="label">{{ $t('personnalinformation.alias') }}</span>
|
<span class="label">{{ $t('personnalinformation.alias') }}</span>
|
||||||
<span class="value">{{ userStore.user.alias }}</span>
|
<span class="value">{{ userProfileStore.value.alias }}</span>
|
||||||
<span><v-icon>mdi-chevron-right</v-icon></span>
|
<span><v-icon>mdi-chevron-right</v-icon></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
class="editableValue"
|
class="editableValue"
|
||||||
@click="openEditBirthday">
|
@click="openEditBirthday">
|
||||||
<span class="label">{{ $t('personnalinformation.dob') }}</span>
|
<span class="label">{{ $t('personnalinformation.dob') }}</span>
|
||||||
<span class="value">{{ userStore.user.birthDate }}</span>
|
<span class="value">{{ userProfileStore.value.birthDate }}</span>
|
||||||
<span><v-icon>mdi-chevron-right</v-icon></span>
|
<span><v-icon>mdi-chevron-right</v-icon></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
class="editableValue"
|
class="editableValue"
|
||||||
@click="openEditEmail">
|
@click="openEditEmail">
|
||||||
<span class="label">{{ $t('personnalinformation.email') }}</span>
|
<span class="label">{{ $t('personnalinformation.email') }}</span>
|
||||||
<span class="value">{{ userStore.user.email }}</span>
|
<span class="value">{{ userProfileStore.value.email }}</span>
|
||||||
<span><v-icon>mdi-chevron-right</v-icon></span>
|
<span><v-icon>mdi-chevron-right</v-icon></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
class="editableValue"
|
class="editableValue"
|
||||||
@click="openEditPhone">
|
@click="openEditPhone">
|
||||||
<span class="label">{{ $t('personnalinformation.phone') }}</span>
|
<span class="label">{{ $t('personnalinformation.phone') }}</span>
|
||||||
<span class="value">{{ userStore.user.phoneNumber }}</span>
|
<span class="value">{{ userProfileStore.value.phoneNumber }}</span>
|
||||||
<span><v-icon>mdi-chevron-right</v-icon></span>
|
<span><v-icon>mdi-chevron-right</v-icon></span>
|
||||||
</button>
|
</button>
|
||||||
</v-card>
|
</v-card>
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
class="editableValue"
|
class="editableValue"
|
||||||
@click="openEditAddress">
|
@click="openEditAddress">
|
||||||
<span class="label">{{ $t('personnalinformation.home') }}</span>
|
<span class="label">{{ $t('personnalinformation.home') }}</span>
|
||||||
<span class="value">{{ userStore.user.address }}</span>
|
<span class="value">{{ userProfileStore.value.address }}</span>
|
||||||
<span><v-icon>mdi-chevron-right</v-icon></span>
|
<span><v-icon>mdi-chevron-right</v-icon></span>
|
||||||
</button>
|
</button>
|
||||||
</v-card>
|
</v-card>
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
<v-dialog v-model="dialogEditPortraitShown" max-width="600px">
|
<v-dialog v-model="dialogEditPortraitShown" max-width="600px">
|
||||||
<portrait-dialog
|
<portrait-dialog
|
||||||
:portrait-url="userStore.user.portraitUrl"
|
:portrait-url="userProfileStore.value.portraitUrl"
|
||||||
@close="handleCloseEditPortrait"
|
@close="handleCloseEditPortrait"
|
||||||
@save="handleSaveEditPortrait"
|
@save="handleSaveEditPortrait"
|
||||||
></portrait-dialog>
|
></portrait-dialog>
|
||||||
@@ -102,8 +102,8 @@
|
|||||||
|
|
||||||
<v-dialog v-model="dialogEditFullnameShown" max-width="600px">
|
<v-dialog v-model="dialogEditFullnameShown" max-width="600px">
|
||||||
<fullname-dialog
|
<fullname-dialog
|
||||||
:firstname="userStore.user.firstname"
|
:firstname="userProfileStore.value.firstname"
|
||||||
:lastname="userStore.user.lastname"
|
:lastname="userProfileStore.value.lastname"
|
||||||
@close="handleCloseEditFullname"
|
@close="handleCloseEditFullname"
|
||||||
@save="handleSaveEditFullname"
|
@save="handleSaveEditFullname"
|
||||||
></fullname-dialog>
|
></fullname-dialog>
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
|
|
||||||
<v-dialog v-model="dialogEditAliasShown" max-width="600px">
|
<v-dialog v-model="dialogEditAliasShown" max-width="600px">
|
||||||
<alias-dialog
|
<alias-dialog
|
||||||
:alias="userStore.user.alias"
|
:alias="userProfileStore.value.alias"
|
||||||
@close="handleCloseEditAlias"
|
@close="handleCloseEditAlias"
|
||||||
@save="handleSaveEditAlias"
|
@save="handleSaveEditAlias"
|
||||||
></alias-dialog>
|
></alias-dialog>
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
|
|
||||||
<v-dialog v-model="dialogEditBirthdayShown" max-width="600px">
|
<v-dialog v-model="dialogEditBirthdayShown" max-width="600px">
|
||||||
<birthday-dialog
|
<birthday-dialog
|
||||||
:birth-date="userStore.user.birthDate"
|
:birth-date="userProfileStore.value.birthDate"
|
||||||
@close="handleCloseEditBirthday"
|
@close="handleCloseEditBirthday"
|
||||||
@save="handleSaveEditBirthday"
|
@save="handleSaveEditBirthday"
|
||||||
></birthday-dialog>
|
></birthday-dialog>
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
|
|
||||||
<v-dialog v-model="dialogEditPhoneShown" max-width="600px">
|
<v-dialog v-model="dialogEditPhoneShown" max-width="600px">
|
||||||
<phone-dialog
|
<phone-dialog
|
||||||
:phone="userStore.user.phoneNumber"
|
:phone="userProfileStore.value.phoneNumber"
|
||||||
@close="handleCloseEditPhone"
|
@close="handleCloseEditPhone"
|
||||||
@save="handleSaveEditPhone"
|
@save="handleSaveEditPhone"
|
||||||
></phone-dialog>
|
></phone-dialog>
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
|
|
||||||
<v-dialog v-model="dialogEditEmailShown" max-width="600px">
|
<v-dialog v-model="dialogEditEmailShown" max-width="600px">
|
||||||
<email-dialog
|
<email-dialog
|
||||||
:email="userStore.user.email"
|
:email="userProfileStore.value.email"
|
||||||
@close="handleCloseEditEmail"
|
@close="handleCloseEditEmail"
|
||||||
@save="handleSaveEditEmail"
|
@save="handleSaveEditEmail"
|
||||||
></email-dialog>
|
></email-dialog>
|
||||||
@@ -143,7 +143,7 @@
|
|||||||
|
|
||||||
<v-dialog v-model="dialogEditAddressShown" max-width="600px">
|
<v-dialog v-model="dialogEditAddressShown" max-width="600px">
|
||||||
<address-dialog
|
<address-dialog
|
||||||
:address="userStore.user.address"
|
:address="userProfileStore.value.address"
|
||||||
@close="handleCloseEditAddress"
|
@close="handleCloseEditAddress"
|
||||||
@save="handleSaveEditAddress"
|
@save="handleSaveEditAddress"
|
||||||
></address-dialog>
|
></address-dialog>
|
||||||
@@ -159,9 +159,10 @@ import BirthdayDialog from "@/views/profile/account/BirthdayDialog.vue";
|
|||||||
import AliasDialog from "@/views/profile/account/AliasDialog.vue";
|
import AliasDialog from "@/views/profile/account/AliasDialog.vue";
|
||||||
import FullnameDialog from "@/views/profile/account/FullnameDialog.vue";
|
import FullnameDialog from "@/views/profile/account/FullnameDialog.vue";
|
||||||
import PortraitDialog from "@/views/profile/account/PortraitDialog.vue";
|
import PortraitDialog from "@/views/profile/account/PortraitDialog.vue";
|
||||||
import {useUserStore} from "@/stores/userStore.js";
|
import {useUserProfileStore} from "@/stores/userProfileStore.js";
|
||||||
|
|
||||||
|
const userProfileStore = useUserProfileStore()
|
||||||
|
|
||||||
const userStore = useUserStore()
|
|
||||||
|
|
||||||
// ### Portrait
|
// ### Portrait
|
||||||
|
|
||||||
@@ -176,7 +177,7 @@ function handleCloseEditPortrait() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveEditPortrait(portraitData) {
|
function handleSaveEditPortrait(portraitData) {
|
||||||
userStore.changePortrait(portraitData)
|
userProfileStore.changePortrait(portraitData)
|
||||||
dialogEditPortraitShown.value = false
|
dialogEditPortraitShown.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +194,7 @@ function handleCloseEditFullname() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveEditFullname(firstname, lastname) {
|
function handleSaveEditFullname(firstname, lastname) {
|
||||||
userStore.changeFullname(firstname, lastname)
|
userProfileStore.changeFullname(firstname, lastname)
|
||||||
dialogEditFullnameShown.value = false
|
dialogEditFullnameShown.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +211,7 @@ function handleCloseEditAlias() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveEditAlias(alias) {
|
function handleSaveEditAlias(alias) {
|
||||||
userStore.changeAlias(alias)
|
userProfileStore.changeAlias(alias)
|
||||||
dialogEditAliasShown.value = false
|
dialogEditAliasShown.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +228,7 @@ function handleCloseEditBirthday() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveEditBirthday(birthday) {
|
function handleSaveEditBirthday(birthday) {
|
||||||
userStore.changeBirthday(birthday)
|
userProfileStore.changeBirthday(birthday)
|
||||||
dialogEditBirthdayShown.value = false
|
dialogEditBirthdayShown.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +245,7 @@ function handleCloseEditPhone() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveEditPhone(phone) {
|
function handleSaveEditPhone(phone) {
|
||||||
userStore.changePhone(phone)
|
userProfileStore.changePhone(phone)
|
||||||
dialogEditPhoneShown.value = false
|
dialogEditPhoneShown.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +262,7 @@ function handleCloseEditEmail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveEditEmail(email) {
|
function handleSaveEditEmail(email) {
|
||||||
userStore.changeEmail(email)
|
userProfileStore.changeEmail(email)
|
||||||
dialogEditEmailShown.value = false
|
dialogEditEmailShown.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +278,7 @@ function handleCloseEditAddress() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveEditAddress(address) {
|
function handleSaveEditAddress(address) {
|
||||||
userStore.changeAddress(address)
|
userProfileStore.changeAddress(address)
|
||||||
dialogEditAddressShown.value = false
|
dialogEditAddressShown.value = false
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import {ref} from 'vue'
|
|
||||||
import {useClient} from "@/plugins/api.js";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
creator: {
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const emits = defineEmits(['closeRequested'])
|
|
||||||
|
|
||||||
const title = ref(props.creator.about.title)
|
|
||||||
const description = ref(props.creator.about.description)
|
|
||||||
|
|
||||||
const client = useClient()
|
|
||||||
const save = async () => {
|
|
||||||
try {
|
|
||||||
await client.post(
|
|
||||||
`/api/creators/${props.creator.id}/about`,
|
|
||||||
{
|
|
||||||
"title": title.value || null,
|
|
||||||
"description": description.value || null
|
|
||||||
})
|
|
||||||
|
|
||||||
props.creator.about.title = title
|
|
||||||
props.creator.about.description = description
|
|
||||||
|
|
||||||
emits('closeRequested')
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const cancel = () => {
|
|
||||||
emits('closeRequested')
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="pb-5 text-2xl">About</div>
|
|
||||||
|
|
||||||
<div class="flex flex-row align-center">
|
|
||||||
<v-text-field
|
|
||||||
variant="outlined"
|
|
||||||
v-model="title"
|
|
||||||
label="Titre"
|
|
||||||
outlined
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="flex flex-row align-center">
|
|
||||||
<v-text-field
|
|
||||||
variant="outlined"
|
|
||||||
v-model="description"
|
|
||||||
label="Description"
|
|
||||||
outlined
|
|
||||||
></v-text-field>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-end space-x-4">
|
|
||||||
<v-btn color="black" variant="text" @click="cancel">Annuler</v-btn>
|
|
||||||
<v-btn color="#A6147D" @click="save">Enregistrer</v-btn>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,22 +1,23 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import XIcon from '@/assets/icons/x.svg'
|
||||||
import {computed, ref} from 'vue'
|
import {computed, ref} from 'vue'
|
||||||
import {useUserStore} from "@/stores/userStore.js"
|
|
||||||
import Socials from './Socials.vue'
|
import Socials from './Socials.vue'
|
||||||
import BannerPicker from './BannerPicker.vue'
|
import BannerPicker from './BannerPicker.vue'
|
||||||
import ColorsPicker from './ColorsPicker.vue'
|
import ColorsPicker from './ColorsPicker.vue'
|
||||||
import LogoPicker from "./LogoPicker.vue"
|
import LogoPicker from "./LogoPicker.vue"
|
||||||
import About from "./About.vue";
|
|
||||||
import CreateCreator from "./CreateCreator.vue";
|
import CreateCreator from "./CreateCreator.vue";
|
||||||
import {useClient} from "@/plugins/api.js";
|
import {useClient} from "@/plugins/api.js";
|
||||||
|
import {useCreatorProfileStore} from "@/stores/creatorProfileStore.js";
|
||||||
|
import {useUserProfileStore} from "@/stores/userProfileStore.js";
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const creatorProfileStore = useCreatorProfileStore()
|
||||||
|
|
||||||
const colorBannerTop = computed(() => userStore.creator.colors.bannerTop || '#a0c0f0')
|
const colorBannerTop = computed(() => creatorProfileStore.value.colors.bannerTop || '#a0c0f0')
|
||||||
const colorBannerBottom = computed(() => userStore.creator.colors.bannerBottom || '#a0c0f0')
|
const colorBannerBottom = computed(() => creatorProfileStore.value.colors.bannerBottom || '#a0c0f0')
|
||||||
const colorAccent = computed(() => userStore.creator.colors.accent || '#a0c0f0')
|
const colorAccent = computed(() => creatorProfileStore.value.colors.accent || '#a0c0f0')
|
||||||
const colorMenu = computed(() => userStore.creator.colors.menu || '#a0c0f0')
|
const colorMenu = computed(() => creatorProfileStore.value.colors.menu || '#a0c0f0')
|
||||||
const imageBanner = computed(() => userStore.creator.images.banner || '/images/placeholders/banner.png')
|
const imageBanner = computed(() => creatorProfileStore.value.images.banner || '/images/placeholders/banner.png')
|
||||||
const imageLogo = computed(() => userStore.creator.images.logo || '/images/placeholders/logo.png')
|
const imageLogo = computed(() => creatorProfileStore.value.images.logo || '/images/placeholders/logo.png')
|
||||||
|
|
||||||
const dialog = ref(false);
|
const dialog = ref(false);
|
||||||
const currentComponent = ref('')
|
const currentComponent = ref('')
|
||||||
@@ -27,20 +28,20 @@ const componentsMap = {
|
|||||||
LogoPicker,
|
LogoPicker,
|
||||||
Socials,
|
Socials,
|
||||||
ColorsPicker,
|
ColorsPicker,
|
||||||
About,
|
|
||||||
CreateCreator
|
CreateCreator
|
||||||
};
|
};
|
||||||
|
|
||||||
async function requestAccept(creatorName) {
|
async function requestAccept(creatorName) {
|
||||||
|
const userProfileStore = useUserProfileStore()
|
||||||
const client = useClient()
|
const client = useClient()
|
||||||
const response = await client.post(
|
const response = await client.post(
|
||||||
'/api/creators',
|
'/api/creators',
|
||||||
{
|
{
|
||||||
'creatorId': userStore.user.id,
|
'creatorId': userProfileStore.value.id,
|
||||||
'name': creatorName
|
'name': creatorName
|
||||||
})
|
})
|
||||||
if (response.status >= 200 && response.status < 300) {
|
if (response.status >= 200 && response.status < 300) {
|
||||||
await userStore.fetchCurrentCreatorProfile()
|
await creatorProfileStore.fetchCurrentCreatorProfile()
|
||||||
dialog.value = false
|
dialog.value = false
|
||||||
} else {
|
} else {
|
||||||
console.log(`An issue while creating the creator: ${response.statusText}`)
|
console.log(`An issue while creating the creator: ${response.statusText}`)
|
||||||
@@ -70,7 +71,7 @@ const closeDialog = () => {
|
|||||||
<v-card :style="{ borderRadius: '25px', border: '3px solid rgb(159, 76, 173)' }">
|
<v-card :style="{ borderRadius: '25px', border: '3px solid rgb(159, 76, 173)' }">
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<component :is="currentComponent"
|
<component :is="currentComponent"
|
||||||
:creator="userStore.creator"
|
:creator="creatorProfileStore.value"
|
||||||
:colorName="colorToEdit"
|
:colorName="colorToEdit"
|
||||||
@closeRequested="closeDialog"
|
@closeRequested="closeDialog"
|
||||||
@requestAccept="requestAccept"
|
@requestAccept="requestAccept"
|
||||||
@@ -87,7 +88,7 @@ const closeDialog = () => {
|
|||||||
{{ $t('creatorinfopage.pageinformation') }}
|
{{ $t('creatorinfopage.pageinformation') }}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div v-if="userStore.hasCreator" class="w-full max-w-[800px]">
|
<div v-if="creatorProfileStore.hasCreator" class="w-full max-w-[800px]">
|
||||||
|
|
||||||
<div class="my-10 border rounded-2xl">
|
<div class="my-10 border rounded-2xl">
|
||||||
|
|
||||||
@@ -97,27 +98,7 @@ const closeDialog = () => {
|
|||||||
|
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
||||||
<span class="flex-none pa-2 min-w-32 text-left">{{ $t('creatorinfopage.name') }}</span>
|
<span class="flex-none pa-2 min-w-32 text-left">{{ $t('creatorinfopage.name') }}</span>
|
||||||
<span class="flex-auto text-left pr-6 capitalize">{{ userStore.creator.name }}</span>
|
<span class="flex-auto text-left pr-6 capitalize">{{ creatorProfileStore.value.name }}</span>
|
||||||
<span class="flex-none">
|
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
@click="openDialog('About')"
|
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
|
||||||
<span class="flex-none pa-2 min-w-32 text-left">{{$t('creatorinfopage.title')}}</span>
|
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.about.title }}</span>
|
|
||||||
<span class="flex-none">
|
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
@click="openDialog('About')"
|
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full rounded-b-2xl ">
|
|
||||||
<span class="pa-2 min-w-32 text-left">{{$t('creatorinfopage.description')}}</span>
|
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.about.description }}</span>
|
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
@@ -195,7 +176,7 @@ const closeDialog = () => {
|
|||||||
@click="openDialog('Socials')"
|
@click="openDialog('Socials')"
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
||||||
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-facebook</v-icon></span>
|
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-facebook</v-icon></span>
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.socials.facebookUrl }}</span>
|
<span class="flex-auto text-left pr-6">{{ creatorProfileStore.value.socials.facebookUrl }}</span>
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
@@ -205,7 +186,7 @@ const closeDialog = () => {
|
|||||||
@click="openDialog('Socials')"
|
@click="openDialog('Socials')"
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
||||||
<span class="flex-none pa-2 min-w-32 text-left"> <v-icon>mdi-instagram</v-icon></span>
|
<span class="flex-none pa-2 min-w-32 text-left"> <v-icon>mdi-instagram</v-icon></span>
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.socials.instagramUrl }}</span>
|
<span class="flex-auto text-left pr-6">{{ creatorProfileStore.value.socials.instagramUrl }}</span>
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
@@ -214,9 +195,10 @@ const closeDialog = () => {
|
|||||||
<button
|
<button
|
||||||
@click="openDialog('Socials')"
|
@click="openDialog('Socials')"
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full">
|
||||||
<span class="flex-none pa-2 min-w-32 text-left"> <img src="/images/hutopymedia/icons/x.svg" width="23px"
|
<span class="flex-none pa-2 w-6 h-6 text-left">
|
||||||
height="23px"></span>
|
<XIcon></XIcon>
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.socials.xUrl }}</span>
|
</span>
|
||||||
|
<span class="flex-auto text-left pr-6">{{ creatorProfileStore.value.socials.xUrl }}</span>
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
@@ -226,7 +208,7 @@ const closeDialog = () => {
|
|||||||
@click="openDialog('Socials')"
|
@click="openDialog('Socials')"
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full ">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full ">
|
||||||
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-linkedin</v-icon></span>
|
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-linkedin</v-icon></span>
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.socials.linkedInUrl }}</span>
|
<span class="flex-auto text-left pr-6">{{ creatorProfileStore.value.socials.linkedInUrl }}</span>
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
@@ -236,9 +218,9 @@ const closeDialog = () => {
|
|||||||
@click="openDialog('Socials')"
|
@click="openDialog('Socials')"
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full ">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full ">
|
||||||
<span class="flex-none pa-2 min-w-32 text-left">
|
<span class="flex-none pa-2 min-w-32 text-left">
|
||||||
<img src="/images/hutopymedia/icons/tiktok.svg" class="w-5 h-5">
|
<XIcon class="w-5 h-5"></XIcon>
|
||||||
</span>
|
</span>
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.socials.tikTokUrl }}</span>
|
<span class="flex-auto text-left pr-6">{{ creatorProfileStore.value.socials.tikTokUrl }}</span>
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
@@ -248,7 +230,7 @@ const closeDialog = () => {
|
|||||||
@click="openDialog('Socials')"
|
@click="openDialog('Socials')"
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full ">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full ">
|
||||||
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-youtube</v-icon></span>
|
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-youtube</v-icon></span>
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.socials.youtubeUrl }}</span>
|
<span class="flex-auto text-left pr-6">{{ creatorProfileStore.value.socials.youtubeUrl }}</span>
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
@@ -258,7 +240,7 @@ const closeDialog = () => {
|
|||||||
@click="openDialog('Socials')"
|
@click="openDialog('Socials')"
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full ">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full ">
|
||||||
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-reddit</v-icon></span>
|
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-reddit</v-icon></span>
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.socials.redditUrl }}</span>
|
<span class="flex-auto text-left pr-6">{{ creatorProfileStore.value.socials.redditUrl }}</span>
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
@@ -268,7 +250,7 @@ const closeDialog = () => {
|
|||||||
@click="openDialog('Socials')"
|
@click="openDialog('Socials')"
|
||||||
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full rounded-b-2xl ">
|
class="HoverBtn active:bg-gray-300 py-2 px-4 border-gray-400 shadow flex items-center transition duration-200 ease-in-out w-full rounded-b-2xl ">
|
||||||
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-web</v-icon></span>
|
<span class="pa-2 min-w-32 text-left"><v-icon>mdi-web</v-icon></span>
|
||||||
<span class="flex-auto text-left pr-6">{{ userStore.creator.socials.websiteUrl }}</span>
|
<span class="flex-auto text-left pr-6">{{ creatorProfileStore.value.socials.websiteUrl }}</span>
|
||||||
<span class="flex-none">
|
<span class="flex-none">
|
||||||
<v-icon>mdi-chevron-right</v-icon>
|
<v-icon>mdi-chevron-right</v-icon>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import XIcon from '@/assets/icons/x.svg'
|
||||||
import {ref} from 'vue'
|
import {ref} from 'vue'
|
||||||
import {useClient} from "@/plugins/api.js";
|
import {useClient} from "@/plugins/api.js";
|
||||||
|
|
||||||
@@ -56,6 +57,14 @@ const cancel = () => {
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.icon {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
fill: #1976d2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="pb-5 text-2xl">Reseaux Sociaux</div>
|
<div class="pb-5 text-2xl">Reseaux Sociaux</div>
|
||||||
<div class="flex flex-row align-center">
|
<div class="flex flex-row align-center">
|
||||||
@@ -100,7 +109,9 @@ const cancel = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row align-center">
|
<div class="flex flex-row align-center">
|
||||||
<img src="/images/hutopymedia/icons/tiktok.svg" width="23px" height="23px" class="mb-5 mr-2">
|
<div class="w-6 h-6 mb-5 mr-2">
|
||||||
|
<XIcon></XIcon>
|
||||||
|
</div>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
v-model="tikTokUrl"
|
v-model="tikTokUrl"
|
||||||
@@ -118,9 +129,13 @@ const cancel = () => {
|
|||||||
outlined
|
outlined
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-row align-center">
|
<div class="flex flex-row align-center">
|
||||||
<img src="/images/hutopymedia/icons/x.svg" width="23px" height="23px" class="mb-5 mr-2">
|
|
||||||
|
<div class="w-6 h-6 mb-5 mr-2">
|
||||||
|
|
||||||
|
<XIcon class="icon"></XIcon>
|
||||||
|
</div>
|
||||||
|
|
||||||
<v-text-field
|
<v-text-field
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
v-model="xUrl"
|
v-model="xUrl"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {fileURLToPath, URL} from 'node:url'
|
import {fileURLToPath, URL} from 'node:url'
|
||||||
import {defineConfig, loadEnv} from 'vite'
|
import {defineConfig, loadEnv} from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import svgLoader from 'vite-svg-loader'
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig(({mode}) => {
|
export default defineConfig(({mode}) => {
|
||||||
@@ -10,6 +10,7 @@ export default defineConfig(({ mode }) => {
|
|||||||
return {
|
return {
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
|
svgLoader()
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|||||||