Loading...

Animal Villa

animalvilla.org

{{ authError }}

Animal Villa

animalvilla.org

No animals currently boarding

Check in a pet to get started

🐶

{{ dog.dogName }}

Boarding {{ visitCountMap[getDogKey(dog.dogName, dog.ownerName)] || 1 }} visit{{ (visitCountMap[getDogKey(dog.dogName, dog.ownerName)] || 1) !== 1 ? 's' : '' }}

Owner: {{ dog.ownerName }}

Breed

{{ dog.breed }}

Age

{{ dog.age }}

Checked In

{{ formatDate(dog.checkInDate) }}

Expected Out

{{ formatDate(dog.expectedCheckOut) }}

$${{ dog.ratePerNight }}/night

$${{ getEstimatedTotal(dog.checkInDate, dog.expectedCheckOut, dog.ratePerNight).toFixed(2) }}

{{ getEstimatedTotal(dog.checkInDate, dog.expectedCheckOut, dog.ratePerNight) }} nights

{{ dog.documentName }}

Notes

{{ dog.notes }}

📱 {{ dog.ownerPhone }} 🕐 {{ formatRelative(dog.checkInDate) }}

Check In a New Pet

🐶

{{ dog.dogName }}

{{ dog.ownerName }} · {{ dog.breed }}

{{ dog.visitCount }} visit{{ dog.visitCount !== 1 ? 's' : '' }}
Dog photo

Add photo

×
Estimated Total ${{ calculatedTotal.toFixed(2) }}

{{ calculatedNights }} night{{ calculatedNights !== 1 ? 's' : '' }} × ${{ form.ratePerNight || 0 }}/night

{{ uploadedDocName }}

No conversations yet

Chat threads appear when you check in a dog

{{ chatVisits.length }} conversation{{ chatVisits.length !== 1 ? 's' : '' }}

🐶

{{ cv.visit.dogName }}

{{ cv.visit.ownerName }}

{{ formatMessageTime(cv.lastMessage.createdAt) }}

{{ cv.unreadCount }}

{{ cv.lastMessage.senderId === user.uid ? 'You' : cv.visit.ownerName }}: {{ cv.lastMessage.text }}

No messages yet — start the conversation

🐶

{{ selectedChatVisit.dogName }}

{{ selectedChatVisit.ownerName }}

No messages yet. Say hello!

{{ msg.text }}

{{ formatMessageTime(msg.createdAt) }}

No history yet

Completed visits will appear here

{{ history.length }} completed visit{{ history.length !== 1 ? 's' : '' }}

{{ visit.dogName }}

Completed {{ visitCountMap[getDogKey(visit.dogName, visit.ownerName)] || 1 }} visit{{ (visitCountMap[getDogKey(visit.dogName, visit.ownerName)] || 1) !== 1 ? 's' : '' }}

{{ visit.ownerName }}

{{ formatDate(visit.checkInDate) }} → {{ formatDate(visit.checkOutDate) }}

{{ getStayDuration(visit.checkInDate, visit.checkOutDate) }}

{{ calendarImportResult }}

Calendar Sync Error

{{ calendarError }}

Import ICS File

Export your calendar as an ICS file and upload it here. Events with title format PetName (OwnerName) will be detected. Use the search box below to find specific events.

{{ uploadedICSName }}
or paste ICS text
Advanced: Google Calendar API sync (requires Cloud Console setup)

This method requires enabling the Google Calendar API in your Google Cloud project. If you don't have Cloud Console access, use the ICS file upload above instead.

Sign in with Google Calendar access to sync.

{{ filteredEvents.length }} of {{ calendarEvents.length }} Event{{ calendarEvents.length !== 1 ? 's' : '' }}

Filtered by "{{ calendarFilter }}"

{{ ev.petName }}

Owner: {{ ev.ownerName }}

📅 {{ ev.checkInDate }} {{ ev.checkInTime || '' }} 📆 {{ ev.checkOutDate }} {{ ev.checkOutTime || '' }} {{ ev.originalTitle }}

Check Out {{ selectedDog?.dogName }}

Confirm check-out details

Final Total ${{ calcCheckoutTotal().toFixed(2) }}

{{ calcCheckoutNights() }} night{{ calcCheckoutNights() !== 1 ? 's' : '' }} × ${{ selectedDog.ratePerNight }}/night

Edit Visit

Update details for {{ editForm.dogName || 'this visit' }}

Dog photo

Add photo

×
{{ editFormDocName }}
🐶

{{ selectedDogProfile.dogName }}

Owner: {{ selectedDogProfile.ownerName }}

{{ dogProfileVisits.length }} visit{{ dogProfileVisits.length !== 1 ? 's' : '' }} total

Breed{{ selectedDogProfile.breed }}
Age{{ selectedDogProfile.age }}
Phone{{ selectedDogProfile.ownerPhone }}
Rate${{ selectedDogProfile.ratePerNight }}/night

Notes

{{ selectedDogProfile.notes }}

Visit History

No visits found
{{ v.status === 'checked_in' ? 'Boarding' : 'Completed' }} ${{ v.ratePerNight }}/night

{{ formatDate(v.checkInDate) }} → {{ formatDate(v.checkOutDate) }}

{{ getStayDuration(v.checkInDate, v.checkOutDate || v.expectedCheckOut) }}

{{ toast.message }}