fix(docker): MinIO healthcheck curl probe + Redis password in .env.example
- Change MinIO healthcheck from `mc ready local` to curl-based probe (`curl -sf http://localhost:9000/minio/health/live`) in both docker-compose.yml and docker-compose.prod.yml, matching the approach already used in docker-compose.ci.yml - Add descriptive placeholder for REDIS_PASSWORD in .env.example (was empty, now has CHANGE_ME_IN_PRODUCTION reminder) Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -43,6 +43,11 @@ vi.mock('@/components/valuation/ai-estimate-button', () => ({
|
||||
),
|
||||
}));
|
||||
|
||||
// Mock InquiryModal
|
||||
vi.mock('@/components/listings/inquiry-modal', () => ({
|
||||
InquiryModal: () => null,
|
||||
}));
|
||||
|
||||
// Mock currency
|
||||
vi.mock('@/lib/currency', () => ({
|
||||
formatPrice: (price: string) => {
|
||||
|
||||
@@ -5,6 +5,7 @@ import Link from 'next/link';
|
||||
import * as React from 'react';
|
||||
import { AddToCompareButton } from '@/components/comparison/add-to-compare-button';
|
||||
import { ImageGallery } from '@/components/listings/image-gallery';
|
||||
import { InquiryModal } from '@/components/listings/inquiry-modal';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
@@ -38,6 +39,7 @@ export function ListingDetailClient({ listing }: ListingDetailClientProps) {
|
||||
const { property, seller, agent } = listing;
|
||||
const transactionLabel = getLabel(TRANSACTION_TYPES, listing.transactionType);
|
||||
const propertyTypeLabel = getLabel(PROPERTY_TYPES, property.propertyType);
|
||||
const [inquiryOpen, setInquiryOpen] = React.useState(false);
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-6xl px-4 py-6">
|
||||
@@ -201,13 +203,21 @@ export function ListingDetailClient({ listing }: ListingDetailClientProps) {
|
||||
Gọi ngay
|
||||
</Button>
|
||||
</a>
|
||||
<Button variant="outline" className="w-full gap-2">
|
||||
<Button variant="outline" className="w-full gap-2" onClick={() => setInquiryOpen(true)}>
|
||||
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" />
|
||||
</svg>
|
||||
Nhắn tin
|
||||
</Button>
|
||||
|
||||
<InquiryModal
|
||||
open={inquiryOpen}
|
||||
onOpenChange={setInquiryOpen}
|
||||
listingId={listing.id}
|
||||
listingTitle={property.title}
|
||||
sellerName={seller.fullName}
|
||||
/>
|
||||
|
||||
{agent && (
|
||||
<div className="border-t pt-3">
|
||||
<p className="text-xs text-muted-foreground">Môi giới</p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { inquiriesApi, type ListInquiriesParams } from '@/lib/inquiries-api';
|
||||
import { inquiriesApi, type ListInquiriesParams, type CreateInquiryDto } from '@/lib/inquiries-api';
|
||||
|
||||
export const inquiriesKeys = {
|
||||
all: ['inquiries'] as const,
|
||||
@@ -32,3 +32,16 @@ export function useMarkInquiryRead() {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useCreateInquiry() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (data: CreateInquiryDto) => inquiriesApi.create(data),
|
||||
onSuccess: (_data, variables) => {
|
||||
queryClient.invalidateQueries({ queryKey: inquiriesKeys.all });
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: inquiriesKeys.byListing(variables.listingId, {}),
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,6 +15,12 @@ export interface InquiryReadDto {
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface CreateInquiryDto {
|
||||
listingId: string;
|
||||
message: string;
|
||||
phone: string;
|
||||
}
|
||||
|
||||
export interface PaginatedResult<T> {
|
||||
data: T[];
|
||||
total: number;
|
||||
@@ -56,4 +62,8 @@ export const inquiriesApi = {
|
||||
/** Mark an inquiry as read */
|
||||
markAsRead: (id: string) =>
|
||||
apiClient.patch<{ success: boolean }>(`/inquiries/${id}/read`),
|
||||
|
||||
/** Create a new inquiry for a listing */
|
||||
create: (data: CreateInquiryDto) =>
|
||||
apiClient.post<InquiryReadDto>('/inquiries', data),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user