Compare commits
No commits in common. "8c6b9e1010ce5efa89d494e4f622328be82ffcdb" and "752d3465221c5845e9ca8a477f51e60d828617e4" have entirely different histories.
8c6b9e1010
...
752d346522
@ -1,42 +0,0 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export async function GET() {
|
||||
const apiKey = "37eb7f83988cfd76ffb5c5af9adc25652efe5607e39997fc7d0e054d690ef25e";
|
||||
const placeId = "ChIJGyfJwKE7K4gRbq-m1ao-eHo";
|
||||
|
||||
let allReviews = [];
|
||||
let nextPageToken = null;
|
||||
|
||||
try {
|
||||
let pageCount = 0;
|
||||
while (pageCount < 3) {
|
||||
pageCount++;
|
||||
const url = `https://serpapi.com/search.json?engine=google_maps_reviews&hl=en&api_key=${apiKey}&place_id=${placeId}${nextPageToken ? `&next_page_token=${nextPageToken}` : ""}`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
console.error("Pages API: SerpAPI Error:", data.error);
|
||||
break;
|
||||
}
|
||||
|
||||
if (data.reviews && data.reviews.length > 0) {
|
||||
allReviews = [...allReviews, ...data.reviews];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!data.serpapi_pagination || !data.serpapi_pagination.next_page_token) {
|
||||
break;
|
||||
}
|
||||
|
||||
nextPageToken = data.serpapi_pagination.next_page_token;
|
||||
await new Promise((resolve) => setTimeout(resolve, 2500));
|
||||
}
|
||||
|
||||
return NextResponse.json({ reviews: allReviews, total: allReviews.length });
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error: "Failed to fetch reviews", details: error.message }, { status: 500 });
|
||||
}
|
||||
}
|
||||
206
app/globals.css
206
app/globals.css
@ -75,209 +75,3 @@
|
||||
.tab-style-one .nav-link:hover {
|
||||
color: var(--heading-color);
|
||||
}
|
||||
|
||||
.read-more-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ffc107;
|
||||
padding: 10px 0 0 0;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
text-align: left;
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.read-more-btn:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.testimonial-two-item {
|
||||
min-height: 250px;
|
||||
display: flex !important;
|
||||
flex-direction: column;
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
.testimonial-two-item .text {
|
||||
flex-grow: 1;
|
||||
text-align: left !important;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.google-review-header-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.google-info-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.google-info-right .google-name {
|
||||
text-transform: uppercase;
|
||||
font-weight: 900;
|
||||
font-size: 20px;
|
||||
margin-bottom: 5px !important;
|
||||
color: #fff;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.google-info-right .ratting {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.google-info-right .ratting i {
|
||||
font-size: 18px;
|
||||
margin-right: 3px;
|
||||
/* text-shadow:
|
||||
-1px -1px 0 #fff,
|
||||
1px -1px 0 #fff,
|
||||
-1px 1px 0 #fff,
|
||||
1px 1px 0 #fff; */
|
||||
/* Alternative for smoother outline */
|
||||
-webkit-text-stroke: 1px #fff;
|
||||
}
|
||||
|
||||
.google-info-right .ratting i.text-warning {
|
||||
color: #ffc212 !important;
|
||||
}
|
||||
|
||||
.google-info-right .ratting i.text-white {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.theme-btn-dark {
|
||||
background: #222222 !important;
|
||||
}
|
||||
|
||||
.theme-btn-dark:hover {
|
||||
background: #000000 !important;
|
||||
}
|
||||
|
||||
|
||||
.google-review-card {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 25px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid #f0f0f0;
|
||||
height: 100%;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.google-review-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.google-avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background: #546e7a;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.google-avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.google-user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.google-name {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
margin: 0 !important;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.google-stars {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.google-stars span,
|
||||
.google-stars i {
|
||||
font-size: 16px;
|
||||
color: #ffc107;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.google-text {
|
||||
font-size: 15px;
|
||||
color: #eee;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.google-review-card-home {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.google-review-card-home .google-name {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.google-review-card-home .google-user-info h4 {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.google-review-card-home .testimonial-text {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Ensure stars are visible on white background for About page */
|
||||
.testimonial-five-item .google-stars i {
|
||||
color: #ffc107 !important;
|
||||
}
|
||||
|
||||
.google-review-header .google-name {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.read-more-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #ffb936;
|
||||
padding: 15px 0 0 0;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
display: block;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.read-more-btn:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.equal-height {
|
||||
min-height: 380px;
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import Link from "next/link";
|
||||
const AboutContent2 = () => {
|
||||
return (
|
||||
<section className="about-us-area-four pt-130 rpt-100 pb-85 rpb-55 rel z-1">
|
||||
import Link from "next/link";
|
||||
const AboutContent2 = () => {
|
||||
return (
|
||||
<section className="about-us-area-four pt-130 rpt-100 pb-85 rpb-55 rel z-1">
|
||||
<div className="container">
|
||||
<div className="row align-items-center">
|
||||
<div className="col-lg-6">
|
||||
@ -17,8 +17,8 @@ const AboutContent2 = () => {
|
||||
</div>
|
||||
<p>
|
||||
At Shiva Sakthi, we serve the rich, unforgettable flavors of Indian cuisine in a setting that feels just like home. From the first bite to the last, each dish is crafted with care, tradition, and a passion for authentic taste.</p>
|
||||
<p>Whether you're craving the bold spices of a South Indian classic or the comfort of a familiar favorite, every visit is a celebration of flavor and hospitality. Delicious food. Warm ambiance. Memorable moments.</p>
|
||||
<Link href="/menu" className="theme-btn mt-25">
|
||||
<p>Whether you're craving the bold spices of a South Indian classic or the comfort of a familiar favorite, every visit is a celebration of flavor and hospitality. Delicious food. Warm ambiance. Memorable moments.</p>
|
||||
<Link href="/menu" className="theme-btn mt-25 mb-60">
|
||||
Check Out Our Menu <i className="far fa-arrow-alt-right" />
|
||||
</Link>
|
||||
{/* <div className="row">
|
||||
@ -68,7 +68,7 @@ const AboutContent2 = () => {
|
||||
data-aos-duration={1500}
|
||||
data-aos-offset={50}
|
||||
>
|
||||
<img src="/assets/images/about/about-2.webp" alt="About" loading="lazy" />
|
||||
<img src="/assets/images/about/about-2.webp" alt="About" loading="lazy" />
|
||||
{/* <div className="row">
|
||||
<div className="col">
|
||||
<img src="assets/images/about/about-four1.jpg" alt="About" />
|
||||
|
||||
@ -1,59 +1,8 @@
|
||||
"use client";
|
||||
import { sliderProps } from "@/utility/sliderProps";
|
||||
import Slider from "react-slick";
|
||||
import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import GoogleReviewsBranding from "../GoogleReviewsBranding";
|
||||
|
||||
const Testimonial = () => {
|
||||
const [reviews, setReviews] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [expandedReview, setExpandedReview] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
async function loadReviews() {
|
||||
try {
|
||||
const res = await fetch("/api/reviews");
|
||||
const data = await res.json();
|
||||
const cleaned = (data.reviews || []).filter(r =>
|
||||
(r.text || r.description || r.snippet || r.review_text || r.body || r.content) &&
|
||||
r.rating >= 4
|
||||
);
|
||||
setReviews(cleaned);
|
||||
} catch (error) {
|
||||
console.error("About: Failed to fetch reviews", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
loadReviews();
|
||||
}, []);
|
||||
|
||||
function renderStars(rating) {
|
||||
return [...Array(5)].map((_, i) => (
|
||||
<i key={i} className={`fa fa-star ${i < rating ? "text-warning" : "text-white"}`}></i>
|
||||
));
|
||||
}
|
||||
|
||||
function getReviewText(r) {
|
||||
return r.text || r.description || r.snippet || r.review_text || r.body || r.content || "";
|
||||
}
|
||||
|
||||
function truncateText(text) {
|
||||
return text.length > 200 ? text.substring(0, 200) + "..." : text;
|
||||
}
|
||||
|
||||
function getProfileImage(r) {
|
||||
const url = r.profile_photo_url || r.author_profile_photo_url || r.user?.thumbnail;
|
||||
if (!url) return null;
|
||||
return url.startsWith("http") ? url : `https://lh3.googleusercontent.com/${url}`;
|
||||
}
|
||||
|
||||
function getInitials(name) {
|
||||
if (!name) return "U";
|
||||
return name.split(' ').map(n => n[0]).join('').substring(0, 2).toUpperCase();
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className="testimonials-two bgc-primary"
|
||||
@ -80,93 +29,77 @@ const Testimonial = () => {
|
||||
>
|
||||
<span className="sub-title mb-5">customer feedback</span>
|
||||
<h2>what have lot’s off happy customer explore feedback</h2>
|
||||
<GoogleReviewsBranding centered={true}/>
|
||||
</div>
|
||||
<span className="marquee-wrap style-two">
|
||||
<span className="marquee-inner left">review </span>
|
||||
<span className="marquee-inner left">review </span>
|
||||
<span className="marquee-inner left">review </span>
|
||||
</span>
|
||||
|
||||
{loading ? (
|
||||
<div className="text-center">
|
||||
<p>Loading reviews...</p>
|
||||
<Slider
|
||||
{...sliderProps.testimonialsTwoCarousel}
|
||||
className="testimonials-two-carousel"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay={50}
|
||||
data-aos-duration={1500}
|
||||
data-aos-offset={50}
|
||||
>
|
||||
<div className="testimonial-two-item">
|
||||
<div className="ratting">
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
</div>
|
||||
<div className="text">
|
||||
Visited this beautiful restaurant while nearby for a conference. The staff were welcoming from the very start! We started with the Gobi 65 which had light spice but a to. Of flavour. Then, we had the hakka noodles, masala dosa and chettinadu chicken curry which was so tasty. Our Server Gagan recommended it and I’m glad he did. He was fantastic and if we are in town again, we will definitely return!
|
||||
</div>
|
||||
<span className="author">Cam Larocque</span>
|
||||
{/* <span className="designation">Manager</span> */}
|
||||
</div>
|
||||
) : (
|
||||
<Slider
|
||||
{...sliderProps.testimonialsTwoCarousel}
|
||||
className="testimonials-two-carousel"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay={50}
|
||||
data-aos-duration={1500}
|
||||
data-aos-offset={50}
|
||||
>
|
||||
{reviews.map((r, index) => {
|
||||
const name = r.user?.name || r.author_name || "Customer";
|
||||
const profileImg = getProfileImage(r);
|
||||
const fullText = getReviewText(r);
|
||||
const isExpanded = expandedReview === index;
|
||||
return (
|
||||
<div key={index} className="testimonial-two-item">
|
||||
<div className="google-review-header-flex">
|
||||
<div className="google-avatar" style={{
|
||||
width: '75px',
|
||||
height: '75px',
|
||||
minWidth: '75px',
|
||||
borderRadius: '50%',
|
||||
overflow: 'hidden',
|
||||
background: '#eee',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: '2px solid #fff'
|
||||
}}>
|
||||
{profileImg ? (
|
||||
<img
|
||||
src={profileImg}
|
||||
alt={name}
|
||||
onError={(e) => (e.target.style.display = 'none')}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||||
/>
|
||||
) : (
|
||||
<span style={{ fontSize: '24px', fontWeight: 'bold', color: '#555' }}>{getInitials(name)}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="google-info-right">
|
||||
<span className="google-name">{name}</span>
|
||||
<div className="ratting">
|
||||
{renderStars(r.rating)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text">
|
||||
{isExpanded ? fullText : truncateText(fullText)}
|
||||
</div>
|
||||
{fullText.length > 200 && (
|
||||
<button
|
||||
className="read-more-btn"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setExpandedReview(isExpanded ? null : index);
|
||||
}}
|
||||
>
|
||||
{isExpanded ? "Read Less" : "Read More"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Slider>
|
||||
)}
|
||||
|
||||
<div className="new-button d-flex justify-content-center pt-30">
|
||||
<Link
|
||||
legacyBehavior
|
||||
href="https://www.google.com/maps/place/SHIVA+SAKTHI+RESTAURANT/@43.70693,-79.6499035,17z/data=!4m8!3m7!1s0x882b3ba1c0c9271b:0x7a783eaad5a6af6e!8m2!3d43.70693!4d-79.6473286!9m1!1b1!16s%2Fg%2F11wh3sh7p4?entry=ttu&g_ep=EgoyMDI1MTIwOS4wIKXMDSoASAFQAw%3D%3D"
|
||||
>
|
||||
<a target="_blank" className="theme-btn style-three">Review us on Google</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="testimonial-two-item">
|
||||
<div className="ratting">
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
</div>
|
||||
<div className="text">
|
||||
Good to have another new south india cuisine in GTA. The food was amazing, The service was good and fast, thanks for offering the milk burfi for tasting.
|
||||
I have been to their other restaurant locations in GTA and KW area, the service and food was excellent. All the best for this new location. Must visit for guys looking to try south indian Biryani.
|
||||
</div>
|
||||
<span className="author">Sen K</span>
|
||||
{/* <span className="designation">Manager</span> */}
|
||||
</div>
|
||||
<div className="testimonial-two-item">
|
||||
<div className="ratting mb-3">
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
</div>
|
||||
<div className="text">
|
||||
Absolutely incredible experience! This Tamil restaurant is a hidden gem in Canada. The flavors are rich, authentic, and remind me of home. Each dish was perfectly spiced and cooked to perfection. The staff were warm, welcoming, and attentive, making the whole visit even more enjoyable. The ambiance is cozy yet vibrant, and you can tell they take pride in both their food and service. Highly recommend to anyone looking for a true taste of South Indian cuisine!
|
||||
</div>
|
||||
<span className="author">manimala s</span>
|
||||
{/* <span className="designation">Manager</span> */}
|
||||
</div>
|
||||
{/* <div className="testimonial-two-item">
|
||||
<div className="quote">
|
||||
<i className="flaticon-quote" />
|
||||
</div>
|
||||
<div className="text">
|
||||
Renowned for its versatility in the kitchen, Red King Crab can
|
||||
prepared in various ways, from simple steaming or boiling to
|
||||
elaborate preparations such as grilling incorporating weather
|
||||
loving
|
||||
</div>
|
||||
<span className="author">Salvador I. Burton</span>
|
||||
<span className="designation">Manager</span>
|
||||
</div> */}
|
||||
</Slider>
|
||||
<div className="shape">
|
||||
<img src="/assets/images/shapes/tomato.png" alt="Shape" loading="lazy" />
|
||||
</div>
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
const GoogleReviewsBranding = ({ centered = false }) => {
|
||||
return (
|
||||
<div className="google-reviews-branding" style={{
|
||||
marginTop: '15px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: centered ? 'center' : 'flex-start',
|
||||
gap: '0px'
|
||||
}}>
|
||||
<div style={{
|
||||
fontSize: '28px',
|
||||
fontWeight: '700',
|
||||
lineHeight: '1.2',
|
||||
letterSpacing: '3px',
|
||||
fontFamily: '"Product Sans", "Google Sans", Roboto, Arial, sans-serif',
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
<span style={{ color: '#4285F4' }}>G</span>
|
||||
<span style={{ color: '#EA4335' }}>o</span>
|
||||
<span
|
||||
style={{
|
||||
color: '#FBBC04',
|
||||
WebkitTextStroke: '1px white'
|
||||
}}
|
||||
>
|
||||
o
|
||||
</span>
|
||||
<span style={{ color: '#4285F4' }}>g</span>
|
||||
<span style={{ color: '#34A853' }}>l</span>
|
||||
<span style={{ color: '#EA4335' }}>e</span>
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: '13px',
|
||||
fontWeight: '700',
|
||||
lineHeight: '1.2',
|
||||
fontFamily: '"Product Sans", "Google Sans", Roboto, Arial, sans-serif',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '5px',
|
||||
marginTop: '-2px'
|
||||
}}>
|
||||
<span style={{ color: '#5F6368' }}>Reviews</span>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
gap: '2px',
|
||||
fontSize: '8px',
|
||||
lineHeight: '1'
|
||||
}}>
|
||||
<span style={{ color: '#FBBC04', WebkitTextStroke: '1px white' }}><i className='fa fa-star text-warning'></i></span>
|
||||
<span style={{ color: '#FBBC04', WebkitTextStroke: '1px white' }}><i className='fa fa-star text-warning'></i></span>
|
||||
<span style={{ color: '#FBBC04', WebkitTextStroke: '1px white' }}><i className='fa fa-star text-warning'></i></span>
|
||||
<span style={{ color: '#FBBC04', WebkitTextStroke: '1px white' }}><i className='fa fa-star text-warning'></i></span>
|
||||
<span style={{ color: '#FBBC04', WebkitTextStroke: '1px white' }}><i className='fa fa-star text-warning'></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GoogleReviewsBranding;
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,59 +1,8 @@
|
||||
"use client";
|
||||
import { sliderProps } from "@/utility/sliderProps";
|
||||
import Slider from "react-slick";
|
||||
import { useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import GoogleReviewsBranding from "./GoogleReviewsBranding";
|
||||
|
||||
const Testimonial = () => {
|
||||
const [reviews, setReviews] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [expandedReview, setExpandedReview] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
async function loadReviews() {
|
||||
try {
|
||||
const res = await fetch("/api/reviews");
|
||||
const data = await res.json();
|
||||
const cleaned = (data.reviews || []).filter(r =>
|
||||
(r.text || r.description || r.snippet || r.review_text || r.body || r.content) &&
|
||||
r.rating >= 4
|
||||
);
|
||||
setReviews(cleaned);
|
||||
} catch (error) {
|
||||
console.error("Home: Failed to fetch reviews", error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
loadReviews();
|
||||
}, []);
|
||||
|
||||
function renderStars(rating) {
|
||||
return [...Array(5)].map((_, i) => (
|
||||
<i key={i} className={`fa fa-star ${i < rating ? "text-warning" : "text-white"}`}></i>
|
||||
));
|
||||
}
|
||||
|
||||
function getReviewText(r) {
|
||||
return r.text || r.description || r.snippet || r.review_text || r.body || r.content || "";
|
||||
}
|
||||
|
||||
function truncateText(text) {
|
||||
return text.length > 200 ? text.substring(0, 200) + "..." : text;
|
||||
}
|
||||
|
||||
function getProfileImage(r) {
|
||||
const url = r.profile_photo_url || r.author_profile_photo_url || r.user?.thumbnail;
|
||||
if (!url) return null;
|
||||
return url.startsWith("http") ? url : `https://lh3.googleusercontent.com/${url}`;
|
||||
}
|
||||
|
||||
function getInitials(name) {
|
||||
if (!name) return "U";
|
||||
return name.split(' ').map(n => n[0]).join('').substring(0, 2).toUpperCase();
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className="testimonials-two bgc-primary"
|
||||
@ -80,94 +29,77 @@ const Testimonial = () => {
|
||||
>
|
||||
<span className="sub-title mb-5">customer feedback</span>
|
||||
<h2>what have lot’s off happy customer explore feedback</h2>
|
||||
<GoogleReviewsBranding centered={true}/>
|
||||
</div>
|
||||
<span className="marquee-wrap style-two">
|
||||
<span className="marquee-inner left">review </span>
|
||||
<span className="marquee-inner left">review </span>
|
||||
<span className="marquee-inner left">review </span>
|
||||
</span>
|
||||
|
||||
|
||||
{loading ? (
|
||||
<div className="text-center">
|
||||
<p>Loading reviews...</p>
|
||||
<Slider
|
||||
{...sliderProps.testimonialsTwoCarousel}
|
||||
className="testimonials-two-carousel"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay={50}
|
||||
data-aos-duration={1500}
|
||||
data-aos-offset={50}
|
||||
>
|
||||
<div className="testimonial-two-item">
|
||||
<div className="ratting">
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
</div>
|
||||
<div className="text">
|
||||
Visited this beautiful restaurant while nearby for a conference. The staff were welcoming from the very start! We started with the Gobi 65 which had light spice but a to. Of flavour. Then, we had the hakka noodles, masala dosa and chettinadu chicken curry which was so tasty. Our Server Gagan recommended it and I’m glad he did. He was fantastic and if we are in town again, we will definitely return!
|
||||
</div>
|
||||
<span className="author">Cam Larocque</span>
|
||||
{/* <span className="designation">Manager</span> */}
|
||||
</div>
|
||||
) : (
|
||||
<Slider
|
||||
{...sliderProps.testimonialsTwoCarousel}
|
||||
className="testimonials-two-carousel"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay={50}
|
||||
data-aos-duration={1500}
|
||||
data-aos-offset={50}
|
||||
>
|
||||
{reviews.map((r, index) => {
|
||||
const name = r.user?.name || r.author_name || "Customer";
|
||||
const profileImg = getProfileImage(r);
|
||||
const fullText = getReviewText(r);
|
||||
const isExpanded = expandedReview === index;
|
||||
return (
|
||||
<div key={index} className="testimonial-two-item">
|
||||
<div className="google-review-header-flex">
|
||||
<div className="google-avatar" style={{
|
||||
width: '75px',
|
||||
height: '75px',
|
||||
minWidth: '75px',
|
||||
borderRadius: '50%',
|
||||
overflow: 'hidden',
|
||||
background: '#eee',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: '2px solid #fff'
|
||||
}}>
|
||||
{profileImg ? (
|
||||
<img
|
||||
src={profileImg}
|
||||
alt={name}
|
||||
onError={(e) => (e.target.style.display = 'none')}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||||
/>
|
||||
) : (
|
||||
<span style={{ fontSize: '24px', fontWeight: 'bold', color: '#555' }}>{getInitials(name)}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="google-info-right">
|
||||
<span className="google-name">{name}</span>
|
||||
<div className="ratting">
|
||||
{renderStars(r.rating)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text">
|
||||
{isExpanded ? fullText : truncateText(fullText)}
|
||||
</div>
|
||||
{fullText.length > 200 && (
|
||||
<button
|
||||
className="read-more-btn"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setExpandedReview(isExpanded ? null : index);
|
||||
}}
|
||||
>
|
||||
{isExpanded ? "Read Less" : "Read More"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Slider>
|
||||
)}
|
||||
|
||||
<div className="new-button d-flex justify-content-center pt-30">
|
||||
<Link
|
||||
legacyBehavior
|
||||
href="https://www.google.com/maps/place/SHIVA+SAKTHI+RESTAURANT/@43.70693,-79.6499035,17z/data=!4m8!3m7!1s0x882b3ba1c0c9271b:0x7a783eaad5a6af6e!8m2!3d43.70693!4d-79.6473286!9m1!1b1!16s%2Fg%2F11wh3sh7p4?entry=ttu&g_ep=EgoyMDI1MTIwOS4wIKXMDSoASAFQAw%3D%3D"
|
||||
>
|
||||
<a target="_blank" className="theme-btn style-three">Review us on Google</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="testimonial-two-item">
|
||||
<div className="ratting">
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
</div>
|
||||
<div className="text">
|
||||
Good to have another new south india cuisine in GTA. The food was amazing, The service was good and fast, thanks for offering the milk burfi for tasting.
|
||||
I have been to their other restaurant locations in GTA and KW area, the service and food was excellent. All the best for this new location. Must visit for guys looking to try south indian Biryani.
|
||||
</div>
|
||||
<span className="author">Sen K</span>
|
||||
{/* <span className="designation">Manager</span> */}
|
||||
</div>
|
||||
<div className="testimonial-two-item">
|
||||
<div className="ratting mb-3">
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
<i className="fas fa-star text-white" />
|
||||
</div>
|
||||
<div className="text">
|
||||
Absolutely incredible experience! This Tamil restaurant is a hidden gem in Canada. The flavors are rich, authentic, and remind me of home. Each dish was perfectly spiced and cooked to perfection. The staff were warm, welcoming, and attentive, making the whole visit even more enjoyable. The ambiance is cozy yet vibrant, and you can tell they take pride in both their food and service. Highly recommend to anyone looking for a true taste of South Indian cuisine!
|
||||
</div>
|
||||
<span className="author">manimala s</span>
|
||||
{/* <span className="designation">Manager</span> */}
|
||||
</div>
|
||||
{/* <div className="testimonial-two-item">
|
||||
<div className="quote">
|
||||
<i className="flaticon-quote" />
|
||||
</div>
|
||||
<div className="text">
|
||||
Renowned for its versatility in the kitchen, Red King Crab can
|
||||
prepared in various ways, from simple steaming or boiling to
|
||||
elaborate preparations such as grilling incorporating weather
|
||||
loving
|
||||
</div>
|
||||
<span className="author">Salvador I. Burton</span>
|
||||
<span className="designation">Manager</span>
|
||||
</div> */}
|
||||
</Slider>
|
||||
<div className="shape">
|
||||
<img src="assets/images/shapes/tomato.png" alt="Shape" loading="lazy" />
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { Blog } from "@/utility/constant.utils";
|
||||
import { sliderProps } from "@/utility/sliderProps";
|
||||
import Link from "next/link";
|
||||
import Slider from "react-slick";
|
||||
|
||||
const BlogSection = () => {
|
||||
return (
|
||||
@ -20,18 +18,17 @@ const BlogSection = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Slider {...sliderProps.testimonialsActive} className="blog-slider row justify-content-center">
|
||||
<div className="row justify-content-center">
|
||||
{
|
||||
Blog?.map((blog) => {
|
||||
return (
|
||||
<div className="px-3" key={blog?.id}>
|
||||
<div className="col-xl-4 col-md-6" key={blog?.id}>
|
||||
<div
|
||||
className="blog-item"
|
||||
data-aos="fade-up"
|
||||
data-aos-delay={50}
|
||||
data-aos-duration={1500}
|
||||
data-aos-offset={50}
|
||||
style={{ marginBottom: '30px' }}
|
||||
>
|
||||
<div className="image">
|
||||
<img src={blog?.image} alt={blog?.slug} loading="lazy" />
|
||||
@ -54,7 +51,7 @@ const BlogSection = () => {
|
||||
)
|
||||
})
|
||||
}
|
||||
</Slider>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@ -125,7 +125,7 @@ const DefaultFooter = () => {
|
||||
<div className="col-lg-12">
|
||||
<div className="copyright-text text-center">
|
||||
<p>
|
||||
Copyright {new Date().getFullYear()} © Shiva Sakthi Restaurant. Powered by <Link href="https://metatroncubesolutions.com/" target="_blank">MetatronCube</Link>. All Right Reserved.{" "}
|
||||
Copyright {new Date().getFullYear()} © Shivas Dosa Restaurant. Powered by <Link href="https://metatroncubesolutions.com/" target="_blank">MetatronCube</Link>. All Right Reserved.{" "}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1353,7 +1353,7 @@ h5,
|
||||
.food-menu-item .content .price,
|
||||
.testimonial-item .text {
|
||||
line-height: 1.66;
|
||||
font-size: 20px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h6,
|
||||
@ -8234,19 +8234,18 @@ h6,
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: none;
|
||||
flex: none;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.food-menu-item.style-two .content h5 .dots {
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
margin-left: 5px;
|
||||
margin-left: 25px;
|
||||
margin-bottom: 10px;
|
||||
border-bottom: 2px dotted var(--base-color);
|
||||
}
|
||||
|
||||
.food-menu-item.style-two .content h5 .price {
|
||||
margin-left: 10px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
@media(max-width:425px) {
|
||||
@ -8281,63 +8280,6 @@ h6,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ================================================
|
||||
Hakka Menu Tab - specific layout fixes
|
||||
Left column: price wraps to next line below 1399px
|
||||
Right column: untouched at all sizes
|
||||
================================================ */
|
||||
|
||||
/* General gap increase for hakka tab on all sizes */
|
||||
.hakka-menu {
|
||||
--bs-gutter-x: 3rem;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1200px) {
|
||||
.hakka-menu {
|
||||
--bs-gutter-x: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1920px) {
|
||||
.hakka-menu {
|
||||
--bs-gutter-x: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide desc-price by default */
|
||||
.food-menu-item.style-two .content .desc-price {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* LEFT COLUMN ONLY - below 1399px: price drops to after description */
|
||||
@media only screen and (max-width: 1399px) {
|
||||
.hakka-left .food-menu-item.style-two .content h5 .inline-price {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hakka-left .food-menu-item.style-two .content h5 .dots {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.hakka-left .food-menu-item.style-two .content .desc-price {
|
||||
display: block;
|
||||
margin-top: 4px;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #ffb936;
|
||||
line-height: 1.4;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 425px) {
|
||||
.food-menu-item.style-two .content h5 .title,
|
||||
.hakka-left .food-menu-item.style-two .content .desc-price {
|
||||
font-size: 17px;
|
||||
}
|
||||
}
|
||||
|
||||
.popular-menu-wrap {
|
||||
height: 100%;
|
||||
background: white;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user