From 2c48ecd2b4cb602f9bcf158c71459ad430e4cdf5 Mon Sep 17 00:00:00 2001 From: NotII <46204250+NotII@users.noreply.github.com> Date: Thu, 7 Aug 2025 16:05:31 +0100 Subject: [PATCH] Add product applicability controls to promotion forms Introduces product selection and exclusion controls to both new and edit promotion forms, allowing promotions to target all, specific, or all-but-specific products. Adds a reusable ProductSelector component, updates promotion types to support new fields, and adjusts cookie max-age for authentication. Also adds two new business quotes. --- app/api/auth/set-cookie/route.ts | 4 +- app/auth/login/components/LoginForm.tsx | 2 +- app/dashboard/orders/[id]/page.tsx | 4 +- .../promotions/EditPromotionForm.tsx | 111 ++++++++ .../dashboard/promotions/NewPromotionForm.tsx | 111 ++++++++ .../dashboard/promotions/ProductSelector.tsx | 243 ++++++++++++++++++ config/quotes.ts | 182 +++++++------ lib/types/promotion.ts | 13 + 8 files changed, 584 insertions(+), 86 deletions(-) create mode 100644 components/dashboard/promotions/ProductSelector.tsx diff --git a/app/api/auth/set-cookie/route.ts b/app/api/auth/set-cookie/route.ts index c2eb942..f9ca98e 100644 --- a/app/api/auth/set-cookie/route.ts +++ b/app/api/auth/set-cookie/route.ts @@ -31,8 +31,8 @@ export async function POST(req: NextRequest) { const cookieOptions = { // HttpOnly for security - prevents JavaScript access httpOnly: true, - // Valid for 7 days (same as the JWT) - maxAge: 7 * 24 * 60 * 60, + // Valid for 3 hours + maxAge: 3 * 60 * 60, // Only send in requests to our domain path: '/', // Strict same-site policy to prevent CSRF diff --git a/app/auth/login/components/LoginForm.tsx b/app/auth/login/components/LoginForm.tsx index 1cd4894..675df75 100644 --- a/app/auth/login/components/LoginForm.tsx +++ b/app/auth/login/components/LoginForm.tsx @@ -66,7 +66,7 @@ export default function LoginForm() { if (response.ok && data.token) { // Store the token in both cookie and localStorage for redundancy - document.cookie = `Authorization=${data.token}; path=/; Secure; SameSite=Strict; max-age=604800`; + document.cookie = `Authorization=${data.token}; path=/; Secure; SameSite=Strict; max-age=10800`; localStorage.setItem("Authorization", data.token); // Show success notification diff --git a/app/dashboard/orders/[id]/page.tsx b/app/dashboard/orders/[id]/page.tsx index 177c8ad..1af2a60 100644 --- a/app/dashboard/orders/[id]/page.tsx +++ b/app/dashboard/orders/[id]/page.tsx @@ -361,8 +361,6 @@ export default function OrderDetailsPage() { const productNamesMap = await fetchProductNames(productIds, authToken); setProductNames(productNamesMap); - // Add a short timeout to ensure any products still showing as loading - // are marked as deleted/unknown setTimeout(() => { setProductNames(prev => { const newMap = {...prev}; @@ -373,7 +371,7 @@ export default function OrderDetailsPage() { }); return newMap; }); - }, 3000); // 3 second timeout + }, 3000); if (data.status === "paid") { setIsPaid(true); diff --git a/components/dashboard/promotions/EditPromotionForm.tsx b/components/dashboard/promotions/EditPromotionForm.tsx index dd1c4d7..df01694 100644 --- a/components/dashboard/promotions/EditPromotionForm.tsx +++ b/components/dashboard/promotions/EditPromotionForm.tsx @@ -22,6 +22,7 @@ import { Textarea } from '@/components/ui/textarea'; import { toast } from '@/components/ui/use-toast'; import { Promotion, PromotionFormData } from '@/lib/types/promotion'; import { fetchClient } from '@/lib/api'; +import ProductSelector from './ProductSelector'; // Form schema validation with Zod (same as NewPromotionForm) const formSchema = z.object({ @@ -47,6 +48,9 @@ const formSchema = z.object({ startDate: z.string().optional(), endDate: z.string().nullable().optional(), description: z.string().max(200, 'Description cannot exceed 200 characters').optional(), + blacklistedProducts: z.array(z.string()).default([]), + applicableProducts: z.enum(['all', 'specific', 'exclude_specific']).default('all'), + specificProducts: z.array(z.string()).default([]), }); interface EditPromotionFormProps { @@ -78,6 +82,9 @@ export default function EditPromotionForm({ promotion, onSuccess, onCancel }: Ed description: promotion.description, startDate: formatDateForInput(promotion.startDate), endDate: formatDateForInput(promotion.endDate), + blacklistedProducts: promotion.blacklistedProducts || [], + applicableProducts: promotion.applicableProducts || 'all', + specificProducts: promotion.specificProducts || [], }, }); @@ -308,6 +315,110 @@ export default function EditPromotionForm({ promotion, onSuccess, onCancel }: Ed )} /> + {/* Product Applicability Section */} +
+

Product Applicability

+ + ( + + Apply Promotion To + + +
+ + +
+
+ + +
+
+ + +
+
+
+ +
+ )} + /> + + {/* Show blacklist selector for "all" and "exclude_specific" modes */} + {(form.watch('applicableProducts') === 'all' || form.watch('applicableProducts') === 'exclude_specific') && ( + ( + + + {form.watch('applicableProducts') === 'all' + ? 'Exclude Products (Blacklist)' + : 'Products to Exclude'} + + + + + + {form.watch('applicableProducts') === 'all' + ? 'Select products that should not be eligible for this promotion' + : 'Select products to exclude in addition to those selected above'} + + + + )} + /> + )} + + {/* Show specific products selector for "specific" and "exclude_specific" modes */} + {(form.watch('applicableProducts') === 'specific' || form.watch('applicableProducts') === 'exclude_specific') && ( + ( + + + {form.watch('applicableProducts') === 'specific' + ? 'Select Specific Products' + : 'Products to Exclude'} + + + + + + {form.watch('applicableProducts') === 'specific' + ? 'Only selected products will be eligible for this promotion' + : 'Selected products will be excluded from this promotion'} + + + + )} + /> + )} +
+ + {/* Product Applicability Section */} +
+

Product Applicability

+ + ( + + Apply Promotion To + + +
+ + +
+
+ + +
+
+ + +
+
+
+ +
+ )} + /> + + {/* Show blacklist selector for "all" and "exclude_specific" modes */} + {(form.watch('applicableProducts') === 'all' || form.watch('applicableProducts') === 'exclude_specific') && ( + ( + + + {form.watch('applicableProducts') === 'all' + ? 'Exclude Products (Blacklist)' + : 'Products to Exclude'} + + + + + + {form.watch('applicableProducts') === 'all' + ? 'Select products that should not be eligible for this promotion' + : 'Select products to exclude in addition to those selected above'} + + + + )} + /> + )} + + {/* Show specific products selector for "specific" and "exclude_specific" modes */} + {(form.watch('applicableProducts') === 'specific' || form.watch('applicableProducts') === 'exclude_specific') && ( + ( + + + {form.watch('applicableProducts') === 'specific' + ? 'Select Specific Products' + : 'Products to Exclude'} + + + + + + {form.watch('applicableProducts') === 'specific' + ? 'Only selected products will be eligible for this promotion' + : 'Selected products will be excluded from this promotion'} + + + + )} + /> + )} +
+ void; + placeholder?: string; + maxHeight?: string; +} + +export default function ProductSelector({ + selectedProductIds, + onSelectionChange, + placeholder = "Select products...", + maxHeight = "200px" +}: ProductSelectorProps) { + const [products, setProducts] = useState([]); + const [loading, setLoading] = useState(false); + const [open, setOpen] = useState(false); + const [searchTerm, setSearchTerm] = useState(''); + const triggerRef = useRef(null); + + // Handle escape key to close dropdown + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape' && open) { + setOpen(false); + } + }; + + if (open) { + document.addEventListener('keydown', handleKeyDown); + return () => document.removeEventListener('keydown', handleKeyDown); + } + }, [open]); + + // Fetch products when component mounts + useEffect(() => { + const fetchProducts = async () => { + setLoading(true); + try { + const response = await fetchClient('/promotions/products/all'); + setProducts(response); + } catch (error) { + console.error('Error fetching products:', error); + } finally { + setLoading(false); + } + }; + + fetchProducts(); + }, []); + + // Filter products based on search term + const filteredProducts = products.filter(product => + product.name.toLowerCase().includes(searchTerm.toLowerCase()) || + product.description?.toLowerCase().includes(searchTerm.toLowerCase()) + ); + + // Get selected products for display + const selectedProducts = products.filter(product => + selectedProductIds.includes(product._id) + ); + + const handleProductToggle = (productId: string) => { + const updatedSelection = selectedProductIds.includes(productId) + ? selectedProductIds.filter(id => id !== productId) + : [...selectedProductIds, productId]; + + onSelectionChange(updatedSelection); + }; + + const handleRemoveProduct = (productId: string) => { + onSelectionChange(selectedProductIds.filter(id => id !== productId)); + }; + + const clearAll = () => { + onSelectionChange([]); + }; + + return ( +
+
+ + + {/* Dropdown using absolute positioning within relative container */} + {open && ( +
+ {/* Search Header */} +
+ + setSearchTerm(e.target.value)} + className="border-0 bg-transparent p-0 h-auto focus-visible:ring-0 focus-visible:ring-offset-0" + autoFocus + /> +
+ + {/* Products List */} + + {loading ? ( +
+ Loading products... +
+ ) : filteredProducts.length === 0 ? ( +
+ {searchTerm ? 'No products found matching your search.' : 'No products found.'} +
+ ) : ( +
+ {filteredProducts.map((product) => ( +
{ + e.preventDefault(); + e.stopPropagation(); + handleProductToggle(product._id); + }} + className="flex items-center gap-3 p-2 hover:bg-accent rounded-sm cursor-pointer transition-colors" + > +
+ {selectedProductIds.includes(product._id) && ( + + )} +
+
+
{product.name}
+ {product.description && ( +
+ {product.description} +
+ )} +
+ {!product.enabled && ( + + Disabled + + )} +
+ ))} +
+ )} +
+
+ )} + + {/* Backdrop to close dropdown */} + {open && ( +
setOpen(false)} + /> + )} +
+ + {/* Selected products display */} + {selectedProducts.length > 0 && ( +
+
+ Selected Products: + +
+
+ {selectedProducts.map((product) => ( + + {product.name} + + + ))} +
+
+ )} +
+ ); +} \ No newline at end of file diff --git a/config/quotes.ts b/config/quotes.ts index 85ab63c..f01fffa 100644 --- a/config/quotes.ts +++ b/config/quotes.ts @@ -4,82 +4,108 @@ export interface Quote { } export const businessQuotes: Quote[] = [ - // Steve Jobs quotes - { text: "Your work is going to fill a large part of your life, and the only way to be truly satisfied is to do what you believe is great work.", author: "Steve Jobs" }, - { text: "Innovation distinguishes between a leader and a follower.", author: "Steve Jobs" }, - { text: "If you really look closely, most overnight successes took a long time.", author: "Steve Jobs" }, - - // Entrepreneurs and CEOs - { text: "Your most unhappy customers are your greatest source of learning.", author: "Bill Gates" }, - { text: "The way to get started is to quit talking and begin doing.", author: "Walt Disney" }, - { text: "Opportunities don't happen. You create them.", author: "Chris Grosser" }, - { text: "The best way to predict the future is to create it.", author: "Peter Drucker" }, - { text: "If you are not willing to risk the usual, you will have to settle for the ordinary.", author: "Jim Rohn" }, - { text: "Chase the vision, not the money; the money will end up following you.", author: "Tony Hsieh" }, - { text: "It's not about ideas. It's about making ideas happen.", author: "Scott Belsky" }, - { text: "If you do build a great experience, customers tell each other about that. Word of mouth is very powerful.", author: "Jeff Bezos" }, - - // Persistence and growth - { text: "The secret of getting ahead is getting started.", author: "Mark Twain" }, - { text: "Success is not final; failure is not fatal: It is the courage to continue that counts.", author: "Winston Churchill" }, - { text: "Don't watch the clock; do what it does. Keep going.", author: "Sam Levenson" }, - { text: "The future belongs to those who believe in the beauty of their dreams.", author: "Eleanor Roosevelt" }, - { text: "If you can't fly, then run. If you can't run, then walk. If you can't walk, then crawl. But whatever you do, you have to keep moving forward.", author: "Martin Luther King Jr." }, - - // Risk and innovation - { text: "The biggest risk is not taking any risk. In a world that's changing quickly, the only strategy that is guaranteed to fail is not taking risks.", author: "Mark Zuckerberg" }, - { text: "I have not failed. I've just found 10,000 ways that won't work.", author: "Thomas Edison" }, - { text: "What would you do if you weren't afraid?", author: "Sheryl Sandberg" }, - { text: "When everything seems to be going against you, remember that the airplane takes off against the wind, not with it.", author: "Henry Ford" }, - { text: "If you're not embarrassed by the first version of your product, you've launched too late.", author: "Reid Hoffman" }, - - // Quality and execution - { text: "The only place where success comes before work is in the dictionary.", author: "Vidal Sassoon" }, - { text: "Make every detail perfect and limit the number of details to perfect.", author: "Jack Dorsey" }, - { text: "There's no shortage of remarkable ideas, what's missing is the will to execute them.", author: "Seth Godin" }, - { text: "Always deliver more than expected.", author: "Larry Page" }, - { text: "Your reputation is more important than your paycheck, and your integrity is worth more than your career.", author: "Ryan Freitas" }, - - // Teamwork and determination - { text: "No matter how brilliant your mind or strategy, if you're playing a solo game, you'll always lose out to a team.", author: "Reid Hoffman" }, - { text: "If you want to achieve greatness stop asking for permission.", author: "Anonymous" }, - { text: "Things work out best for those who make the best of how things work out.", author: "John Wooden" }, - { text: "The most valuable businesses of coming decades will be built by entrepreneurs who seek to empower people rather than try to make them obsolete.", author: "Peter Thiel" }, - - // Additional quotes - Vision and leadership - { text: "Leadership is the capacity to translate vision into reality.", author: "Warren Bennis" }, - { text: "A goal without a plan is just a wish.", author: "Antoine de Saint-Exupéry" }, - { text: "Good business leaders create a vision, articulate the vision, passionately own the vision, and relentlessly drive it to completion.", author: "Jack Welch" }, - - // Additional quotes - Risk, failure, and learning - { text: "Fail often so you can succeed sooner.", author: "Tom Kelley" }, - { text: "Don’t worry about failure; you only have to be right once.", author: "Drew Houston" }, - { text: "In the middle of difficulty lies opportunity.", author: "Albert Einstein" }, - { text: "Risk more than others think is safe. Dream more than others think is practical.", author: "Howard Schultz" }, - - // Additional quotes - Action and hustle - { text: "Ideas are easy. Implementation is hard.", author: "Guy Kawasaki" }, - { text: "Success usually comes to those who are too busy to be looking for it.", author: "Henry David Thoreau" }, - { text: "Done is better than perfect.", author: "Sheryl Sandberg" }, - { text: "Action is the foundational key to all success.", author: "Pablo Picasso" }, - - // Additional quotes - Customer and product - { text: "People don't buy what you do; they buy why you do it.", author: "Simon Sinek" }, - { text: "The customer is the most important part of the production line.", author: "W. Edwards Deming" }, - { text: "Make something people want and sell that, or be someone people need and sell yourself.", author: "Naval Ravikant" }, - - // Additional quotes - Resilience and mindset - { text: "Success is walking from failure to failure with no loss of enthusiasm.", author: "Winston Churchill" }, - { text: "Whether you think you can or you think you can’t, you’re right.", author: "Henry Ford" }, - { text: "Strength and growth come only through continuous effort and struggle.", author: "Napoleon Hill" }, - { text: "Believe you can and you're halfway there.", author: "Theodore Roosevelt" }, - - // Additional quotes - Money and value - { text: "Try not to become a man of success, but rather try to become a man of value.", author: "Albert Einstein" }, - { text: "Price is what you pay. Value is what you get.", author: "Warren Buffett" }, + { text: 'Your work is going to fill a large part of your life, and the only way to be truly satisfied is to do what you believe is great work.', author: 'Steve Jobs' }, + { text: 'Innovation distinguishes between a leader and a follower.', author: 'Steve Jobs' }, + { text: 'If you really look closely, most overnight successes took a long time.', author: 'Steve Jobs' }, + { text: 'The only way to do great work is to love what you do.', author: 'Steve Jobs' }, + { text: 'Get closer than ever to your customers. So close that you tell them what they need well before they realize it themselves.', author: 'Steve Jobs' }, + { text: 'Innovation is the ability to see change as an opportunity – not a threat.', author: 'Steve Jobs' }, + { text: 'Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple.', author: 'Steve Jobs' }, + { text: 'Your most unhappy customers are your greatest source of learning.', author: 'Bill Gates' }, + { text: 'As we look ahead into the next century, leaders will be those who empower others.', author: 'Bill Gates' }, + { text: 'The way to get started is to quit talking and begin doing.', author: 'Walt Disney' }, + { text: 'Chase the vision, not the money; the money will end up following you.', author: 'Tony Hsieh' }, + { text: "Opportunities don't happen. You create them.", author: 'Chris Grosser' }, + { text: 'The best way to predict the future is to create it.', author: 'Peter Drucker' }, + { text: 'Culture eats strategy for breakfast.', author: 'Peter Drucker' }, + { text: 'Entrepreneurship is neither a science nor an art. It is a practice.', author: 'Peter Drucker' }, + { text: 'If you are not willing to risk the usual, you will have to settle for the ordinary.', author: 'Jim Rohn' }, + { text: "It's not about ideas. It's about making ideas happen.", author: 'Scott Belsky' }, + { text: 'If you do build a great experience, customers tell each other about that. Word of mouth is very powerful.', author: 'Jeff Bezos' }, + { text: 'Work like hell. I mean you just have to put in 80 to 100 hour weeks every week.', author: 'Elon Musk' }, + { text: 'When something is important enough, you do it even if the odds are not in your favor.', author: 'Elon Musk' }, + { text: 'The secret of getting ahead is getting started.', author: 'Mark Twain' }, + { text: 'Success is not final; failure is not fatal: It is the courage to continue that counts.', author: 'Winston Churchill' }, + { text: 'Success is walking from failure to failure with no loss of enthusiasm.', author: 'Winston Churchill' }, + { text: 'Don’t watch the clock; do what it does. Keep going.', author: 'Sam Levenson' }, + { text: 'The future belongs to those who believe in the beauty of their dreams.', author: 'Eleanor Roosevelt' }, + { text: "Believe you can and you're halfway there.", author: 'Theodore Roosevelt' }, + { text: "If you can't fly, then run. If you can't run, then walk. If you can't walk, then crawl. But whatever you do, you have to keep moving forward.", author: 'Martin Luther King Jr.' }, + { text: 'Strength and growth come only through continuous effort and struggle.', author: 'Napoleon Hill' }, + { text: 'The biggest risk is not taking any risk.', author: 'Mark Zuckerberg' }, + { text: 'Move fast and break things. Unless you are breaking stuff, you are not moving fast enough.', author: 'Mark Zuckerberg' }, + { text: "I have not failed. I've just found 10,000 ways that won't work.", author: 'Thomas Edison' }, + { text: 'Vision without execution is hallucination.', author: 'Thomas Edison' }, + { text: "What would you do if you weren't afraid?", author: 'Sheryl Sandberg' }, + { text: 'Done is better than perfect.', author: 'Sheryl Sandberg' }, + { text: 'When everything seems to be going against you, remember that the airplane takes off against the wind, not with it.', author: 'Henry Ford' }, + { text: 'Whether you think you can or you think you can’t, you’re right.', author: 'Henry Ford' }, + { text: "If you're not embarrassed by the first version of your product, you've launched too late.", author: 'Reid Hoffman' }, + { text: 'The only place where success comes before work is in the dictionary.', author: 'Vidal Sassoon' }, + { text: 'Make every detail perfect and limit the number of details to perfect.', author: 'Jack Dorsey' }, + { text: "There's no shortage of remarkable ideas, what's missing is the will to execute them.", author: 'Seth Godin' }, + { text: 'Always deliver more than expected.', author: 'Larry Page' }, + { text: 'Your reputation is more important than your paycheck.', author: 'Ryan Freitas' }, + { text: 'Ideas are easy. Implementation is hard.', author: 'Guy Kawasaki' }, + { text: 'Action is the foundational key to all success.', author: 'Pablo Picasso' }, + { text: 'Success usually comes to those who are too busy to be looking for it.', author: 'Henry David Thoreau' }, + { text: "No matter how brilliant your mind or strategy, if you're playing a solo game, you'll always lose out to a team.", author: 'Reid Hoffman' }, + { text: 'A leader is one who knows the way, goes the way, and shows the way.', author: 'John C. Maxwell' }, + { text: 'Leadership is the capacity to translate vision into reality.', author: 'Warren Bennis' }, + { text: 'Good business leaders create a vision, articulate the vision, passionately own the vision, and relentlessly drive it to completion.', author: 'Jack Welch' }, + { text: 'The function of leadership is to produce more leaders, not more followers.', author: 'Ralph Nader' }, + { text: 'A goal without a plan is just a wish.', author: 'Antoine de Saint-Exupéry' }, + { text: 'Be so good they can’t ignore you.', author: 'Steve Martin' }, + { text: 'Play long-term games with long-term people.', author: 'Naval Ravikant' }, + { text: 'Make something people want and sell that.', author: 'Paul Graham' }, + { text: 'It’s not whether you get knocked down, it’s whether you get up.', author: 'Vince Lombardi' }, + { text: 'Hardships often prepare ordinary people for an extraordinary destiny.', author: 'C.S. Lewis' }, + { text: 'Resilience is knowing that you are the only one that has the power and the responsibility to pick yourself up.', author: 'Mary Holloway' }, + { text: 'Success is how high you bounce when you hit bottom.', author: 'George S. Patton' }, + { text: "People don't buy what you do; they buy why you do it.", author: 'Simon Sinek' }, + { text: 'The customer is the most important part of the production line.', author: 'W. Edwards Deming' }, + { text: "Customers may forget what you said but they'll never forget how you made them feel.", author: 'Maya Angelou' }, + { text: 'The true entrepreneur is a doer, not a dreamer.', author: 'Nolan Bushnell' }, + { text: 'Entrepreneurs are willing to work 80 hours a week to avoid working 40 hours a week.', author: 'Lori Greiner' }, + { text: 'Build something 100 people love, not something 1 million people kind of like.', author: 'Brian Chesky' }, + { text: 'Risk more than others think is safe. Dream more than others think is practical.', author: 'Howard Schultz' }, + { text: 'Fail often so you can succeed sooner.', author: 'Tom Kelley' }, + { text: 'Don’t worry about failure; you only have to be right once.', author: 'Drew Houston' }, + { text: 'Try not to become a man of success, but rather try to become a man of value.', author: 'Albert Einstein' }, + { text: "Compound interest is the eighth wonder of the world. He who understands it, earns it; he who doesn't, pays it.", author: 'Albert Einstein' }, + { text: 'In the middle of difficulty lies opportunity.', author: 'Albert Einstein' }, + { text: 'Price is what you pay. Value is what you get.', author: 'Warren Buffett' }, + { text: 'The best way to predict the future is to invent it.', author: 'Alan Kay' }, + { text: "Strategy is about making choices, trade-offs; it's about deliberately choosing to be different.", author: 'Michael Porter' }, + { text: 'Growth and comfort do not coexist.', author: 'Ginni Rometty' }, + { text: 'Disruption is about risk-taking, trusting your intuition, and rejecting the way things are supposed to be.', author: 'Whitney Wolfe Herd' }, + { text: "Don't be afraid to give up the good to go for the great.", author: 'John D. Rockefeller' }, + { text: 'A goal is a dream with a deadline.', author: 'Napoleon Hill' }, + { text: 'The man who moves a mountain begins by carrying away small stones.', author: 'Confucius' }, + { text: 'Every strike brings me closer to the next home run.', author: 'Babe Ruth' }, + { text: 'Do not be embarrassed by your failures, learn from them and start again.', author: 'Richard Branson' }, + { text: "Business opportunities are like buses, there's always another one coming.", author: 'Richard Branson' }, + { text: 'The most dangerous poison is the feeling of achievement. The antidote is to every evening think what can be done better tomorrow.', author: 'Ingvar Kamprad' }, + { text: 'Don’t count the days, make the days count.', author: 'Muhammad Ali' }, + { text: 'To win big, you sometimes have to take big risks.', author: 'Bill Gates' }, + { text: "If everything seems under control, you're not going fast enough.", author: 'Mario Andretti' }, + { text: "If you really want to do something, you'll find a way. If you don't, you'll find an excuse.", author: 'Jim Rohn' }, + { text: 'One day or day one. You decide.', author: 'Anonymous' }, + { text: 'Don’t be busy. Be productive.', author: 'Anonymous' }, + { text: 'Success isn’t owned, it’s leased. And rent is due every day.', author: 'J.J. Watt' }, + { text: 'Never give up on a dream just because of the time it will take to accomplish it. The time will pass anyway.', author: 'Earl Nightingale' }, + { text: "If you don't build your dream, someone else will hire you to help them build theirs.", author: 'Tony Gaskins' }, + { text: 'The way to get ahead is to start now. The secret is to get started.', author: 'Mark Twain' }, + { text: 'Success is not in what you have, but who you are.', author: 'Bo Bennett' }, + { text: "It's fine to celebrate success but it is more important to heed the lessons of failure.", author: 'Bill Gates' }, + { text: 'Success is getting what you want. Happiness is wanting what you get.', author: 'Dale Carnegie' }, + { text: 'Work until you no longer have to introduce yourself.', author: 'Anonymous' }, + { text: 'Don’t limit your challenges. Challenge your limits.', author: 'Jerry Dunn' }, + { text: "Don't settle. Don't finish crappy books. If you don't like the menu, leave the restaurant. If you're not on the right path, get off it.", author: 'Chris Brogan' }, + { text: 'A person who never made a mistake never tried anything new.', author: 'Albert Einstein' }, + { text: 'Business has only two functions — marketing and innovation.', author: 'Peter Drucker' }, ]; -// For backward compatibility with existing code export const quotes = businessQuotes; export default businessQuotes; @@ -99,11 +125,7 @@ export function getRandomQuoteByAuthor(author: string): Quote { const authorQuotes = businessQuotes.filter(quote => quote.author.toLowerCase() === author.toLowerCase() ); - - if (authorQuotes.length === 0) { - return getRandomQuote(); - } - + if (authorQuotes.length === 0) return getRandomQuote(); const randomIndex = Math.floor(Math.random() * authorQuotes.length); return authorQuotes[randomIndex]; } @@ -115,4 +137,4 @@ export function getQuotesByTheme(keyword: string): Quote[] { return businessQuotes.filter(quote => quote.text.toLowerCase().includes(keyword.toLowerCase()) ); -} +} \ No newline at end of file diff --git a/lib/types/promotion.ts b/lib/types/promotion.ts index 398c750..c2ba4f1 100644 --- a/lib/types/promotion.ts +++ b/lib/types/promotion.ts @@ -11,6 +11,9 @@ export interface Promotion { startDate: string; endDate: string | null; description: string; + blacklistedProducts: string[]; + applicableProducts: 'all' | 'specific' | 'exclude_specific'; + specificProducts: string[]; createdAt: string; updatedAt: string; } @@ -25,4 +28,14 @@ export interface PromotionFormData { startDate: string; endDate: string | null; description: string; + blacklistedProducts: string[]; + applicableProducts: 'all' | 'specific' | 'exclude_specific'; + specificProducts: string[]; +} + +export interface Product { + _id: string; + name: string; + description: string; + enabled: boolean; } \ No newline at end of file