Compare commits
1 Commits
0.4.0
...
features/n
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b86cf52839 |
@@ -1,5 +1,13 @@
|
|||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*/**]
|
[*]
|
||||||
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
insert_final_newline = false
|
||||||
|
trim_trailing_whitespace = false
|
||||||
@@ -1 +0,0 @@
|
|||||||
VITE_API_URL = "http://localhost:3000"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
VITE_API_URL = "https://api-deputes.alexcreates.fr"
|
|
||||||
40
.gitignore
vendored
40
.gitignore
vendored
@@ -1,28 +1,24 @@
|
|||||||
|
# Nuxt dev/build outputs
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.nuxt
|
||||||
|
.nitro
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
# Misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
dist
|
.fleet
|
||||||
dist-ssr
|
|
||||||
coverage
|
|
||||||
*.local
|
|
||||||
|
|
||||||
/cypress/videos/
|
|
||||||
/cypress/screenshots/
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
.idea
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
# Local env files
|
||||||
*.njsproj
|
.env
|
||||||
*.sln
|
.env.*
|
||||||
*.sw?
|
!.env.example
|
||||||
|
|||||||
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
|
||||||
}
|
|
||||||
18
app.vue
Normal file
18
app.vue
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wrapper">
|
||||||
|
<Navbar />
|
||||||
|
<main class="p-4">
|
||||||
|
<NuxtPage />
|
||||||
|
</main>
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.wrapper {
|
||||||
|
min-height: 100dvh;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
76
assets/css/main.css
Normal file
76
assets/css/main.css
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
@apply bg-background text-foreground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--muted: 210 40% 96.1%;
|
||||||
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--border: 214.3 31.8% 91.4%;
|
||||||
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
|
||||||
|
--primary: 222.2 47.4% 11.2%;
|
||||||
|
--primary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--secondary: 210 40% 96.1%;
|
||||||
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--accent: 210 40% 96.1%;
|
||||||
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--ring: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark-mode {
|
||||||
|
--background: 222.2 84% 4.9%;
|
||||||
|
--foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--muted: 217.2 32.6% 17.5%;
|
||||||
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
|
||||||
|
--popover: 222.2 84% 4.9%;
|
||||||
|
--popover-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--card: 222.2 84% 4.9%;
|
||||||
|
--card-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--border: 217.2 32.6% 17.5%;
|
||||||
|
--input: 217.2 32.6% 17.5%;
|
||||||
|
|
||||||
|
--primary: 210 40% 98%;
|
||||||
|
--primary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--secondary: 217.2 32.6% 17.5%;
|
||||||
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--accent: 217.2 32.6% 17.5%;
|
||||||
|
--accent-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--ring: 212.7 26.8% 83.9%;
|
||||||
|
}
|
||||||
16
components.json
Normal file
16
components.json
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://shadcn-vue.com/schema.json",
|
||||||
|
"style": "default",
|
||||||
|
"typescript": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.js",
|
||||||
|
"css": "assets/css/main.css",
|
||||||
|
"baseColor": "slate",
|
||||||
|
"cssVariables": true
|
||||||
|
},
|
||||||
|
"framework": "nuxt",
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
components/footer.vue
Normal file
7
components/footer.vue
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<footer class="p-4">
|
||||||
|
<span>
|
||||||
|
Données issues de <a href="https://data.assemblee-nationale.fr/">data.assemblee-nationale.fr</a>
|
||||||
|
</span>
|
||||||
|
</footer>
|
||||||
|
</template>
|
||||||
9
components/navbar.vue
Normal file
9
components/navbar.vue
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<nav>
|
||||||
|
Testos
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
3
env.d.ts
vendored
3
env.d.ts
vendored
@@ -1,3 +0,0 @@
|
|||||||
/// <reference types="vite/client" />
|
|
||||||
declare module "geojson-geometries-lookup";
|
|
||||||
declare module "pako";
|
|
||||||
44
index.html
44
index.html
@@ -1,44 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Trouver mon député</title>
|
|
||||||
|
|
||||||
<!--theme colors -->
|
|
||||||
<meta name="theme-color" content="#020617" />
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
||||||
|
|
||||||
<!--Basic meta info -->
|
|
||||||
<meta name="keywords" content="député, géolocalisation, assemblée nationale, france, représentant, démocratie, voter, élections, parlementaires, parlementarisme">
|
|
||||||
<meta name="author" content="Alexis Pelé" />
|
|
||||||
<meta name="description" content="Trouvez facilement votre député parlementaires ; Localisez facilement votre circonscription et découvrez qui vous représente sans vous arrachez les cheveux !">
|
|
||||||
|
|
||||||
<!--OpenGraph meta -->
|
|
||||||
<meta property="og:description" content="Application de géolocalisation des députés par circonscription" />
|
|
||||||
<meta property="og:title" content="Trouver mon député" />
|
|
||||||
|
|
||||||
<!--meta for twitter -->
|
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
|
||||||
<meta name="twitter:creator" content="@bhupeshimself">
|
|
||||||
<meta name="twitter:title" content="">
|
|
||||||
<meta name="twitter:image" content="logo.png">
|
|
||||||
<meta name="twitter:site" content="@bhupeshimself">
|
|
||||||
<meta name="twitter:description" content="">
|
|
||||||
|
|
||||||
<!--Favicon-->
|
|
||||||
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
|
||||||
<link rel="manifest" href="/site.webmanifest">
|
|
||||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
|
|
||||||
<link rel="shortcut icon" href="/favicon.ico">
|
|
||||||
<meta name="msapplication-TileColor" content="#da532c">
|
|
||||||
<meta name="msapplication-config" content="/browserconfig.xml">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="module" src="/src/main.ts"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
6
lib/utils.ts
Normal file
6
lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { type ClassValue, clsx } from 'clsx'
|
||||||
|
import { twMerge } from 'tailwind-merge'
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
||||||
21
nuxt.config.ts
Normal file
21
nuxt.config.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
devtools: { enabled: true },
|
||||||
|
modules: [
|
||||||
|
'@nuxtjs/tailwindcss',
|
||||||
|
'@nuxtjs/color-mode',
|
||||||
|
'shadcn-nuxt',
|
||||||
|
'@vueuse/nuxt',
|
||||||
|
],
|
||||||
|
css: ['~/assets/css/main.css'],
|
||||||
|
shadcn: {
|
||||||
|
prefix: '',
|
||||||
|
componentDir: './components/ui'
|
||||||
|
},
|
||||||
|
postcss: {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
12156
package-lock.json
generated
12156
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
62
package.json
62
package.json
@@ -1,43 +1,35 @@
|
|||||||
{
|
{
|
||||||
"name": "rep-lookup-fr",
|
"name": "nuxt-app",
|
||||||
"version": "0.1.0",
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"build": "nuxt build",
|
||||||
"build": "run-p type-check build-only",
|
"dev": "nuxt dev",
|
||||||
"preview": "vite preview --port 4173",
|
"generate": "nuxt generate",
|
||||||
"build-only": "vite build",
|
"preview": "nuxt preview",
|
||||||
"type-check": "vue-tsc --noEmit",
|
"postinstall": "nuxt prepare"
|
||||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.4.0",
|
"@vueuse/core": "^10.9.0",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.4.0",
|
"@vueuse/nuxt": "^10.9.0",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.4.0",
|
"class-variance-authority": "^0.7.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.4.0",
|
"clsx": "^2.1.0",
|
||||||
"@fortawesome/vue-fontawesome": "^3.0.3",
|
"lucide-vue-next": "^0.359.0",
|
||||||
"@tailwindcss/typography": "^0.5.4",
|
"nuxt": "^3.11.1",
|
||||||
"@vueuse/core": "^10.1.0",
|
"radix-vue": "^1.5.3",
|
||||||
"pinia": "^2.0.35",
|
"tailwind-merge": "^2.2.2",
|
||||||
"vue": "^3.2.47",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"vue-router": "^4.1.6"
|
"vue": "^3.4.21",
|
||||||
|
"vue-router": "^4.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.1.0",
|
"@nuxtjs/color-mode": "^3.3.3",
|
||||||
"@types/node": "^16.11.45",
|
"@nuxtjs/tailwindcss": "^6.11.4",
|
||||||
"@vitejs/plugin-vue": "^4.1.0",
|
"autoprefixer": "^10.4.18",
|
||||||
"@vue/eslint-config-prettier": "^7.1.0",
|
"postcss": "^8.4.37",
|
||||||
"@vue/eslint-config-typescript": "^11.0.2",
|
"sass": "^1.72.0",
|
||||||
"@vue/tsconfig": "^0.1.3",
|
"shadcn-nuxt": "^0.10.2",
|
||||||
"autoprefixer": "^10.4.8",
|
"tailwindcss": "^3.4.1",
|
||||||
"eslint": "^8.39.0",
|
"typescript": "^5.4.2"
|
||||||
"eslint-plugin-vue": "^9.0.0",
|
|
||||||
"npm-run-all": "^4.1.5",
|
|
||||||
"postcss": "^8.4.23",
|
|
||||||
"prettier": "^2.5.1",
|
|
||||||
"sass": "^1.62.0",
|
|
||||||
"tailwindcss": "^3.3.1",
|
|
||||||
"typescript": "~4.7.4",
|
|
||||||
"vite": "^4.3.1",
|
|
||||||
"vue-tsc": "^0.38.8"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
pages/index.vue
Normal file
5
pages/index.vue
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Trouver mon député</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
3
server/tsconfig.json
Normal file
3
server/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"extends": "../.nuxt/tsconfig.server.json"
|
||||||
|
}
|
||||||
17
src/App.vue
17
src/App.vue
@@ -1,17 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="wrapper">
|
|
||||||
<div class="flex justify-center items-center">
|
|
||||||
<RouterView />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
#wrapper {
|
|
||||||
min-height: 100dvh;
|
|
||||||
min-height: 100vh;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-rows: 1fr;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');
|
|
||||||
|
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
body {
|
|
||||||
@apply text-slate-100 bg-slate-950
|
|
||||||
}
|
|
||||||
|
|
||||||
@layer components {
|
|
||||||
.btn-red {
|
|
||||||
@apply bg-red-600 outline-red-700 hover:bg-red-700 disabled:bg-slate-400 disabled:outline-slate-400 disabled:hover:bg-slate-400
|
|
||||||
}
|
|
||||||
.btn-twitter {
|
|
||||||
@apply bg-twitter-500 outline-twitter-600 hover:bg-twitter-600
|
|
||||||
}
|
|
||||||
.btn-facebook {
|
|
||||||
@apply bg-facebook-500 outline-facebook-600 hover:bg-facebook-600
|
|
||||||
}
|
|
||||||
.btn-instagram {
|
|
||||||
@apply bg-instagram-500 outline-instagram-600 hover:bg-instagram-600
|
|
||||||
}
|
|
||||||
.btn-linkedin {
|
|
||||||
@apply bg-linkedin-500 outline-linkedin-600 hover:bg-linkedin-600
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { useRepStore } from "@/stores/repStore";
|
|
||||||
import { useGeolocation } from "@vueuse/core";
|
|
||||||
import RepButton from "./RepButton.vue";
|
|
||||||
import { computed, ref } from "vue";
|
|
||||||
|
|
||||||
const { getRep, setRep } = useRepStore();
|
|
||||||
|
|
||||||
const { coords } = useGeolocation({
|
|
||||||
enableHighAccuracy: true,
|
|
||||||
});
|
|
||||||
const isFetching = ref<boolean>(false);
|
|
||||||
const lastError = ref<string>("");
|
|
||||||
|
|
||||||
const buttonIcon = computed(() =>
|
|
||||||
isFetching.value ? "spinner" : "location-dot"
|
|
||||||
);
|
|
||||||
|
|
||||||
async function handleGeolocClick() {
|
|
||||||
isFetching.value = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const rep = await getRep(coords.value.longitude, coords.value.latitude);
|
|
||||||
|
|
||||||
setRep(rep);
|
|
||||||
} catch (err) {
|
|
||||||
const error = (await err) as Error;
|
|
||||||
lastError.value = error.message;
|
|
||||||
} finally {
|
|
||||||
isFetching.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<RepButton @click="handleGeolocClick" :style="'btn-red'">
|
|
||||||
<font-awesome-icon
|
|
||||||
:icon="['fass', buttonIcon]"
|
|
||||||
size="lg"
|
|
||||||
:class="{ 'fa-spin': isFetching }"
|
|
||||||
/>
|
|
||||||
<span>Géolocalisation</span>
|
|
||||||
</RepButton>
|
|
||||||
<!-- <div
|
|
||||||
v-if="!lastError && coords.accuracy > 1000"
|
|
||||||
class="mt-4 max-w-lg mx-auto text-sm text-red-400"
|
|
||||||
>
|
|
||||||
Position peu précise ; votre député sera peut être différement de notre
|
|
||||||
résultat
|
|
||||||
</div> -->
|
|
||||||
<div v-if="lastError" class="mt-4 max-w-lg mx-auto text-sm text-red-400">
|
|
||||||
{{ lastError }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { computed } from "vue";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
href?: string;
|
|
||||||
target?: string;
|
|
||||||
rel?: string;
|
|
||||||
style?:
|
|
||||||
| "btn-red"
|
|
||||||
| "btn-twitter"
|
|
||||||
| "btn-facebook"
|
|
||||||
| "btn-instagram"
|
|
||||||
| "btn-linkedin";
|
|
||||||
disabled?: boolean;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const elementTag = computed(() => (props.href ? "a" : "button"));
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<component
|
|
||||||
:is="elementTag"
|
|
||||||
v-bind="props"
|
|
||||||
class="w-full md:w-max py-[10px] px-4 flex md:inline-flex text-white justify-center items-center gap-2 rounded-md font-semibold tracking-wide outline-2 outline-offset-4 focus-visible:outline transition-colors"
|
|
||||||
:class="props.style"
|
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
</component>
|
|
||||||
</template>
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import { onMounted, ref } from "vue";
|
|
||||||
import GeolocButton from "./GeolocButton.vue";
|
|
||||||
import RepButton from "./RepButton.vue";
|
|
||||||
|
|
||||||
const hasAcceptedGeoloc = ref(false);
|
|
||||||
const hasRefusedGeoloc = ref(false);
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
navigator.permissions.query({ name: "geolocation" }).then((result) => {
|
|
||||||
if (result.state === "granted") {
|
|
||||||
hasAcceptedGeoloc.value = true;
|
|
||||||
hasRefusedGeoloc.value = false;
|
|
||||||
} else if (result.state === "denied") {
|
|
||||||
hasAcceptedGeoloc.value = false;
|
|
||||||
hasRefusedGeoloc.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.addEventListener("change", () => {
|
|
||||||
if (result.state === "granted") {
|
|
||||||
hasAcceptedGeoloc.value = true;
|
|
||||||
hasRefusedGeoloc.value = false;
|
|
||||||
} else if (result.state === "denied") {
|
|
||||||
hasAcceptedGeoloc.value = false;
|
|
||||||
hasRefusedGeoloc.value = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function acceptGeoloc() {
|
|
||||||
navigator.permissions.query({ name: "geolocation" }).then((result) => {
|
|
||||||
if (result.state === "granted" || result.state === "prompt") {
|
|
||||||
hasAcceptedGeoloc.value = true;
|
|
||||||
hasRefusedGeoloc.value = false;
|
|
||||||
} else if (result.state === "denied") {
|
|
||||||
hasAcceptedGeoloc.value = false;
|
|
||||||
hasRefusedGeoloc.value = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<section class="text-center">
|
|
||||||
<header class="mb-4">
|
|
||||||
<h1 class="mt-4 text-center font-bold text-3xl">
|
|
||||||
Qui me représente à l'Assemblée Nationale ?
|
|
||||||
</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<RepButton
|
|
||||||
@click="acceptGeoloc"
|
|
||||||
:style="'btn-red'"
|
|
||||||
:disabled="hasRefusedGeoloc"
|
|
||||||
v-if="!hasAcceptedGeoloc"
|
|
||||||
>
|
|
||||||
<font-awesome-icon :icon="['fas', 'square']" size="lg" />
|
|
||||||
<span>Me géolocaliser</span>
|
|
||||||
</RepButton>
|
|
||||||
<GeolocButton v-else />
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { Organisation } from "@/models/org";
|
|
||||||
import RepButton from "./RepButton.vue";
|
|
||||||
|
|
||||||
import type { Depute } from "@/models/rep";
|
|
||||||
import { computed, onMounted, ref } from "vue";
|
|
||||||
|
|
||||||
const apiUrl = import.meta.env.VITE_API_URL;
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
rep: Depute;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const politicalPartyId = props.rep.acteur.mandats.mandat.find(
|
|
||||||
(m) => m.typeOrgane === "GP" && !m.dateFin
|
|
||||||
)?.organes.organeRef;
|
|
||||||
|
|
||||||
const repPoliticalParty = ref<Organisation | null>(null);
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
repPoliticalParty.value = await fetch(
|
|
||||||
`${apiUrl}/org?id=${politicalPartyId}`
|
|
||||||
).then((t) => t.json());
|
|
||||||
});
|
|
||||||
|
|
||||||
const repImage = computed(() => {
|
|
||||||
const imageRef = props.rep.acteur.uid["#text"].replace("PA", "");
|
|
||||||
return `https://www2.assemblee-nationale.fr/static/tribun/16/photos/carre/${imageRef}.jpg`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const repFullName = computed(
|
|
||||||
() =>
|
|
||||||
`${props.rep.acteur.etatCivil.ident.prenom} ${props.rep.acteur.etatCivil.ident.nom}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const repMandate = computed(() => {
|
|
||||||
const parliamentMandate = props.rep.acteur.mandats.mandat.find(
|
|
||||||
(mandate) => mandate.typeOrgane === "ASSEMBLEE"
|
|
||||||
);
|
|
||||||
return parliamentMandate;
|
|
||||||
});
|
|
||||||
|
|
||||||
const repTwitter = computed(() =>
|
|
||||||
props.rep.acteur.adresses.adresse.find(
|
|
||||||
(adr) => adr["typeLibelle"] === "Twitter"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
const repFacebook = computed(() => {
|
|
||||||
const data = props.rep.acteur.adresses.adresse.find(
|
|
||||||
(adr) => adr["typeLibelle"] === "Facebook"
|
|
||||||
);
|
|
||||||
if (data) {
|
|
||||||
data.valElec = String(data.valElec).replace(/^(.*[\\/])/, "");
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
const repInstagram = computed(() => {
|
|
||||||
const data = props.rep.acteur.adresses.adresse.find(
|
|
||||||
(adr) => adr["typeLibelle"] === "Instagram"
|
|
||||||
);
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
const repLinkedin = computed(() => {
|
|
||||||
const data = props.rep.acteur.adresses.adresse.find(
|
|
||||||
(adr) => adr["typeLibelle"] === "Linkedin"
|
|
||||||
);
|
|
||||||
if (data) {
|
|
||||||
data.valElec = String(data.valElec).replace(/^(.*[\\/])/, "");
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
|
|
||||||
const regionBgFile = computed(() => {
|
|
||||||
if (
|
|
||||||
repMandate.value?.election?.lieu.departement ===
|
|
||||||
"Français établis hors de France"
|
|
||||||
) {
|
|
||||||
return `regions/fr-etranger-${String(
|
|
||||||
repMandate.value?.election?.lieu.numCirco
|
|
||||||
)}.svg`;
|
|
||||||
} else {
|
|
||||||
return `regions/${String(repMandate.value?.election?.lieu.region)
|
|
||||||
.toLocaleLowerCase()
|
|
||||||
.replace(/\s/g, "-")}.svg`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<section class="py-8 md:py-0 w-96 max-w-full">
|
|
||||||
<header class="relative">
|
|
||||||
<div class="text-center">
|
|
||||||
<small class="text-base font-bold"> Votre député·e est... </small>
|
|
||||||
</div>
|
|
||||||
<figure class="mt-4 mx-auto w-44 h-44 rounded-full overflow-hidden">
|
|
||||||
<img
|
|
||||||
:src="repImage"
|
|
||||||
:alt="repFullName"
|
|
||||||
class="w-full h-full object-contain"
|
|
||||||
/>
|
|
||||||
</figure>
|
|
||||||
|
|
||||||
<h1 class="mt-4 text-center font-bold text-3xl">
|
|
||||||
{{ repFullName }}
|
|
||||||
</h1>
|
|
||||||
<div
|
|
||||||
v-if="repPoliticalParty"
|
|
||||||
class="text-center font-bold"
|
|
||||||
:style="`color: ${repPoliticalParty.organe.couleurAssociee}`"
|
|
||||||
>
|
|
||||||
{{ repPoliticalParty.organe.libelle }}
|
|
||||||
</div>
|
|
||||||
<h2 class="mt-2 text-center font-bold text-xl">
|
|
||||||
{{ repMandate?.election?.lieu.departement }} -
|
|
||||||
{{ repMandate?.election?.lieu.numCirco }}e circonscription
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<img
|
|
||||||
:src="regionBgFile"
|
|
||||||
class="absolute top-0 left-0 w-full h-full object-contain select-none -z-20 pointer-events-none"
|
|
||||||
/>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<footer class="mt-8">
|
|
||||||
<div class="mt-4 text-center">
|
|
||||||
<RepButton
|
|
||||||
:href="`https://www.assemblee-nationale.fr/dyn/deputes/${rep.acteur.uid['#text']}`"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
:style="'btn-red'"
|
|
||||||
>
|
|
||||||
<font-awesome-icon :icon="['fass', 'landmark']" size="lg" />
|
|
||||||
<span>Fiche Assemblée</span>
|
|
||||||
</RepButton>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<menu
|
|
||||||
class="mt-4 flex flex-col gap-y-4 md:justify-center md:flex-row md:gap-x-3 md:gap-y-0"
|
|
||||||
>
|
|
||||||
<li v-if="repTwitter">
|
|
||||||
<RepButton
|
|
||||||
:href="`https://twitter.com/${repTwitter.valElec}`"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
:style="'btn-twitter'"
|
|
||||||
>
|
|
||||||
<font-awesome-icon :icon="['fab', 'twitter']" size="lg" />
|
|
||||||
<span>Twitter</span>
|
|
||||||
</RepButton>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li v-if="repFacebook">
|
|
||||||
<RepButton
|
|
||||||
:href="`https://www.facebook.com/${repFacebook.valElec}`"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
:style="'btn-facebook'"
|
|
||||||
>
|
|
||||||
<font-awesome-icon :icon="['fab', 'facebook']" size="lg" />
|
|
||||||
<span>Facebook</span>
|
|
||||||
</RepButton>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li v-if="repLinkedin">
|
|
||||||
<RepButton
|
|
||||||
:href="`https://www.linkedin.com/${repLinkedin.valElec}`"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
:style="'btn-linkedin'"
|
|
||||||
>
|
|
||||||
<font-awesome-icon :icon="['fab', 'linkedin']" size="lg" />
|
|
||||||
<span>Linkedin</span>
|
|
||||||
</RepButton>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li v-if="repInstagram">
|
|
||||||
<RepButton
|
|
||||||
:href="`https://www.instagram.com/${repInstagram.valElec}`"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
:style="'btn-instagram'"
|
|
||||||
>
|
|
||||||
<font-awesome-icon :icon="['fab', 'instagram']" size="lg" />
|
|
||||||
<span>Instagram</span>
|
|
||||||
</RepButton>
|
|
||||||
</li>
|
|
||||||
</menu>
|
|
||||||
</footer>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<template>
|
|
||||||
<nav class="bg-slate-900">
|
|
||||||
<div class="container py-4">Mon Député</div>
|
|
||||||
</nav>
|
|
||||||
</template>
|
|
||||||
45
src/main.ts
45
src/main.ts
@@ -1,45 +0,0 @@
|
|||||||
import { createApp } from "vue";
|
|
||||||
import { createPinia } from "pinia";
|
|
||||||
|
|
||||||
import App from "./App.vue";
|
|
||||||
import router from "./router";
|
|
||||||
|
|
||||||
import "./assets/main.css";
|
|
||||||
|
|
||||||
import { library } from "@fortawesome/fontawesome-svg-core";
|
|
||||||
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
|
||||||
import {
|
|
||||||
faTwitter,
|
|
||||||
faFacebook,
|
|
||||||
faLinkedin,
|
|
||||||
faInstagram,
|
|
||||||
} from "@fortawesome/free-brands-svg-icons";
|
|
||||||
import {
|
|
||||||
faLandmark,
|
|
||||||
faLocationDot,
|
|
||||||
faSpinner,
|
|
||||||
faSquare,
|
|
||||||
faSquareCheck,
|
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
|
||||||
|
|
||||||
library.add(
|
|
||||||
faTwitter,
|
|
||||||
faFacebook,
|
|
||||||
faLinkedin,
|
|
||||||
faInstagram,
|
|
||||||
faLandmark,
|
|
||||||
faLocationDot,
|
|
||||||
faSpinner,
|
|
||||||
faSquare,
|
|
||||||
faSquareCheck
|
|
||||||
);
|
|
||||||
|
|
||||||
const app = createApp(App);
|
|
||||||
|
|
||||||
app.use(createPinia());
|
|
||||||
app.use(router);
|
|
||||||
|
|
||||||
app.component("font-awesome-icon", FontAwesomeIcon);
|
|
||||||
|
|
||||||
app.mount("#app");
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
export interface Organisation {
|
|
||||||
organe: {
|
|
||||||
"@xmlns": string;
|
|
||||||
"@xmlns:xsi": string;
|
|
||||||
"@xsi:type": string;
|
|
||||||
uid: string;
|
|
||||||
codeType: string;
|
|
||||||
libelle: string;
|
|
||||||
libelleEdition: string;
|
|
||||||
libelleAbrege: string;
|
|
||||||
libelleAbrev: string;
|
|
||||||
viMoDe: ViMoDe;
|
|
||||||
organeParent: null;
|
|
||||||
chambre: null;
|
|
||||||
regime: string;
|
|
||||||
legislature: string;
|
|
||||||
secretariat: Secretariat;
|
|
||||||
positionPolitique: string;
|
|
||||||
preseance: string;
|
|
||||||
couleurAssociee: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Secretariat {
|
|
||||||
secretaire01: null;
|
|
||||||
secretaire02: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ViMoDe {
|
|
||||||
dateDebut: Date;
|
|
||||||
dateAgrement: null;
|
|
||||||
dateFin: null;
|
|
||||||
}
|
|
||||||
@@ -1,146 +0,0 @@
|
|||||||
export interface Depute {
|
|
||||||
acteur: Acteur;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Acteur {
|
|
||||||
"@xmlns:xsi": string;
|
|
||||||
uid: Uid;
|
|
||||||
etatCivil: EtatCivil;
|
|
||||||
profession: Profession;
|
|
||||||
uri_hatvp: string;
|
|
||||||
adresses: Adresses;
|
|
||||||
mandats: Mandats;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Adresses {
|
|
||||||
adresse: { [key: string]: null | string }[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EtatCivil {
|
|
||||||
ident: Ident;
|
|
||||||
infoNaissance: InfoNaissance;
|
|
||||||
dateDeces: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Ident {
|
|
||||||
civ: string;
|
|
||||||
prenom: string;
|
|
||||||
nom: string;
|
|
||||||
alpha: string;
|
|
||||||
trigramme: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InfoNaissance {
|
|
||||||
dateNais: Date;
|
|
||||||
villeNais: string;
|
|
||||||
depNais: string;
|
|
||||||
paysNais: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Mandats {
|
|
||||||
mandat: Mandat[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Mandat {
|
|
||||||
"@xsi:type": XsiType;
|
|
||||||
uid: string;
|
|
||||||
acteurRef: Text;
|
|
||||||
legislature: null | string;
|
|
||||||
typeOrgane: string;
|
|
||||||
dateDebut: Date;
|
|
||||||
datePublication: Date | null;
|
|
||||||
dateFin: Date | null;
|
|
||||||
preseance: string;
|
|
||||||
nominPrincipale: string;
|
|
||||||
infosQualite: InfosQualite;
|
|
||||||
organes: Organes;
|
|
||||||
suppleants?: Suppleants | null;
|
|
||||||
libelle?: null;
|
|
||||||
missionSuivanteRef?: null;
|
|
||||||
missionPrecedenteRef?: null;
|
|
||||||
chambre?: null;
|
|
||||||
election?: Election;
|
|
||||||
mandature?: Mandature;
|
|
||||||
collaborateurs?: Collaborateurs;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum XsiType {
|
|
||||||
MandatAvecSuppleantType = "MandatAvecSuppleant_Type",
|
|
||||||
MandatMissionType = "MandatMission_Type",
|
|
||||||
MandatParlementaireType = "MandatParlementaire_type",
|
|
||||||
MandatSimpleType = "MandatSimple_Type",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum Text {
|
|
||||||
Pa794094 = "PA794094",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Collaborateurs {
|
|
||||||
collaborateur: Collaborateur[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Collaborateur {
|
|
||||||
qualite: string;
|
|
||||||
prenom: string;
|
|
||||||
nom: string;
|
|
||||||
dateDebut: null;
|
|
||||||
dateFin: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Election {
|
|
||||||
lieu: Lieu;
|
|
||||||
causeMandat: string;
|
|
||||||
refCirconscription: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Lieu {
|
|
||||||
region: string;
|
|
||||||
regionType: string;
|
|
||||||
departement: string;
|
|
||||||
numDepartement: string;
|
|
||||||
numCirco: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface InfosQualite {
|
|
||||||
codeQualite: string;
|
|
||||||
libQualite: string;
|
|
||||||
libQualiteSex: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Mandature {
|
|
||||||
datePriseFonction: Date;
|
|
||||||
causeFin: null;
|
|
||||||
premiereElection: string;
|
|
||||||
placeHemicycle: string;
|
|
||||||
matriculeVote: string;
|
|
||||||
mandatRemplaceRef: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Organes {
|
|
||||||
organeRef: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Suppleants {
|
|
||||||
suppleant: Suppleant;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Suppleant {
|
|
||||||
dateDebut: Date;
|
|
||||||
dateFin: null;
|
|
||||||
suppleantRef: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Profession {
|
|
||||||
libelleCourant: string;
|
|
||||||
socProcINSEE: SocProcINSEE;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SocProcINSEE {
|
|
||||||
catSocPro: string;
|
|
||||||
famSocPro: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Uid {
|
|
||||||
"@xsi:type": string;
|
|
||||||
"#text": Text;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
|
||||||
import HomeView from "../views/HomeView.vue";
|
|
||||||
|
|
||||||
const router = createRouter({
|
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
|
||||||
routes: [
|
|
||||||
{
|
|
||||||
path: "/",
|
|
||||||
name: "home",
|
|
||||||
component: HomeView,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import type { Depute } from "@/models/rep";
|
|
||||||
import { defineStore } from "pinia";
|
|
||||||
import { ref } from "vue";
|
|
||||||
|
|
||||||
const apiUrl = import.meta.env.VITE_API_URL;
|
|
||||||
|
|
||||||
export const useRepStore = defineStore("repStore", () => {
|
|
||||||
const currentRep = ref<Depute | null>(null);
|
|
||||||
|
|
||||||
async function getRep(lon: number, lat: number): Promise<Depute> {
|
|
||||||
return fetch(`${apiUrl}/rep?lat=${lat}&lon=${lon}`).then(async (res) => {
|
|
||||||
if (res.ok) {
|
|
||||||
return res.json();
|
|
||||||
} else {
|
|
||||||
throw res.json().then((res) => new Error(res.message));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setRep(rep: Depute) {
|
|
||||||
currentRep.value = rep;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { getRep, setRep, currentRep };
|
|
||||||
});
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import RepForm from "@/components/RepForm.vue";
|
|
||||||
import RepInfo from "@/components/RepInfo.vue";
|
|
||||||
import { useRepStore } from "@/stores/repStore";
|
|
||||||
import { storeToRefs } from "pinia";
|
|
||||||
|
|
||||||
const { currentRep } = storeToRefs(useRepStore());
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<main class="container py-4">
|
|
||||||
<Transition name="fade" mode="out-in">
|
|
||||||
<RepForm v-if="!currentRep" />
|
|
||||||
<Suspense v-else>
|
|
||||||
<RepInfo :rep="currentRep" />
|
|
||||||
</Suspense>
|
|
||||||
</Transition>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.fade-enter-from {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.fade-enter-to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.fade-enter-active {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
.fade-leave-from {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
.fade-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.fade-leave-active {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,74 +1,86 @@
|
|||||||
|
const animate = require("tailwindcss-animate")
|
||||||
|
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
|
darkMode: ["class"],
|
||||||
|
safelist: ["dark"],
|
||||||
|
prefix: "",
|
||||||
|
|
||||||
theme: {
|
theme: {
|
||||||
fontFamily: {
|
|
||||||
sans: ["Open Sans", "system-ui", "Lato", "sans-serif"],
|
|
||||||
},
|
|
||||||
container: {
|
container: {
|
||||||
padding: "2rem",
|
|
||||||
center: true,
|
center: true,
|
||||||
|
padding: "2rem",
|
||||||
|
screens: {
|
||||||
|
"2xl": "1400px",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
twitter: {
|
border: "hsl(var(--border))",
|
||||||
DEFAULT: "#1DA1F2",
|
input: "hsl(var(--input))",
|
||||||
50: "#CBE9FC",
|
ring: "hsl(var(--ring))",
|
||||||
100: "#B7E1FB",
|
background: "hsl(var(--background))",
|
||||||
200: "#91D1F9",
|
foreground: "hsl(var(--foreground))",
|
||||||
300: "#6AC1F6",
|
primary: {
|
||||||
400: "#44B1F4",
|
DEFAULT: "hsl(var(--primary))",
|
||||||
500: "#1DA1F2",
|
foreground: "hsl(var(--primary-foreground))",
|
||||||
600: "#0C82CB",
|
|
||||||
700: "#096096",
|
|
||||||
800: "#063E61",
|
|
||||||
900: "#031C2C",
|
|
||||||
950: "#010B12",
|
|
||||||
},
|
},
|
||||||
facebook: {
|
secondary: {
|
||||||
DEFAULT: "#4267B2",
|
DEFAULT: "hsl(var(--secondary))",
|
||||||
50: "#C3CFE9",
|
foreground: "hsl(var(--secondary-foreground))",
|
||||||
100: "#B4C4E3",
|
|
||||||
200: "#96ACD8",
|
|
||||||
300: "#7894CD",
|
|
||||||
400: "#5B7DC2",
|
|
||||||
500: "#4267B2",
|
|
||||||
600: "#334F89",
|
|
||||||
700: "#243860",
|
|
||||||
800: "#142037",
|
|
||||||
900: "#05080E",
|
|
||||||
950: "#000000",
|
|
||||||
},
|
},
|
||||||
instagram: {
|
destructive: {
|
||||||
DEFAULT: "#C13584",
|
DEFAULT: "hsl(var(--destructive))",
|
||||||
50: "#EEC0DA",
|
foreground: "hsl(var(--destructive-foreground))",
|
||||||
100: "#E9B0D0",
|
|
||||||
200: "#E090BD",
|
|
||||||
300: "#D870AA",
|
|
||||||
400: "#CF5098",
|
|
||||||
500: "#C13584",
|
|
||||||
600: "#952966",
|
|
||||||
700: "#691D48",
|
|
||||||
800: "#3D112A",
|
|
||||||
900: "#11050C",
|
|
||||||
950: "#000000",
|
|
||||||
},
|
},
|
||||||
linkedin: {
|
muted: {
|
||||||
DEFAULT: "#0072B1",
|
DEFAULT: "hsl(var(--muted))",
|
||||||
50: "#6ACAFF",
|
foreground: "hsl(var(--muted-foreground))",
|
||||||
100: "#55C3FF",
|
|
||||||
200: "#2CB4FF",
|
|
||||||
300: "#04A6FF",
|
|
||||||
400: "#008CDA",
|
|
||||||
500: "#0072B1",
|
|
||||||
600: "#004E79",
|
|
||||||
700: "#002A41",
|
|
||||||
800: "#000609",
|
|
||||||
900: "#000000",
|
|
||||||
950: "#000000",
|
|
||||||
},
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: "hsl(var(--accent))",
|
||||||
|
foreground: "hsl(var(--accent-foreground))",
|
||||||
|
},
|
||||||
|
popover: {
|
||||||
|
DEFAULT: "hsl(var(--popover))",
|
||||||
|
foreground: "hsl(var(--popover-foreground))",
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
DEFAULT: "hsl(var(--card))",
|
||||||
|
foreground: "hsl(var(--card-foreground))",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
xl: "calc(var(--radius) + 4px)",
|
||||||
|
lg: "var(--radius)",
|
||||||
|
md: "calc(var(--radius) - 2px)",
|
||||||
|
sm: "calc(var(--radius) - 4px)",
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
"accordion-down": {
|
||||||
|
from: { height: 0 },
|
||||||
|
to: { height: "var(--radix-accordion-content-height)" },
|
||||||
|
},
|
||||||
|
"accordion-up": {
|
||||||
|
from: { height: "var(--radix-accordion-content-height)" },
|
||||||
|
to: { height: 0 },
|
||||||
|
},
|
||||||
|
"collapsible-down": {
|
||||||
|
from: { height: 0 },
|
||||||
|
to: { height: 'var(--radix-collapsible-content-height)' },
|
||||||
|
},
|
||||||
|
"collapsible-up": {
|
||||||
|
from: { height: 'var(--radix-collapsible-content-height)' },
|
||||||
|
to: { height: 0 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
"accordion-down": "accordion-down 0.2s ease-out",
|
||||||
|
"accordion-up": "accordion-up 0.2s ease-out",
|
||||||
|
"collapsible-down": "collapsible-down 0.2s ease-in-out",
|
||||||
|
"collapsible-up": "collapsible-up 0.2s ease-in-out",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [animate],
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "@vue/tsconfig/tsconfig.node.json",
|
|
||||||
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*"],
|
|
||||||
"compilerOptions": {
|
|
||||||
"composite": true,
|
|
||||||
"types": ["node"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,4 @@
|
|||||||
{
|
{
|
||||||
"extends": "@vue/tsconfig/tsconfig.web.json",
|
// https://nuxt.com/docs/guide/concepts/typescript
|
||||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
"compilerOptions": {
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.config.json"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
import { fileURLToPath, URL } from "node:url";
|
|
||||||
|
|
||||||
import { defineConfig } from "vite";
|
|
||||||
import vue from "@vitejs/plugin-vue";
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [vue()],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user