Skip to content

Commit 0098a74

Browse files
committed
feat: enhance UI components and improve date handling across the application
- Updated .env.sample to remove hardcoded SMTP credentials for better security. - Refactored CSS styles in various components for a more consistent look, including background color changes. - Added robust date parsing and formatting functions to improve date handling in task and project components. - Enhanced task and project modals with improved button styles and accessibility features. - Implemented new date-related features in Kanban and List views to display due dates and statuses more effectively. - Improved user experience in team and project management components with better visual feedback and interactions.
1 parent 9a0264f commit 0098a74

18 files changed

+1352
-531
lines changed

.env.sample

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ S3_ENDPOINT_URL=
4545
# Mail Server
4646
SMTP_HOST=host.docker.internal
4747
SMTP_PORT=587
48-
SMTP_USER=task@commitflow.space
49-
SMTP_PASS=Sukses123
48+
SMTP_USER=
49+
SMTP_PASS=
5050
SMTP_SECURE=false # true untuk SMTPS(465), false untuk STARTTLS (587)
5151
FROM_NAME=CommitFlow
52-
FROM_ADDRESS=task@commitflow.space
52+
FROM_ADDRESS=

frontend/src/App.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,4 @@
5858

5959
.animate-fadeIn {
6060
animation: fadeIn 0.8s ease-out both;
61-
}
61+
}
Lines changed: 65 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,75 @@
1-
import { useState, useEffect } from "react"
2-
import "./AiAgent.css"
1+
import { useState, useEffect } from "react";
2+
import "./AiAgent.css";
33

44
function AiAgent({ setIsShow }: any) {
5-
const messages = [
6-
"📈 Halo, pantau kontribusi yuk!",
7-
"💡 Mau analisa cepat?",
8-
"🔍 Cari kontributor terbaik?",
9-
"🤖 Siap bantu analisa!",
10-
"🔍 Siapa aja yang berkontribusi?",
11-
"🔍 Ada repo apa aja ya?",
12-
"💡 Butuh insight repo?",
13-
"🧠 Analisis aktif!",
14-
]
5+
const messages = [
6+
"📈 Halo, pantau kontribusi yuk!",
7+
"💡 Mau analisa cepat?",
8+
"🔍 Cari kontributor terbaik?",
9+
"🤖 Siap bantu analisa!",
10+
"🔍 Siapa aja yang berkontribusi?",
11+
"🔍 Ada repo apa aja ya?",
12+
"💡 Butuh insight repo?",
13+
"🧠 Analisis aktif!",
14+
];
1515

16-
const [currentIndex, setCurrentIndex] = useState(0)
17-
const [displayedText, setDisplayedText] = useState("")
18-
const [wordIndex, setWordIndex] = useState(0)
19-
const [isTyping, setIsTyping] = useState(true)
16+
const [currentIndex, setCurrentIndex] = useState(0);
17+
const [displayedText, setDisplayedText] = useState("");
18+
const [wordIndex, setWordIndex] = useState(0);
19+
const [isTyping, setIsTyping] = useState(true);
2020

21-
useEffect(() => {
22-
const words = messages[currentIndex].split(" ")
21+
useEffect(() => {
22+
const words = messages[currentIndex].split(" ");
2323

24-
if (wordIndex < words.length) {
25-
const timeout = setTimeout(() => {
26-
setDisplayedText((prev) =>
27-
prev ? `${prev} ${words[wordIndex]}` : words[wordIndex]
28-
)
29-
setWordIndex((prev) => prev + 1)
30-
}, 250)
31-
return () => clearTimeout(timeout)
32-
} else {
33-
setIsTyping(false)
34-
const wait = setTimeout(() => {
35-
setDisplayedText("")
36-
setWordIndex(0)
37-
setCurrentIndex((prev) => (prev + 1) % messages.length)
38-
setIsTyping(true)
39-
}, 5000)
40-
return () => clearTimeout(wait)
41-
}
42-
}, [wordIndex, currentIndex])
24+
if (wordIndex < words.length) {
25+
const timeout = setTimeout(() => {
26+
setDisplayedText((prev) =>
27+
prev ? `${prev} ${words[wordIndex]}` : words[wordIndex]
28+
);
29+
setWordIndex((prev) => prev + 1);
30+
}, 250);
31+
return () => clearTimeout(timeout);
32+
} else {
33+
setIsTyping(false);
34+
const wait = setTimeout(() => {
35+
setDisplayedText("");
36+
setWordIndex(0);
37+
setCurrentIndex((prev) => (prev + 1) % messages.length);
38+
setIsTyping(true);
39+
}, 5000);
40+
return () => clearTimeout(wait);
41+
}
42+
}, [wordIndex, currentIndex]);
4343

44-
return (
45-
<div
46-
className="fixed bottom-5 right-5 z-50 flex items-center space-x-3"
47-
onClick={() => setIsShow(true)}
48-
>
49-
{/* Balon chat di kiri */}
50-
<div className="chat-bubble relative px-4 py-2 text-sm rounded-2xl shadow-md cursor-pointer backdrop-blur-md border border-blue-100 animate-gradient select-none">
51-
<span>{displayedText}</span>
52-
{isTyping && <span className="typing-cursor text-blue-500">|</span>}
44+
return (
45+
<div
46+
className="fixed bottom-5 right-5 z-50 flex items-center space-x-3"
47+
onClick={() => setIsShow(true)}
48+
>
49+
{/* Balon chat di kiri */}
50+
<div className="chat-bubble relative px-4 py-2 text-sm rounded-2xl shadow-md cursor-pointer backdrop-blur-md border border-blue-100 animate-gradient select-none">
51+
<span>{displayedText}</span>
52+
{isTyping && <span className="typing-cursor text-blue-500">|</span>}
5353

54-
{/* Segitiga balon (ekor) */}
55-
<div className="chat-tail"></div>
56-
</div>
54+
{/* Segitiga balon (ekor) */}
55+
<div className="chat-tail"></div>
56+
</div>
5757

58-
{/* Tombol chatbot di kanan */}
59-
<button
60-
onClick={() => setIsShow(true)}
61-
className="transform transition-transform duration-200 hover:scale-105 cursor-pointer"
62-
>
63-
<img
64-
src="ai-logo.png"
65-
className="transition-transform duration-300 ease-in-out hover:scale-110"
66-
width={70}
67-
height={70}
68-
alt="Ask AI Agent"
69-
/>
70-
</button>
71-
</div>
72-
)
58+
{/* Tombol chatbot di kanan */}
59+
<button
60+
onClick={() => setIsShow(true)}
61+
className="transform transition-transform duration-200 hover:scale-105 cursor-pointer"
62+
>
63+
<img
64+
src="ai-logo.png"
65+
className="transition-transform duration-300 ease-in-out hover:scale-110"
66+
width={55}
67+
height={55}
68+
alt="Ask AI Agent"
69+
/>
70+
</button>
71+
</div>
72+
);
7373
}
7474

75-
export default AiAgent
75+
export default AiAgent;

frontend/src/components/CreateProjectModal.tsx

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Plus } from "lucide-react";
12
import React, { useEffect, useRef, useState } from "react";
23

34
// CreateProjectModal.tsx
@@ -121,7 +122,7 @@ export default function CreateProjectModal({
121122
value={name}
122123
onChange={(e) => setName(e.target.value)}
123124
placeholder="Project name"
124-
className="mt-1 block w-full px-3 py-2 rounded-lg bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-700 text-sm outline-none focus:ring-1 focus:ring-sky-300"
125+
className="mt-1 block w-full px-3 py-2 rounded-lg bg-slate-100 dark:bg-gray-900 border border-gray-100 dark:border-gray-700 text-sm outline-none focus:ring-1 focus:ring-sky-300"
125126
required
126127
/>
127128
</label>
@@ -134,7 +135,7 @@ export default function CreateProjectModal({
134135
value={description}
135136
onChange={(e) => setDescription(e.target.value)}
136137
placeholder="Short description"
137-
className="mt-1 block w-full px-3 py-2 rounded-lg bg-white dark:bg-gray-900 border border-gray-100 dark:border-gray-700 text-sm outline-none focus:ring-1 focus:ring-sky-300 min-h-[96px]"
138+
className="mt-1 block w-full px-3 py-2 rounded-lg bg-slate-100 dark:bg-gray-900 border border-gray-100 dark:border-gray-700 text-sm outline-none focus:ring-1 focus:ring-sky-300 min-h-[96px]"
138139
/>
139140
</label>
140141

@@ -151,23 +152,19 @@ export default function CreateProjectModal({
151152
<button
152153
type="submit"
153154
disabled={busy}
154-
className="flex items-center gap-2 px-4 py-2 rounded-lg bg-sky-600 hover:bg-sky-700 text-white text-sm font-medium shadow transition-colors disabled:opacity-60"
155+
aria-disabled={busy}
156+
className={`group inline-flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-semibold
157+
bg-gradient-to-r from-sky-500 to-sky-600 text-white
158+
hover:from-sky-600 hover:to-sky-700
159+
active:scale-95 transition-all duration-300
160+
dark:from-sky-600 dark:to-sky-700 dark:hover:from-sky-700 dark:hover:to-sky-800
161+
${busy ? "opacity-60 cursor-not-allowed" : "cursor-pointer"}`}
155162
>
156-
<svg
157-
xmlns="http://www.w3.org/2000/svg"
158-
width="16"
159-
height="16"
160-
viewBox="0 0 24 24"
161-
fill="none"
162-
stroke="currentColor"
163-
strokeWidth="2"
164-
strokeLinecap="round"
165-
strokeLinejoin="round"
166-
className="inline-block"
167-
>
168-
<path d="M12 5v14" />
169-
<path d="M5 12h14" />
170-
</svg>
163+
<Plus
164+
size={16}
165+
className="transition-transform duration-300 group-hover:rotate-90"
166+
aria-hidden="true"
167+
/>
171168
<span>{busy ? submittingText : "Create"}</span>
172169
</button>
173170
</div>

frontend/src/components/CreateWorkspaceModal.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export default function CreateWorkspaceModal({
8989
/>
9090

9191
{/* modal */}
92-
<div className="relative w-full max-w-md mx-4 bg-white dark:bg-gray-900 rounded-2xl shadow-xl ring-1 ring-black/10 dark:ring-white/10 overflow-hidden">
92+
<div className="relative w-full max-w-md mx-4 bg-slate-100 dark:bg-gray-900 rounded-2xl shadow-xl ring-1 ring-black/10 dark:ring-white/10 overflow-hidden">
9393
<div className="flex items-center justify-between px-5 py-4 border-b border-gray-100 dark:border-gray-800">
9494
<h3 className="text-sm font-semibold">Create workspace</h3>
9595
<button
@@ -142,11 +142,24 @@ export default function CreateWorkspaceModal({
142142
</button>
143143
<button
144144
type="submit"
145-
className="inline-flex items-center gap-2 px-3 py-2 rounded-lg bg-sky-600 hover:bg-sky-700 text-white text-sm font-medium shadow transition-colors"
146145
disabled={saving}
146+
className={`group inline-flex items-center gap-2 px-4 py-2 rounded-xl text-sm font-semibold
147+
bg-gradient-to-r from-sky-500 to-sky-600 text-white
148+
hover:from-sky-600 hover:to-sky-700
149+
active:scale-95 transition-all duration-300
150+
disabled:opacity-60 disabled:cursor-not-allowed`}
147151
>
148-
<Check size={14} />
149-
<span>{saving ? "Creating..." : "Create"}</span>
152+
{saving ? (
153+
<span>Creating...</span>
154+
) : (
155+
<>
156+
<Check
157+
size={16}
158+
className="transition-transform duration-300 group-hover:-rotate-6"
159+
/>
160+
<span>Create</span>
161+
</>
162+
)}
150163
</button>
151164
</div>
152165
</form>

0 commit comments

Comments
 (0)