mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-11 17:26:32 +02:00
feat: add settings page for database, OpenRouter, score, theme, and display density configurations.
This commit is contained in:
1 parent
359d196c4d
commit
cfd079fbf5
7 files changed
+41
-28
No files matched your search
@@ -9,8 +9,6 @@ import { useDbSettingsStore } from "@/features/settings/store/use-db-settings-st
|
||||
import { testDatabaseConnection, saveDatabaseSettings, getSavedDatabaseConfig } from "@/features/settings/actions";
|
||||
import { useEffect } from "react";
|
||||
import { UserManagement } from "@/features/admin/components/user-management";
|
||||
import { auth } from "@/lib/auth";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
interface OpenRouterModel { id: string; name: string; free: boolean; }
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ En analysant les données de ventes fournies, génère une recommandation de gam
|
||||
Critères de pondération et Règles Métier Strictes :
|
||||
1. Normalisation Totale (Base 2 magasins) : TOUTES les statistiques fournies sont PONDÉRÉES par 2 si le produit n'est au catalogue que de 1 magasin.
|
||||
2. Segmentation par Rayon (Univers) : Privilégie la comparaison "Intra-Rayon". Un produit doit être performant par rapport aux standards de son propre Rayon (Niveau 2).
|
||||
3. Seuil "Permanent" (A) : Pour être A, un produit doit avoir un volume PONDÉRÉ significatif (ex: > 30-50 unités/an).
|
||||
4. Seuil "Sortie" (Z) : Un produit avec moins de 10 unités pondérées par an et un CA faible est un candidat à la sortie (Z).
|
||||
5. Équilibre : Un produit "A" doit justifier sa place par son flux OU sa rentabilité brute.
|
||||
3. Score de Performance Global (0-10) : Un score > 7 est un indicateur fort pour "Permanent" (A). Un score < 3 est un indicateur fort pour "Sortie" (Z).
|
||||
4. Régularité des Ventes (0-12 mois) : Un produit avec une vente régulière (> 8 mois/an) est un candidat idéal pour "Permanent" (A). Une régularité faible (< 3 mois) couplée à un volume total faible indique une "Sortie" (Z).
|
||||
5. Équilibre : Un produit "A" doit justifier sa place par son flux, sa rentabilité brute OU son score global.
|
||||
|
||||
Ta réponse doit être courte, directe et sans complaisance.
|
||||
Format impératif : "[Recommandation]: [Justification courte]"`;
|
||||
@@ -38,8 +38,10 @@ Benchmarks Rayon ("${p.libelleNiveau2}") :
|
||||
Rayon : ${p.libelleNiveau2 || "Non classé"}
|
||||
Gamme actuelle : ${p.codeGamme ?? "Non définie"}
|
||||
${volumeInfo}${benchmarks}
|
||||
Indicateurs Clés :
|
||||
- Marge : ${p.tauxMarge.toFixed(1)}%
|
||||
Indicateurs de Performance :
|
||||
- Score Global App : ${p.score.toFixed(1)}/10
|
||||
- Régularité des ventes : ${p.regularityScore}/12 mois
|
||||
- Marge brute : ${p.tauxMarge.toFixed(1)}%
|
||||
- Historique mensuel (Pondéré) : ${monthlySummary}
|
||||
|
||||
Quelle est ta recommandation (A, C ou Z) et pourquoi ?`;
|
||||
|
||||
@@ -15,6 +15,8 @@ export interface ProductAnalysisInput {
|
||||
storeCount: number;
|
||||
sales12m: Record<string, number>;
|
||||
codeGamme: string | null;
|
||||
score: number;
|
||||
regularityScore: number;
|
||||
}
|
||||
|
||||
export interface AnalysisResult {
|
||||
|
||||
@@ -80,6 +80,8 @@ export function BulkAiAnalyzer() {
|
||||
Object.entries(r.sales12m || {}).map(([month, val]) => [month, val * weight])
|
||||
),
|
||||
codeGamme: r.codeGamme || null,
|
||||
score: r.score || 0,
|
||||
regularityScore: Object.values(r.sales12m || {}).filter(v => v > 0).length,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { NextAuthConfig } from "next-auth";
|
||||
|
||||
export const authConfig = {
|
||||
pages: {
|
||||
signIn: "/login",
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, user }) {
|
||||
if (user) {
|
||||
token.role = (user as any).role;
|
||||
token.id = user.id;
|
||||
}
|
||||
return token;
|
||||
},
|
||||
async session({ session, token }) {
|
||||
if (session.user) {
|
||||
(session.user as any).role = token.role as string;
|
||||
(session.user as any).id = token.id as string;
|
||||
}
|
||||
return session;
|
||||
},
|
||||
},
|
||||
providers: [], // Les providers seront ajoutés dans auth.ts
|
||||
} satisfies NextAuthConfig;
|
||||
+2
-20
@@ -5,8 +5,10 @@ import { users } from "@/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { verifyPassword } from "@/features/auth/logic/auth-logic";
|
||||
import { ensureAdminExists } from "@/features/auth/logic/seed-admin";
|
||||
import { authConfig } from "./auth.config";
|
||||
|
||||
export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
...authConfig,
|
||||
providers: [
|
||||
Credentials({
|
||||
name: "Credentials",
|
||||
@@ -15,7 +17,6 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
password: { label: "Mot de passe", type: "password" }
|
||||
},
|
||||
async authorize(credentials) {
|
||||
// S'assure que le compte admin par défaut existe
|
||||
await ensureAdminExists();
|
||||
|
||||
if (!credentials?.username || !credentials?.password) return null;
|
||||
@@ -42,23 +43,4 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
|
||||
}
|
||||
})
|
||||
],
|
||||
callbacks: {
|
||||
async jwt({ token, user }) {
|
||||
if (user) {
|
||||
token.role = (user as any).role;
|
||||
token.id = user.id;
|
||||
}
|
||||
return token;
|
||||
},
|
||||
async session({ session, token }) {
|
||||
if (session.user) {
|
||||
(session.user as any).role = token.role as string;
|
||||
(session.user as any).id = token.id as string;
|
||||
}
|
||||
return session;
|
||||
},
|
||||
},
|
||||
pages: {
|
||||
signIn: "/login",
|
||||
}
|
||||
});
|
||||
+4
-1
@@ -1,6 +1,9 @@
|
||||
import { auth } from "@/lib/auth";
|
||||
import NextAuth from "next-auth";
|
||||
import { authConfig } from "@/lib/auth.config";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const { auth } = NextAuth(authConfig);
|
||||
|
||||
export default auth((req) => {
|
||||
const isLoggedIn = !!req.auth;
|
||||
const { nextUrl } = req;
|
||||
|
||||
Reference in new issue
Block a user