Skip to content

Commit a1a303c

Browse files
committed
✨ Enhance Application Functionality and Update Configuration
- Add new dashboard method in ArticlesController to fetch article statistics for the dashboard view. - Update package.json to include a new path for enums. - Modify CORS configuration to allow all origins for improved API accessibility. - Adjust user migration to change password field to nullable and implement role-based access using enums. - Update login and register pages to replace Link components with anchor tags for better compatibility. - Refactor dashboard page to accept individual article statistics as props instead of a single stats object. - Update routes to link the dashboard to the new controller method for dynamic data rendering.
1 parent 203cc68 commit a1a303c

13 files changed

Lines changed: 161 additions & 30 deletions

File tree

app/controllers/articles_controller.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { HttpContext } from '@adonisjs/core/http'
22
import { articleValidator } from '#validators/article_validator'
33
import Article from '#models/article'
44
import { DateTime } from 'luxon'
5+
import ArticleStatsService from '#services/article_stats_service'
56

67
export default class ArticlesController {
78
async index({ inertia, request }: HttpContext) {
@@ -45,4 +46,14 @@ export default class ArticlesController {
4546

4647
return inertia.render('articles/[slug]', { article })
4748
}
49+
50+
async dashboard({ inertia }: HttpContext) {
51+
const stats = await ArticleStatsService.getStats()
52+
return inertia.render('dashboard/index', {
53+
publishedArticles: stats.published,
54+
draftArticles: stats.drafts,
55+
discussions: 0,
56+
questions: 0,
57+
})
58+
}
4859
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Article from '#models/article'
2+
3+
export default class ArticleStatsService {
4+
static async getStats() {
5+
const publishedResult = await Article.query().where('is_published', true).count('* as total')
6+
const draftResult = await Article.query().where('is_published', false).count('* as total')
7+
return {
8+
published: Number(publishedResult[0].$extras.total),
9+
drafts: Number(draftResult[0].$extras.total),
10+
}
11+
}
12+
}

config/cors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { defineConfig } from '@adonisjs/cors'
88
*/
99
const corsConfig = defineConfig({
1010
enabled: true,
11-
origin: [],
11+
origin: ['*'],
1212
methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE'],
1313
headers: true,
1414
exposeHeaders: [],

database/migrations/1736839410875_create_users_table.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { BaseSchema } from '@adonisjs/lucid/schema'
2+
import { Role, roles } from '#enums/role'
23

34
export default class extends BaseSchema {
45
protected tableName = 'users'
@@ -9,12 +10,11 @@ export default class extends BaseSchema {
910
table.string('username').unique().notNullable()
1011
table.string('name').nullable()
1112
table.string('email').unique().notNullable()
12-
table.string('password').notNullable()
13+
table.string('password').nullable()
1314
table.string('avatar').nullable()
1415
table.string('github_id').unique().nullable()
1516
table.string('twitter_id').unique().nullable()
16-
table.boolean('is_admin').defaultTo(false)
17-
table.boolean('is_sponsor').defaultTo(false)
17+
table.enu('role', roles).notNullable().defaultTo(Role.MEMBER)
1818
table.timestamp('email_verified_at').nullable()
1919
table.timestamps(true, true)
2020
})

enums/role.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export enum Role {
2+
ADMIN = 'ADMIN',
3+
SPONSOR = 'SPONSOR',
4+
MEMBER = 'MEMBER',
5+
}
6+
7+
export const roles = Object.values(Role)

inertia/pages/auth/login.tsx

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { FormEvent, useState } from 'react'
33
import { router } from '@inertiajs/react'
44
import Navbar from '../../components/navbar'
55
import Footer from '../../components/footer'
6+
import { demoUsers } from '../../../mock-data/users'
67

78
interface PageProps {
89
errors: {
@@ -40,6 +41,32 @@ export default function Login() {
4041
</h2>
4142
</div>
4243

44+
{/* Demo Buttons */}
45+
<div className="flex gap-2 justify-center mb-2">
46+
<button
47+
type="button"
48+
className="px-3 py-1 bg-blue-100 text-blue-800 rounded hover:bg-blue-200 text-sm"
49+
onClick={() => setData({
50+
...data,
51+
email: demoUsers[0].email,
52+
password: demoUsers[0].password,
53+
})}
54+
>
55+
Demo Admin
56+
</button>
57+
<button
58+
type="button"
59+
className="px-3 py-1 bg-green-100 text-green-800 rounded hover:bg-green-200 text-sm"
60+
onClick={() => setData({
61+
...data,
62+
email: demoUsers[1].email,
63+
password: demoUsers[1].password,
64+
})}
65+
>
66+
Demo Member
67+
</button>
68+
</div>
69+
4370
{/* Flash Messages */}
4471
{(flash?.error || pageErrors?.form) && (
4572
<div className="rounded-md bg-red-50 p-4">
@@ -83,7 +110,7 @@ export default function Login() {
83110

84111
{/* Social Login */}
85112
<div className="space-y-3">
86-
<Link
113+
<a
87114
href="/auth/github"
88115
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-gray-800 hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500"
89116
>
@@ -95,7 +122,7 @@ export default function Login() {
95122
/>
96123
</svg>
97124
Continue with GitHub
98-
</Link>
125+
</a>
99126
</div>
100127

101128
<div className="relative">

inertia/pages/auth/register.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ export default function Register() {
231231
</div>
232232

233233
<div className="mt-6">
234-
<Link
234+
<a
235235
href="/auth/github"
236236
className="flex w-full items-center justify-center gap-3 rounded-md bg-[#24292F] px-3 py-1.5 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#24292F]"
237237
>
@@ -243,7 +243,7 @@ export default function Register() {
243243
/>
244244
</svg>
245245
<span className="text-sm font-semibold leading-6">GitHub</span>
246-
</Link>
246+
</a>
247247
</div>
248248
</div>
249249
</div>

inertia/pages/dashboard/index.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import { Head, Link } from '@inertiajs/react'
22
import DashboardLayout from '../../layouts/dashboard'
33

44
interface DashboardProps {
5-
stats: {
6-
articles: number
7-
discussions: number
8-
questions: number
9-
}
5+
publishedArticles: number
6+
draftArticles: number
7+
discussions: number
8+
questions: number
109
}
1110

12-
export default function Dashboard({ stats }: DashboardProps) {
11+
export default function Dashboard({ publishedArticles, draftArticles, discussions, questions }: DashboardProps) {
1312
return (
1413
<DashboardLayout>
1514
<Head title="Dashboard - JavaScript Cameroun" />
@@ -18,21 +17,27 @@ export default function Dashboard({ stats }: DashboardProps) {
1817
{/* Stats */}
1918
<div className="grid grid-cols-1 gap-5 sm:grid-cols-3">
2019
<div className="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6">
21-
<dt className="truncate text-sm font-medium text-gray-500">Total Articles</dt>
20+
<dt className="truncate text-sm font-medium text-gray-500">Articles publiés</dt>
2221
<dd className="mt-1 text-3xl font-semibold tracking-tight text-gray-900">
23-
{stats.articles}
22+
{publishedArticles}
23+
</dd>
24+
</div>
25+
<div className="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6">
26+
<dt className="truncate text-sm font-medium text-gray-500">Brouillons</dt>
27+
<dd className="mt-1 text-3xl font-semibold tracking-tight text-gray-900">
28+
{draftArticles}
2429
</dd>
2530
</div>
2631
<div className="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6">
2732
<dt className="truncate text-sm font-medium text-gray-500">Total Discussions</dt>
2833
<dd className="mt-1 text-3xl font-semibold tracking-tight text-gray-900">
29-
{stats.discussions}
34+
{discussions}
3035
</dd>
3136
</div>
3237
<div className="overflow-hidden rounded-lg bg-white px-4 py-5 shadow sm:p-6">
3338
<dt className="truncate text-sm font-medium text-gray-500">Total Questions</dt>
3439
<dd className="mt-1 text-3xl font-semibold tracking-tight text-gray-900">
35-
{stats.questions}
40+
{questions}
3641
</dd>
3742
</div>
3843
</div>

mock-data/users.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Role } from '#enums/role'
2+
3+
export const demoUsers = [
4+
{
5+
username: 'admin',
6+
name: 'admin',
7+
email: 'admin@example.com',
8+
password: 'password123',
9+
role: Role.ADMIN,
10+
},
11+
{
12+
username: 'regularuser',
13+
name: 'Regular User',
14+
email: 'regular@example.com',
15+
password: 'password123',
16+
role: Role.MEMBER,
17+
},
18+
]

nomenclature.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
## 🚀 Nomenclature des noms de branches
2+
3+
Les branches doivent décrire leur objectif. Utilise un **préfixe** suivi d’un **slug** clair et concis.
4+
5+
### 📂 Types de branches :
6+
7+
| Type | Préfixe | Exemple |
8+
| -------- | ----------- | --------------------------------- |
9+
| Feature | `feature/` | `feature/user-authentication` |
10+
| Bug fix | `fix/` | `fix/login-redirect-bug` |
11+
| Hotfix | `hotfix/` | `hotfix/crash-on-startup` |
12+
| Refactor | `refactor/` | `refactor/user-service-structure` |
13+
| Chore | `chore/` | `chore/update-dependencies` |
14+
| Test | `test/` | `test/add-login-unit-tests` |
15+
| Docs | `docs/` | `docs/api-auth-docs` |
16+
| Release | `release/` | `release/v1.0.0` |
17+
18+
**Bonus :** Ajoute un identifiant de ticket si tu travailles avec un outil comme Jira, Notion ou Linear :
19+
20+
```
21+
feature/1234-user-authentication
22+
fix/BUG-982-login-crash
23+
```
24+
25+
---
26+
27+
## 📝 Nomenclature des messages de commit
28+
29+
Utilise le **format conventionnel** `type(scope): message`, inspiré de [Conventional Commits](https://www.conventionalcommits.org/), très apprécié dans les projets pro, surtout avec les outils d’intégration continue (CI/CD).
30+
31+
### 🔠 Types courants de commits
32+
33+
| Type | Utilisation | Exemple |
34+
| ---------- | ------------------------------------------------------ | ----------------------------------------------- |
35+
| `feat` | Nouvelle fonctionnalité | `feat(auth): add GitHub OAuth login` |
36+
| `fix` | Correction de bug | `fix(api): prevent crash on empty payload` |
37+
| `docs` | Changement de documentation | `docs(readme): add usage instructions` |
38+
| `style` | Changement sans impact sur le code (indentation, etc.) | `style(ui): reindent login form` |
39+
| `refactor` | Refactoring sans changement fonctionnel | `refactor(db): simplify user query` |
40+
| `perf` | Amélioration des performances | `perf(api): reduce response time for dashboard` |
41+
| `test` | Ajout ou mise à jour de tests | `test(user): add signup unit tests` |
42+
| `chore` | Tâches diverses (build, dépendances, scripts, etc.) | `chore: update eslint config` |
43+
| `ci` | Configuration de l’intégration continue | `ci(github): add action for test coverage` |
44+
45+
### 🎯 Bonnes pratiques
46+
47+
* **Présent** : Utilise l’impératif présent → `add`, `fix`, `update` (pas `added` ou `adds`)
48+
* **Court et clair** : Max 50-60 caractères pour le titre
49+
* **Optionnel** : Ajoute une description en dessous si nécessaire
50+
51+
```bash
52+
git commit -m "feat(profile): add profile picture upload"
53+
54+
# ou avec un corps :
55+
git commit -m "fix(auth): handle empty token on refresh" -m "Previously, the app crashed when the token was null. This ensures a fallback redirect."
56+
```

0 commit comments

Comments
 (0)