Refactor NewChatForm for improved readability
Reformatted code in NewChatForm.tsx for better readability and maintainability, including consistent spacing, line breaks, and minor style adjustments. No functional changes were made.
This commit is contained in:
@@ -1,8 +1,14 @@
|
|||||||
"use client"
|
"use client";
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
CardDescription,
|
||||||
|
} from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
@@ -29,41 +35,43 @@ export default function NewChatForm() {
|
|||||||
const [initialMessage, setInitialMessage] = useState("");
|
const [initialMessage, setInitialMessage] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [loadingUser, setLoadingUser] = useState(false);
|
const [loadingUser, setLoadingUser] = useState(false);
|
||||||
const [vendorStores, setVendorStores] = useState<{ _id: string, name: string }[]>([]);
|
const [vendorStores, setVendorStores] = useState<
|
||||||
|
{ _id: string; name: string }[]
|
||||||
|
>([]);
|
||||||
const [selectedStore, setSelectedStore] = useState<string>("");
|
const [selectedStore, setSelectedStore] = useState<string>("");
|
||||||
const [selectedUser, setSelectedUser] = useState<User | null>(null);
|
const [selectedUser, setSelectedUser] = useState<User | null>(null);
|
||||||
|
|
||||||
// Create an axios instance with auth
|
// Create an axios instance with auth
|
||||||
const getAuthAxios = () => {
|
const getAuthAxios = () => {
|
||||||
const authToken = getCookie("Authorization");
|
const authToken = getCookie("Authorization");
|
||||||
if (!authToken) return null;
|
if (!authToken) return null;
|
||||||
|
|
||||||
return axios.create({
|
return axios.create({
|
||||||
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
||||||
headers: { Authorization: `Bearer ${authToken}` }
|
headers: { Authorization: `Bearer ${authToken}` },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse URL parameters for buyerId and fetch user details if present
|
// Parse URL parameters for buyerId and fetch user details if present
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const buyerIdParam = searchParams.get('buyerId');
|
const buyerIdParam = searchParams.get("buyerId");
|
||||||
if (buyerIdParam) {
|
if (buyerIdParam) {
|
||||||
setBuyerId(buyerIdParam);
|
setBuyerId(buyerIdParam);
|
||||||
// We'll fetch user details after stores are loaded
|
// We'll fetch user details after stores are loaded
|
||||||
}
|
}
|
||||||
}, [searchParams]);
|
}, [searchParams]);
|
||||||
|
|
||||||
// Fetch user information by ID
|
// Fetch user information by ID
|
||||||
const fetchUserById = async (userId: string) => {
|
const fetchUserById = async (userId: string) => {
|
||||||
if (!userId || !vendorStores[0]?._id) return;
|
if (!userId || !vendorStores[0]?._id) return;
|
||||||
|
|
||||||
const authAxios = getAuthAxios();
|
const authAxios = getAuthAxios();
|
||||||
if (!authAxios) {
|
if (!authAxios) {
|
||||||
toast.error("You need to be logged in");
|
toast.error("You need to be logged in");
|
||||||
router.push("/auth/login");
|
router.push("/auth/login");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoadingUser(true);
|
setLoadingUser(true);
|
||||||
try {
|
try {
|
||||||
const response = await authAxios.get(`/chats/user/${userId}`);
|
const response = await authAxios.get(`/chats/user/${userId}`);
|
||||||
@@ -90,7 +98,9 @@ export default function NewChatForm() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
setSearching(true);
|
setSearching(true);
|
||||||
const response = await authAxios.get(`/chats/search/users?query=${encodeURIComponent(query)}&storeId=${vendorStores[0]._id}`);
|
const response = await authAxios.get(
|
||||||
|
`/chats/search/users?query=${encodeURIComponent(query)}&storeId=${vendorStores[0]._id}`,
|
||||||
|
);
|
||||||
setSearchResults(response.data);
|
setSearchResults(response.data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error searching users:", error);
|
console.error("Error searching users:", error);
|
||||||
@@ -114,7 +124,7 @@ export default function NewChatForm() {
|
|||||||
setSearchQuery(user.telegramUsername || user.telegramUserId);
|
setSearchQuery(user.telegramUsername || user.telegramUserId);
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fetch vendor stores
|
// Fetch vendor stores
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchVendorStores = async () => {
|
const fetchVendorStores = async () => {
|
||||||
@@ -124,41 +134,51 @@ export default function NewChatForm() {
|
|||||||
router.push("/auth/login");
|
router.push("/auth/login");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get vendor profile first
|
// Get vendor profile first
|
||||||
const vendorResponse = await authAxios.get('/auth/me');
|
const vendorResponse = await authAxios.get("/auth/me");
|
||||||
|
|
||||||
// Extract vendor ID properly
|
// Extract vendor ID properly
|
||||||
const vendorId = vendorResponse.data.vendor?._id;
|
const vendorId = vendorResponse.data.vendor?._id;
|
||||||
|
|
||||||
if (!vendorId) {
|
if (!vendorId) {
|
||||||
console.error("Vendor ID not found in profile response:", vendorResponse.data);
|
console.error(
|
||||||
|
"Vendor ID not found in profile response:",
|
||||||
|
vendorResponse.data,
|
||||||
|
);
|
||||||
toast.error("Could not retrieve vendor information");
|
toast.error("Could not retrieve vendor information");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch store
|
// Fetch store
|
||||||
const storeResponse = await authAxios.get(`/storefront`);
|
const storeResponse = await authAxios.get(`/storefront`);
|
||||||
|
|
||||||
// Handle both array and single object responses
|
// Handle both array and single object responses
|
||||||
if (Array.isArray(storeResponse.data)) {
|
if (Array.isArray(storeResponse.data)) {
|
||||||
setVendorStores(storeResponse.data);
|
setVendorStores(storeResponse.data);
|
||||||
if (storeResponse.data.length > 0) {
|
if (storeResponse.data.length > 0) {
|
||||||
setSelectedStore(storeResponse.data[0]._id);
|
setSelectedStore(storeResponse.data[0]._id);
|
||||||
}
|
}
|
||||||
} else if (storeResponse.data && typeof storeResponse.data === 'object' && storeResponse.data._id) {
|
} else if (
|
||||||
|
storeResponse.data &&
|
||||||
|
typeof storeResponse.data === "object" &&
|
||||||
|
storeResponse.data._id
|
||||||
|
) {
|
||||||
const singleStore = [storeResponse.data];
|
const singleStore = [storeResponse.data];
|
||||||
setVendorStores(singleStore);
|
setVendorStores(singleStore);
|
||||||
setSelectedStore(storeResponse.data._id);
|
setSelectedStore(storeResponse.data._id);
|
||||||
} else {
|
} else {
|
||||||
console.error("Expected store data but received:", storeResponse.data);
|
console.error(
|
||||||
|
"Expected store data but received:",
|
||||||
|
storeResponse.data,
|
||||||
|
);
|
||||||
setVendorStores([]);
|
setVendorStores([]);
|
||||||
toast.error("Failed to load store data in expected format");
|
toast.error("Failed to load store data in expected format");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have the store, fetch user details if buyerId was set
|
// Now that we have the store, fetch user details if buyerId was set
|
||||||
const buyerIdParam = searchParams.get('buyerId');
|
const buyerIdParam = searchParams.get("buyerId");
|
||||||
if (buyerIdParam) {
|
if (buyerIdParam) {
|
||||||
fetchUserById(buyerIdParam);
|
fetchUserById(buyerIdParam);
|
||||||
}
|
}
|
||||||
@@ -168,29 +188,29 @@ export default function NewChatForm() {
|
|||||||
setVendorStores([]);
|
setVendorStores([]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fetchVendorStores();
|
fetchVendorStores();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleBackClick = () => {
|
const handleBackClick = () => {
|
||||||
router.push("/dashboard/chats");
|
router.push("/dashboard/chats");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (!buyerId) {
|
if (!buyerId) {
|
||||||
toast.error("Please select a customer");
|
toast.error("Please select a customer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vendorStores.length === 0) {
|
if (vendorStores.length === 0) {
|
||||||
toast.error("No store available. Please create a store first.");
|
toast.error("No store available. Please create a store first.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const storeId = vendorStores[0]._id;
|
const storeId = vendorStores[0]._id;
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const authAxios = getAuthAxios();
|
const authAxios = getAuthAxios();
|
||||||
@@ -199,13 +219,13 @@ export default function NewChatForm() {
|
|||||||
router.push("/auth/login");
|
router.push("/auth/login");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await authAxios.post("/chats/create", {
|
const response = await authAxios.post("/chats/create", {
|
||||||
buyerId,
|
buyerId,
|
||||||
storeId: storeId,
|
storeId: storeId,
|
||||||
initialMessage: initialMessage.trim() || undefined
|
initialMessage: initialMessage.trim() || undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.data.chatId) {
|
if (response.data.chatId) {
|
||||||
toast.success("Chat created successfully!");
|
toast.success("Chat created successfully!");
|
||||||
router.push(`/dashboard/chats/${response.data.chatId}`);
|
router.push(`/dashboard/chats/${response.data.chatId}`);
|
||||||
@@ -215,7 +235,7 @@ export default function NewChatForm() {
|
|||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("Error creating chat:", error);
|
console.error("Error creating chat:", error);
|
||||||
|
|
||||||
if (error.response?.status === 409) {
|
if (error.response?.status === 409) {
|
||||||
toast.info("Chat already exists, redirecting...");
|
toast.info("Chat already exists, redirecting...");
|
||||||
router.push(`/dashboard/chats/${error.response.data.chatId}`);
|
router.push(`/dashboard/chats/${error.response.data.chatId}`);
|
||||||
@@ -226,7 +246,7 @@ export default function NewChatForm() {
|
|||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="w-full">
|
<Card className="w-full">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
@@ -240,7 +260,7 @@ export default function NewChatForm() {
|
|||||||
Start a new conversation with a customer by their Telegram ID
|
Start a new conversation with a customer by their Telegram ID
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<form onSubmit={handleSubmit} className="space-y-6">
|
<form onSubmit={handleSubmit} className="space-y-6">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -260,7 +280,7 @@ export default function NewChatForm() {
|
|||||||
<Search className="h-4 w-4 text-muted-foreground" />
|
<Search className="h-4 w-4 text-muted-foreground" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{open && searchQuery && (
|
{open && searchQuery && (
|
||||||
<div className="absolute z-50 w-full mt-1 border bg-card rounded-md shadow-md max-h-[300px] overflow-auto">
|
<div className="absolute z-50 w-full mt-1 border bg-card rounded-md shadow-md max-h-[300px] overflow-auto">
|
||||||
{searching ? (
|
{searching ? (
|
||||||
@@ -300,9 +320,11 @@ export default function NewChatForm() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
This is the customer's Telegram ID or username. You can search for them above or ask them to use the /myid command in your Telegram bot.
|
This is the customer's Telegram ID or username. You can search for
|
||||||
|
them above or ask them to use the /myid command in your Telegram
|
||||||
|
bot.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{buyerId && !searchQuery && (
|
{buyerId && !searchQuery && (
|
||||||
<div className="p-2 border rounded-md bg-muted/20 mt-2">
|
<div className="p-2 border rounded-md bg-muted/20 mt-2">
|
||||||
<p className="text-sm font-medium">
|
<p className="text-sm font-medium">
|
||||||
@@ -311,7 +333,7 @@ export default function NewChatForm() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="initialMessage">Initial Message (Optional)</Label>
|
<Label htmlFor="initialMessage">Initial Message (Optional)</Label>
|
||||||
<Textarea
|
<Textarea
|
||||||
@@ -322,7 +344,7 @@ export default function NewChatForm() {
|
|||||||
rows={4}
|
rows={4}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end space-x-2">
|
<div className="flex justify-end space-x-2">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -332,7 +354,10 @@ export default function NewChatForm() {
|
|||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="submit" disabled={loading || !buyerId || vendorStores.length === 0}>
|
<Button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading || !buyerId || vendorStores.length === 0}
|
||||||
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<>
|
<>
|
||||||
<RefreshCw className="mr-2 h-4 w-4 animate-spin" />
|
<RefreshCw className="mr-2 h-4 w-4 animate-spin" />
|
||||||
@@ -350,4 +375,4 @@ export default function NewChatForm() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"commitHash": "74f3a2c",
|
"commitHash": "b1e486c",
|
||||||
"buildTime": "2026-01-05T21:55:11.573Z"
|
"buildTime": "2026-01-05T21:59:27.052Z"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user