feat(web): lien « Buy me a coffee » (nav, réglages, funding)
- constante BUYMEACOFFEE_URL ; item de nav « Offrez-moi un café » - section support dans les Réglages + i18n EN/FR - champ `funding` dans le package.json publié ; mentions README EN/FR
This commit is contained in:
@@ -255,6 +255,12 @@ node packages/server/scripts/acceptance-p4.mjs # Web Push + commande WS `answe
|
||||
node packages/server/scripts/acceptance-p5.mjs # groupes de travail : CRUD + broadcast WS + CASCADE
|
||||
```
|
||||
|
||||
## Soutenir le projet
|
||||
|
||||
Arboretum est un projet personnel libre et auto-financé. S'il vous fait gagner du temps, vous pouvez soutenir son développement :
|
||||
|
||||
[](https://buymeacoffee.com/johanleroy)
|
||||
|
||||
## Licence
|
||||
|
||||
MIT — voir [LICENSE](LICENSE).
|
||||
|
||||
@@ -255,6 +255,12 @@ node packages/server/scripts/acceptance-p4.mjs # Web Push + WS `answer` comman
|
||||
node packages/server/scripts/acceptance-p5.mjs # work groups: CRUD + WS broadcast + CASCADE
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
Arboretum is a free, self-funded side project. If it saves you time, you can support its development:
|
||||
|
||||
[](https://buymeacoffee.com/johanleroy)
|
||||
|
||||
## License
|
||||
|
||||
MIT — see [LICENSE](LICENSE).
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
"bugs": {
|
||||
"url": "https://git.lidge.fr/johanleroy/arboretum/issues"
|
||||
},
|
||||
"funding": {
|
||||
"type": "buymeacoffee",
|
||||
"url": "https://buymeacoffee.com/johanleroy"
|
||||
},
|
||||
"keywords": [
|
||||
"git",
|
||||
"worktree",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { computed, type Component } from 'vue';
|
||||
import { useRoute, type RouteLocationRaw } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { Boxes, GitBranch, LifeBuoy, Settings, TerminalSquare } from '@lucide/vue';
|
||||
import { Boxes, Coffee, GitBranch, LifeBuoy, Settings, TerminalSquare } from '@lucide/vue';
|
||||
import { useSessionsStore } from '../stores/sessions';
|
||||
import GiteaIcon from '../components/ui/GiteaIcon.vue';
|
||||
import { REPO_SOURCE_URL } from '../lib/constants';
|
||||
import { BUYMEACOFFEE_URL, REPO_SOURCE_URL } from '../lib/constants';
|
||||
|
||||
export interface NavEntry {
|
||||
key: string;
|
||||
@@ -41,6 +41,7 @@ export function useNav() {
|
||||
{ key: 'settings', to: { name: 'settings' }, icon: Settings, label: t('nav.settings'), match: ['settings'], badge: 0 },
|
||||
{ key: 'help', to: { name: 'help' }, icon: LifeBuoy, label: t('nav.help'), match: ['help'], badge: 0 },
|
||||
{ key: 'gitea', href: REPO_SOURCE_URL, icon: GiteaIcon, label: t('nav.gitea'), match: [], badge: 0 },
|
||||
{ key: 'buymeacoffee', href: BUYMEACOFFEE_URL, icon: Coffee, label: t('nav.buymeacoffee'), match: [], badge: 0 },
|
||||
]);
|
||||
|
||||
const isActive = (match: string[]): boolean => match.includes(String(route.name));
|
||||
|
||||
@@ -182,6 +182,7 @@ export default {
|
||||
help: 'Help',
|
||||
more: 'More',
|
||||
gitea: 'Source code',
|
||||
buymeacoffee: 'Buy me a coffee',
|
||||
waiting: 'waiting',
|
||||
},
|
||||
controls: {
|
||||
@@ -364,6 +365,10 @@ export default {
|
||||
vapidContact: 'VAPID contact',
|
||||
none: 'none',
|
||||
flagHint: 'CLI flag: {flag}',
|
||||
// Support
|
||||
support: 'Support',
|
||||
supportHint: 'Arboretum is a free, self-funded side project. If it saves you time, you can support its development.',
|
||||
supportCta: 'Buy me a coffee',
|
||||
},
|
||||
help: {
|
||||
title: 'Help',
|
||||
|
||||
@@ -185,6 +185,7 @@ const fr: typeof en = {
|
||||
help: 'Aide',
|
||||
more: 'Plus',
|
||||
gitea: 'Code source',
|
||||
buymeacoffee: 'Offrez-moi un café',
|
||||
waiting: 'en attente',
|
||||
},
|
||||
controls: {
|
||||
@@ -367,6 +368,10 @@ const fr: typeof en = {
|
||||
vapidContact: 'Contact VAPID',
|
||||
none: 'aucune',
|
||||
flagHint: 'Flag CLI : {flag}',
|
||||
// Soutien
|
||||
support: 'Soutenir le projet',
|
||||
supportHint: 'Arboretum est un projet personnel libre et auto-financé. S’il vous fait gagner du temps, vous pouvez soutenir son développement.',
|
||||
supportCta: 'Offrez-moi un café',
|
||||
},
|
||||
help: {
|
||||
title: 'Aide',
|
||||
|
||||
@@ -6,3 +6,9 @@
|
||||
* tous les utilisateurs de la solution.
|
||||
*/
|
||||
export const REPO_SOURCE_URL = 'https://git.lidge.fr/johanleroy/arboretum';
|
||||
|
||||
/**
|
||||
* Lien « Buy me a coffee » affiché dans la navigation et la page Réglages.
|
||||
* En dur (pas un réglage) : page de don personnelle, identique pour tous.
|
||||
*/
|
||||
export const BUYMEACOFFEE_URL = 'https://buymeacoffee.com/johanleroy';
|
||||
|
||||
@@ -18,6 +18,15 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
/* Tailwind v4 ne met plus cursor:pointer sur les boutons → on le rétablit
|
||||
(sauf désactivés, qui gardent le curseur par défaut / not-allowed). */
|
||||
button:not(:disabled),
|
||||
[role='button']:not([aria-disabled='true']) {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@layer components {
|
||||
/* Champs : rayon unifié + anneau de focus visible (absent auparavant). */
|
||||
.input {
|
||||
|
||||
@@ -178,13 +178,31 @@
|
||||
</dl>
|
||||
<SkeletonRow v-else />
|
||||
</section>
|
||||
|
||||
<!-- Support -->
|
||||
<section class="card flex flex-col gap-3">
|
||||
<h2 class="flex items-center gap-2 text-sm font-semibold text-zinc-100">
|
||||
<Coffee :size="16" /> {{ t('settings.support') }}
|
||||
</h2>
|
||||
<p class="text-xs text-zinc-500">{{ t('settings.supportHint') }}</p>
|
||||
<div>
|
||||
<a
|
||||
:href="BUYMEACOFFEE_URL"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex h-9 items-center justify-center gap-1.5 rounded-lg border border-zinc-700 bg-zinc-800 px-3 text-sm font-medium text-zinc-200 transition-colors hover:bg-zinc-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/70 focus-visible:ring-offset-2 focus-visible:ring-offset-zinc-950"
|
||||
>
|
||||
<Coffee :size="16" /> {{ t('settings.supportCta') }}
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { Bell, BellOff, Check, Copy, Download, FolderOpen, KeyRound, Plus, RefreshCw, ScanSearch, Send, Server, Shield, SlidersHorizontal, Trash2, X } from '@lucide/vue';
|
||||
import { Bell, BellOff, Check, Coffee, Copy, Download, FolderOpen, KeyRound, Plus, RefreshCw, ScanSearch, Send, Server, Shield, SlidersHorizontal, Trash2, X } from '@lucide/vue';
|
||||
import type {
|
||||
AuditLogEntry,
|
||||
AuditLogsResponse,
|
||||
@@ -195,6 +213,7 @@ import type {
|
||||
TokensListResponse,
|
||||
} from '@arboretum/shared';
|
||||
import { api, ApiError } from '../lib/api';
|
||||
import { BUYMEACOFFEE_URL } from '../lib/constants';
|
||||
import { useSettingsStore } from '../stores/settings';
|
||||
import { usePushStore } from '../stores/push';
|
||||
import { useToastsStore } from '../stores/toasts';
|
||||
|
||||
Reference in New Issue
Block a user