Skip to content

Commit a95c3a6

Browse files
Add files via upload
1 parent 6566edd commit a95c3a6

2 files changed

Lines changed: 96 additions & 18 deletions

File tree

src/app/api/chat/route.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,25 @@ const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || "https://karachigum.com";
77
const SITE_NAME = "Karachi Gum";
88

99
const SYSTEM_PROMPT = `
10-
You are the AI Sales Assistant for Karachi Gum Industry (KGI). Your goal is to provide technical insights and assist buyers in a professional, conversational manner.
10+
You are the Karachi AI, a specialized Technical Sales Assistant for Karachi Gum Industry (KGI), global leaders in Guar-based hydrocolloids. Your goal is to provide expert technical insights and assist B2B buyers with precision and professionalism.
1111
12-
Guidelines:
13-
- **Conversation Flow**: Do NOT dump all company information at once. Provide a concise initial greeting and answer specific questions as they come.
14-
- **Tone**: Technical, professional, and helpful.
15-
- **Formatting**: Use Markdown (bullet points, bolding) to make information readable.
16-
- **Technical Precision**: Mention specific viscosities (e.g., 200 Mesh, 3500-7000 cps) based on product categories if relevant to the user's inquiry.
17-
- **Call to Action**: If the user asks for bulk pricing, samples, or factory visits, guide them to the "Contact Us" page or provide the emails: ssaleem@karachigum.com or info@karachigum.com.
12+
Core Technical Knowledge:
13+
- **Food Grade (E412)**: High-purity Guar Gum powder (80-200 Mesh) used as a thickener, stabilizer, and emulsifier. ISO/HACCP/Halal/Kosher certified.
14+
- **Industrial Grade**: Primarily for Mining, Explosives, and Textile printing. High viscosity maintenance is key.
15+
- **Fast Hydration Guar**: Specialized for Oil & Gas (Fracking/Drilling). Reaches peak viscosity in <3 minutes.
16+
- **Guar Splits**: 90-95% pure de-husked splits for further processing into high-grade powder.
17+
- **Guar Meal (Churi/Korma)**: High-protein (up to 55%) animal feed, organic and non-GMO.
1818
19-
KGI Portrait Reference:
20-
- Established: 1995 | Location: Gulbai, SITE, Karachi.
21-
- Certifications: ISO 9001:2008, HACCP, Halal.
22-
- Production: Powder (4.5k MT/yr), Splits (7.3k MT/yr), Meal (16k MT/yr).
23-
- Logistics: 7KM from KICT, 40KM from Port Qasim.
24-
- Products: E412 Food Grade, Industrial Grade, Fast Hydration (Oil/Gas), Cassia Tora.
19+
Company Metrics & Logistics:
20+
- **Capacity**: 4,500 MT/year Powder, 7,300 MT/year Splits, 16,000 MT/year Meal.
21+
- **Location**: Hub of Karachi industry (SITE). 7km from KICT (Karachi Port).
22+
- **Global Presence**: Exporting to 50+ countries including USA, EU, and China.
23+
24+
Guidelines for Interaction:
25+
1. **Persona**: Be technical but accessible. You are a consultant, not just a chatbot.
26+
2. **Conciseness**: Avoid massive walls of text. Use bullet points for comparisons (e.g., Mesh sizes or Viscosity ranges).
27+
3. **Viscosity Reference**: Standard industrial viscosity ranges from 3500 cps to 7500 cps (1% solution on Brookfield RVT).
28+
4. **CTA**: For formal quotes, COA requests, or Laboratory TDS, direct users to sales@karachigum.com or the Contact page.
2529
`;
2630

2731
export async function POST(req: Request) {

src/app/chat/page.tsx

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Button } from "@/components/ui/button";
55
import { Input } from "@/components/ui/input";
66
import { Card } from "@/components/ui/card";
77
import { ScrollArea } from "@/components/ui/scroll-area";
8-
import { Bot, Send, User, Loader2, Plus, Mic, AudioLines, Zap } from "lucide-react";
8+
import { Bot, Send, User, Loader2, Plus, Mic, AudioLines, Zap, Trash2, Copy, Check, Download } from "lucide-react";
99
import { cn } from "@/lib/utils";
1010
import ReactMarkdown from "react-markdown";
1111

@@ -26,17 +26,64 @@ export default function ChatPage() {
2626
const [messages, setMessages] = useState<Message[]>([]);
2727
const [input, setInput] = useState("");
2828
const [isLoading, setIsLoading] = useState(false);
29+
const [copyId, setCopyId] = useState<string | null>(null);
2930
const scrollRef = useRef<HTMLDivElement>(null);
3031

3132
// Initial greeting handling
3233
const hasStarted = messages.length > 0;
3334

35+
// Persistence: Load on mount
36+
useEffect(() => {
37+
const saved = localStorage.getItem("kgi_chat_history");
38+
if (saved) {
39+
try {
40+
setMessages(JSON.parse(saved));
41+
} catch (e) {
42+
console.error("Failed to parse chat history", e);
43+
}
44+
}
45+
}, []);
46+
47+
// Persistence: Save on change
48+
useEffect(() => {
49+
if (messages.length > 0) {
50+
localStorage.setItem("kgi_chat_history", JSON.stringify(messages));
51+
}
52+
}, [messages]);
53+
3454
useEffect(() => {
3555
if (scrollRef.current) {
3656
scrollRef.current.scrollIntoView({ behavior: "smooth" });
3757
}
3858
}, [messages]);
3959

60+
const handleNewChat = () => {
61+
if (confirm("Are you sure you want to clear this conversation?")) {
62+
setMessages([]);
63+
localStorage.removeItem("kgi_chat_history");
64+
}
65+
};
66+
67+
const handleCopy = (content: string, id: string) => {
68+
navigator.clipboard.writeText(content);
69+
setCopyId(id);
70+
setTimeout(() => setCopyId(null), 2000);
71+
};
72+
73+
const handleDownload = () => {
74+
if (messages.length === 0) return;
75+
const text = messages.map(m => `${m.role.toUpperCase()}: ${m.content}`).join("\n\n---\n\n");
76+
const blob = new Blob([`KGI TECHNICAL ASSISTANT - CONSULTATION SUMMARY\nGenerated: ${new Date().toLocaleString()}\n\n${text}`], { type: "text/plain" });
77+
const url = URL.createObjectURL(blob);
78+
const a = document.createElement("a");
79+
a.href = url;
80+
a.download = `KGI-Consultation-${new Date().toISOString().split('T')[0]}.txt`;
81+
document.body.appendChild(a);
82+
a.click();
83+
document.body.removeChild(a);
84+
URL.revokeObjectURL(url);
85+
};
86+
4087
const handleSuggestedPrompt = (prompt: string) => {
4188
setInput(prompt);
4289
};
@@ -138,8 +185,26 @@ export default function ChatPage() {
138185
<h1 className="font-semibold text-slate-800 tracking-tight">KGI Assistant</h1>
139186
</div>
140187
<div className="flex items-center gap-2">
141-
<span className="h-2 w-2 rounded-full bg-emerald-500" />
142-
<span className="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Live Support</span>
188+
<Button
189+
onClick={handleDownload}
190+
variant="ghost"
191+
size="sm"
192+
className="text-slate-400 hover:text-emerald-600 hover:bg-emerald-50 rounded-full flex items-center gap-2 px-3"
193+
title="Download Summary"
194+
>
195+
<Download className="h-4 w-4" />
196+
<span className="text-xs font-medium hidden md:inline">Export</span>
197+
</Button>
198+
<Button
199+
onClick={handleNewChat}
200+
variant="ghost"
201+
size="sm"
202+
className="text-slate-400 hover:text-red-500 hover:bg-red-50 rounded-full flex items-center gap-2 px-3"
203+
title="Clear Conversation"
204+
>
205+
<Trash2 className="h-4 w-4" />
206+
<span className="text-xs font-medium hidden md:inline">Clear</span>
207+
</Button>
143208
</div>
144209
</div>
145210
)}
@@ -196,10 +261,9 @@ export default function ChatPage() {
196261
"relative group max-w-[85%] md:max-w-[80%]"
197262
)}>
198263
<div className={cn(
199-
"text-[15px] leading-relaxed",
200264
m.role === "user" ? "text-emerald-700 font-medium" : "text-slate-700"
201265
)}>
202-
<div className="prose prose-sm max-w-none break-words">
266+
<div className="prose prose-sm max-w-none break-words pr-8">
203267
<ReactMarkdown
204268
components={{
205269
p: ({ children }) => <p className="mb-4 last:mb-0">{children}</p>,
@@ -211,6 +275,16 @@ export default function ChatPage() {
211275
</ReactMarkdown>
212276
</div>
213277
</div>
278+
279+
{m.role === "assistant" && m.content && (
280+
<button
281+
onClick={() => handleCopy(m.content, `msg-${index}`)}
282+
className="absolute top-0 -right-8 p-1.5 text-slate-300 hover:text-emerald-600 transition-colors opacity-0 group-hover:opacity-100 focus:opacity-100"
283+
title="Copy to clipboard"
284+
>
285+
{copyId === `msg-${index}` ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
286+
</button>
287+
)}
214288
</div>
215289
</div>
216290
))}

0 commit comments

Comments
 (0)