Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .gitea/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Build Check

on:
push:

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build
24 changes: 24 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Build Check

on:
push:

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Run build
run: npm run build
7 changes: 0 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@

<h1 align="center">Klickbee CRM</h1>

<h1 align="center">

Due to GitHub Politics and the fact that [JMauclair](https://github.com/JMauclair) has been recently suspended for no reasons, all our projects will be only on [Stralya Gitea](https://git.stralya.com/Klickbee/klickbee-crm)

</h1>

<p align="center">
<a href="https://app.supademo.com/demo/cmhvs1cli17ry17y0j39gcp3n?utm_source=github">
<img src="https://img.shields.io/badge/A%20demo%20is%20better%20than%20a%20thousand%20words-black?style=for-the-badge&logo=Supabase&logoColor=white" alt="A demo is better than a thousand words" />
Expand Down
2 changes: 1 addition & 1 deletion src/components/detailPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ const DetailModal: React.FC<DetailModalProps> = ({
) : (
<Edit size={15}/>
)}
{editLabel || "Edit Deal"}
{editLabel || "Edit Task"}
</Button>
)}
{onReschedule && (
Expand Down
2 changes: 1 addition & 1 deletion src/components/layout/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default function NavBar() {
case 'settings/ai':
return {
title: 'AI Settings',
description: 'Edit the content and SEO of your page.'
description: 'Setup AI settings for your account.'
};
case 'settings/users':
return {
Expand Down
83 changes: 76 additions & 7 deletions src/components/ui/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,92 @@
import * as React from "react";
import * as React from "react"

import { cn } from "@/libs/utils";

export function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
function Card({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card"
className={cn(
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
className
)}
{...props}
/>
)
}

function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-header"
className={cn(
"rounded-2xl border border-gray-200 bg-white shadow-sm",
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
className
)}
{...props}
/>
);
)
}

export function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
className={cn("p-2", className)}
data-slot="card-title"
className={cn("leading-none font-semibold", className)}
{...props}
/>
);
)
}

function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}

function CardAction({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-action"
className={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
)}
{...props}
/>
)
}

function CardContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-content"
className={cn("px-6", className)}
{...props}
/>
)
}

function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-footer"
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
{...props}
/>
)
}

export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
}
9 changes: 4 additions & 5 deletions src/components/ui/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import React, { useEffect, useRef, useState } from 'react'
import { ChevronUp, ChevronDown, MoreHorizontal } from 'lucide-react'
import React, {useEffect, useRef, useState} from 'react'
import {MoreHorizontal} from 'lucide-react'
import AvatarInitials from '@/components/ui/AvatarInitials'
import Loading from '@/components/ui/Loading'

Expand Down Expand Up @@ -67,8 +67,7 @@ const Badge: React.FC<{
const formatCellValue = (value: any) => {
if (value === null || value === undefined) return '-'
if (typeof value === 'string' && value.trim() === '') return '-'
const str = String(value)
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()
return String(value)
}

// Table Row Component
Expand Down Expand Up @@ -115,7 +114,7 @@ const TableRow = <T,>({
{columns.map((column) => (
<td
key={column.key}
className="px-6 py-3 text-sm text-[var(--foreground)] whitespace-nowrap capitalize"
className="px-6 py-3 text-sm text-[var(--foreground)] whitespace-nowrap"
style={{ width: column.width }}
>
{column.avatar ? (
Expand Down
1 change: 0 additions & 1 deletion src/feature/auth/api/apiUsers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {prisma} from "@/libs/prisma";

type Params = { params: Promise<{ id: string }> };


export async function GET(req: NextRequest, context: Params) {
try {
const session = await getServerSession(authOptions);
Expand Down
32 changes: 17 additions & 15 deletions src/feature/companies/components/CompaniesForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client"

import type React from "react"
import {useState, useEffect} from "react"
import React, {useEffect} from "react"
import {useState} from "react"
import {useForm} from "react-hook-form"
import {zodResolver} from "@hookform/resolvers/zod"
import * as z from "zod"
Expand All @@ -12,7 +12,7 @@ import SearchableDropdown from "@/components/ui/SearchableDropdown"
import {Company} from "../types/types"
import CustomDropdown from "@/components/ui/CustomDropdown"
import {validateOwner} from "@/feature/forms/lib/formValidation"
import {useCompaniesStore} from "@/feature/companies/stores/useCompaniesStore";
import {getSession, useSession} from "next-auth/react";

type CompanyFormValues = z.infer<typeof zodSchema>;

Expand All @@ -28,15 +28,13 @@ const zodSchema = z.object({
phone: z
.union([
z.literal(""), // chaîne vide acceptée
z.string().regex(/^\+?[0-9]{6,15}$/, { message: "Invalid phone number" })
z.string().regex(/^\+?[0-9]{6,15}$/, {message: "Invalid phone number"})
])
.optional(),
owner: z
.string()
.optional()
.refine(async (id) => !id || (await validateOwner(id)), {
message: "User does not exist",
}),
.trim()
.refine(async (id) => await validateOwner(id), {message: "User does not exist"}),
tags: z.array(z.string().min(1)).max(10, "Up to 10 tags allowed").optional(),
assign: z.array(z.string().min(1)).max(10, "Up to 10 assignments allowed").optional(),
notes: z.string().optional(),
Expand Down Expand Up @@ -75,10 +73,10 @@ export default function CompaniesForm({
const [assignInput, setAssignInput] = useState("")
const [uploading, setUploading] = useState(false)
const [uploadedFiles, setUploadedFiles] = useState<any[]>([])

const {data: userData} = useSession();

// 🧩 Compute initial values like avant
const getInitialValues = (): CompanyFormValues => {
const getInitialValues = (userData: { user: { id: string } | null } | null): CompanyFormValues => {
if (mode === "edit" && initialData) {
return {
fullName: initialData.fullName || "",
Expand Down Expand Up @@ -116,8 +114,12 @@ export default function CompaniesForm({
notes: "",
files: [],
}
} else {
return {
...initialValues,
owner: userData?.user?.id || "",
}
}
return initialValues
}

const {
Expand All @@ -129,13 +131,13 @@ export default function CompaniesForm({
watch,
} = useForm<CompanyFormValues>({
resolver: zodResolver(zodSchema),
defaultValues: getInitialValues(),
defaultValues: getInitialValues(userData),
})

const values = watch()

useEffect(() => {
reset(getInitialValues())
reset(getInitialValues(userData))
}, [mode, initialData])

const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
Expand Down Expand Up @@ -237,12 +239,12 @@ export default function CompaniesForm({
setInput={setAssignInput}
/>

<FieldBlock name="owner" label="Owner">
<FieldBlock name="owner" label="Owner" error={errors.owner?.message}>
<SearchableDropdown
name="owner"
value={values.owner || ""}
options={userOptions}
onChange={(val) => setValue("owner", val)}
onChange={(val) => setValue("owner", val, {shouldValidate: true})}
placeholder="Select Owner"
showIcon={false}
maxOptions={20}
Expand Down
Loading
Loading