Skip to content
Open
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
Binary file added bin/crm.exe
Binary file not shown.
11 changes: 11 additions & 0 deletions cmd/crm/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

import (
"github.com/armanceau/mini-crm/internal/app"
"github.com/armanceau/mini-crm/internal/storage"
)

func main() {
var store storage.Storer = storage.NewJsonStore("./")
app.Run(store)
}
143 changes: 143 additions & 0 deletions internal/app/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package app

import (
"bufio"
"flag"
"fmt"
"os"
"strconv"
"strings"

"github.com/armanceau/mini-crm/internal/storage"
)

func Run(store storage.Storer) {
nomFlag := flag.String("nom", "", "Nom du contact à ajouter")
emailFlag := flag.String("email", "", "Email du contact à ajouter")

flag.Parse()
if *nomFlag != "" && *emailFlag != "" {
contact := storage.Contact{
Nom: strings.TrimSpace(*nomFlag),
Email: strings.TrimSpace(*emailFlag),
}
c := store.Ajouter(contact)
fmt.Println("Contact ajouté via flag :", c.ID, c.Nom, c.Email)
return
}
menu(store)
}

func menu(store storage.Storer) {
reader := bufio.NewReader(os.Stdin)

for {
fmt.Println("\n--- cli contact ---")
fmt.Println("1. Ajouter un contact")
fmt.Println("2. Liste des contacts")
fmt.Println("3. Supprimer un contact")
fmt.Println("4. Mettre à jour un contact")
fmt.Println("5. Quitter")
input, _ := reader.ReadString('\n')
choix := strings.TrimSpace(input)

switch choix {
case "1":
ajouterContact(reader, store)
case "2":
listeContacts(store)
case "3":
supprimerContact(reader, store)
case "4":
mettreAJourContact(reader, store)
case "5":
fmt.Println("À bientôt 👋")
return
default:
fmt.Println("Choix invalide")
}
}

}

func New(ID int, Nom string, Email string) storage.Contact {
contact := storage.Contact{ID: ID, Nom: Nom, Email: Email}
return contact
}

func ajouterContact(reader *bufio.Reader, store storage.Storer) {
fmt.Print("Nom : ")
nom, _ := reader.ReadString('\n')
fmt.Print("Email : ")
email, _ := reader.ReadString('\n')

contact := storage.Contact{
Nom: strings.TrimSpace(nom),
Email: strings.TrimSpace(email),
}

c := store.Ajouter(contact)
fmt.Println("Contact ajouté ✅ :", c.ID, c.Nom, c.Email)
}

func listeContacts(store storage.Storer) {
contacts := store.Lister()
if len(contacts) == 0 {
fmt.Println("Aucun contact trouvé ❌")
return
}
for _, c := range contacts {
fmt.Printf("[%d] %s - %s\n", c.ID, c.Nom, c.Email)
}
}

func supprimerContact(reader *bufio.Reader, store storage.Storer) {
fmt.Print("ID du contact à supprimer : ")
input, _ := reader.ReadString('\n')
id, err := strconv.Atoi(strings.TrimSpace(input))
if err != nil {
fmt.Println("ID invalide")
return
}
if store.Supprimer(id) {
fmt.Println("Contact supprimé ✅")
} else {
fmt.Println("Contact introuvable ❌")
}
}

func mettreAJourContact(reader *bufio.Reader, store storage.Storer) {
fmt.Print("ID du contact à mettre à jour : ")
input, _ := reader.ReadString('\n')
id, err := strconv.Atoi(strings.TrimSpace(input))
if err != nil {
fmt.Println("ID invalide")
return
}

contact, ok := store.Recuperer(id)
if !ok {
fmt.Println("Contact introuvable ❌")
return
}

fmt.Print("Nouveau nom (laisser vide pour garder actuel) : ")
nom, _ := reader.ReadString('\n')
nom = strings.TrimSpace(nom)
if nom != "" {
contact.Nom = nom
}

fmt.Print("Nouvel email (laisser vide pour garder actuel) : ")
email, _ := reader.ReadString('\n')
email = strings.TrimSpace(email)
if email != "" {
contact.Email = email
}

if c, ok := store.MettreAJour(contact); ok {
fmt.Println("Contact mis à jour ✅ :", c.ID, c.Nom, c.Email)
} else {
fmt.Println("Erreur lors de la mise à jour ❌")
}
}
68 changes: 68 additions & 0 deletions internal/storage/memory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package storage

import (
"encoding/json"
"os"
)

type JsonStore struct {
filePath string
contacts map[int]Contact
nextID int
}

func NewJsonStore(filePath string) *JsonStore {
return &JsonStore{
filePath: filePath,
contacts: make(map[int]Contact),
nextID: 1,
}
}

func (j *JsonStore) save() {
data, _ := json.MarshalIndent(j.contacts, "", " ")
os.WriteFile("contacts.json", data, 0644)
}

func (j *JsonStore) Ajouter(c Contact) Contact {
c.ID = j.nextID
j.contacts[j.nextID] = c
j.nextID++
j.save()
return c
}

func (j *JsonStore) Lister() []Contact {
var list []Contact
for _, c := range j.contacts {
list = append(list, c)
}
return list
}

func (j *JsonStore) Supprimer(ID int) bool {
if _, ok := j.contacts[ID]; ok {
delete(j.contacts, ID)
j.save()
return true
}
return false
}

func (j *JsonStore) Recuperer(ID int) (Contact, bool) {
c, ok := j.contacts[ID]
return c, ok
}

func (j *JsonStore) MettreAJour(c Contact) (Contact, bool) {
if _, ok := j.contacts[c.ID]; ok {
j.contacts[c.ID] = c
j.save()
return c, true
}
return Contact{}, false
}

func (j *JsonStore) NextID() int {
return j.nextID
}
22 changes: 22 additions & 0 deletions internal/storage/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package storage

import "fmt"

type Contact struct {
ID int `json:"contact_id"`
Nom string `json:"nom"`
Email string `json:"email"`
}

type Storer interface {
Ajouter(c Contact) Contact
Lister() []Contact
Supprimer(ID int) bool
MettreAJour(c Contact) (Contact, bool)
Recuperer(ID int) (Contact, bool)
NextID() int
}

var ErrContactNotFound = func(id int) error {
return fmt.Errorf("Contact avec l'ID non trouvé")
}
File renamed without changes.
File renamed without changes.