import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' import './index.css' ReactDOM.createRoot(document.getElementById('root')!).render( , ) [src/index.css] @tailwind base; @tailwind components; @tailwind utilities; @layer base { :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; --card-foreground: 222.2 84% 4.9%; --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; --primary: 142.1 76.2% 36.3%; --primary-foreground: 355.7 100% 97.3%; --secondary: 210 40% 96%; --secondary-foreground: 222.2 84% 4.9%; --muted: 210 40% 96%; --muted-foreground: 215.4 16.3% 46.9%; --accent: 210 40% 96%; --accent-foreground: 222.2 84% 4.9%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; --ring: 142.1 76.2% 36.3%; --radius: 0.5rem; } .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; --card: 222.2 84% 4.9%; --card-foreground: 210 40% 98%; --popover: 222.2 84% 4.9%; --popover-foreground: 210 40% 98%; --primary: 142.1 70.6% 45.3%; --primary-foreground: 144.9 80.4% 10%; --secondary: 217.2 32.6% 17.5%; --secondary-foreground: 210 40% 98%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; --accent: 217.2 32.6% 17.5%; --accent-foreground: 210 40% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; --ring: 142.4 71.8% 29.2%; } } @layer base { * { @apply border-border; } body { @apply bg-background text-foreground; } } @keyframes animate-in { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } .animate-in { animation: animate-in 0.5s ease-out; } [src/lib/utils.ts] import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } [src/utils/solutionTemplates.ts] export interface ProblemCategory { id: string; keywords: string[]; solutions: string[]; } export const problemCategories: ProblemCategory[] = [ { id: 'dishes', keywords: ['dishes', 'sink', 'dirty', 'clean', 'wash', 'kitchen', 'mess'], solutions: [ "Would you be open to a chore chart so we both know what's expected?", "Let's agree on a 24-hour rule for dishes - anything left longer gets washed by whoever used it.", "How about we each take turns doing a full kitchen reset every other day?", "Maybe we could set a reminder for 9 PM to check if dishes need doing?", "What if we invest in a second drying rack to make cleanup easier?" ] }, { id: 'noise', keywords: ['loud', 'music', 'noise', 'quiet', 'night', 'sleep', 'party'], solutions: [ "Could we establish quiet hours from 10 PM to 8 AM on weekdays?", "Would you be willing to use headphones for music after 9 PM?", "Let's create a shared calendar for when we have guests or need quiet time.", "How about we check in with each other before having people over?", "Maybe we could soundproof the common areas with some rugs and curtains?" ] }, { id: 'guests', keywords: ['guests', 'friends', 'people', 'overnight', 'visitors'], solutions: [ "Let's agree to give 24 hours notice before having overnight guests.", "Could we set a limit of 2 nights per week for visitors?", "How about we create a shared calendar for guest schedules?", "Would you be comfortable setting a 'no guests' rule during exam weeks?", "Let's discuss what makes us comfortable with guests in shared spaces." ] }, { id: 'bills', keywords: ['bills', 'money', 'rent', 'utilities', 'pay', 'split'], solutions: [ "Let's set up automatic transfers for bills on the 1st of each month.", "How about we use a shared spreadsheet to track all expenses?", "Could we agree on a buffer amount for unexpected utility increases?", "What if we take turns being responsible for different bills?", "Let's schedule a monthly money check-in to stay on the same page." ] }, { id: 'cleaning', keywords: ['clean', 'mess', 'dirty', 'vacuum', 'bathroom', 'trash'], solutions: [ "Let's create a weekly cleaning schedule with specific tasks for each of us.", "How about we both do a 15-minute tidy-up every evening?", "Could we agree on a 'clean as you go' policy for common areas?", "What if we hire a cleaning service every other week and split the cost?", "Let's set aside Sunday mornings for a joint cleaning session." ] }, { id: 'food', keywords: ['food', 'eat', 'groceries', 'fridge', 'milk', 'steal'], solutions: [ "Let's label our food with our names and purchase dates.", "How about we create separate shelves in the fridge for each person?", "Could we agree to ask before borrowing food, with a 24-hour replacement rule?", "What if we take turns buying shared items like milk and bread?", "Let's use a whiteboard on the fridge to track shared groceries." ] }, { id: 'bathroom', keywords: ['bathroom', 'shower', 'toilet', 'hair', 'time'], solutions: [ "Let's create a bathroom cleaning schedule that rotates weekly.", "How about we agree to a 20-minute limit for showers during morning rush?", "Could we each keep our own caddies to reduce clutter?", "What if we set up a cleaning supplies fund we both contribute to?", "Let's establish a rule about wiping down surfaces after each use." ] }, { id: 'temperature', keywords: ['temperature', 'cold', 'hot', 'thermostat', 'heat', 'ac'], solutions: [ "Could we compromise on 72 degrees as our baseline temperature?", "Let's agree to adjust the thermostat only when both of us are home.", "How about we use fans and personal space heaters for individual comfort?", "What if we set different temperatures for day and night?", "Let's create a seasonal temperature agreement we can revisit." ] }, { id: 'privacy', keywords: ['privacy', 'door', 'knock', 'room', 'enter', 'space'], solutions: [ "Let's agree to always knock before entering closed doors.", "How about we establish a 'do not disturb' signal for when we need alone time?", "Could we set boundaries about borrowing things from each other's rooms?", "What if we create a shared understanding about when our rooms are private vs. shared space?", "Let's respect each other's need for downtime without taking it personally." ] }, { id: 'pets', keywords: ['pet', 'dog', 'cat', 'animal', 'allergy', 'fur'], solutions: [ "Let's create a pet care schedule that's fair to both of us.", "How about we invest in an air purifier to help with allergens?", "Could we agree on pet-free zones in the apartment?", "What if we set up a pet emergency fund for unexpected vet visits?", "Let's establish clear rules about guests bringing their pets over." ] } ]; export const genericSolutions = [ "Have you considered scheduling a calm chat over coffee to discuss what's bothering you?", "Try setting up a weekly 10-minute check-in to address small issues before they grow.", "What if you both wrote down your expectations for shared living and compared notes?", "Consider using 'I feel' statements instead of 'you always' when bringing up concerns.", "Maybe it would help to establish a roommate agreement that covers common friction points." ]; [src/components/ui/button.tsx] import * as React from "react" import { Slot } from "@radix-ui/react-slot" import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const buttonVariants = cva( "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-10 px-4 py-2", sm: "h-9 rounded-md px-3", lg: "h-11 rounded-md px-8", icon: "h-10 w-10", }, }, defaultVariants: { variant: "default", size: "default", }, } ) export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { asChild?: boolean } const Button = React.forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : "button" return ( ) } ) Button.displayName = "Button" export { Button, buttonVariants } [src/components/ui/card.tsx] import * as React from "react" import { cn } from "@/lib/utils" const Card = React.forwardRef>(({ className, ...props }, ref) => (
)) Card.displayName = "Card" const CardHeader = React.forwardRef>(({ className, ...props }, ref) => (
)) CardHeader.displayName = "CardHeader" const CardTitle = React.forwardRef>(({ className, ...props }, ref) => (

)) CardTitle.displayName = "CardTitle" const CardDescription = React.forwardRef>(({ className, ...props }, ref) => (

)) CardDescription.displayName = "CardDescription" const CardContent = React.forwardRef>(({ className, ...props }, ref) => (

)) CardContent.displayName = "CardContent" const CardFooter = React.forwardRef>(({ className, ...props }, ref) => (
)) CardFooter.displayName = "CardFooter" export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } [src/components/ui/textarea.tsx] import * as React from "react" import { cn } from "@/lib/utils" export interface TextareaProps extends React.TextareaHTMLAttributes {} const Textarea = React.forwardRef(({ className, ...props }, ref) => { return (