+ {/* Left image panel */}
+
+
+ {/* Right form panel */}
+
+
+
+
Register Your Organization
+
+ Create your organization account and start coordinating volunteers.
+
+
+
+
+
+
+
+ )
+}
diff --git a/app/routes/_marketing+/privacy.tsx b/app/routes/_marketing+/privacy.tsx
index 3a1fee2..7ca600a 100644
--- a/app/routes/_marketing+/privacy.tsx
+++ b/app/routes/_marketing+/privacy.tsx
@@ -3,16 +3,16 @@ import { type V2_MetaFunction } from '@remix-run/node'
export const meta: V2_MetaFunction = () => {
return [
{
- title: 'Privacy Policy | TrotTrack.org',
+ title: 'Privacy Policy | thebarnaz.com',
},
{
property: 'og:title',
- content: 'Privacy Policy | TrotTrack.org',
+ content: 'Privacy Policy | thebarnaz.com',
},
{
name: 'description',
content:
- 'Read our Privacy Policy for TrotTrack.org, a nonprofit equestrian volunteer system that connects volunteers with equestrian organizations.',
+ 'Read our Privacy Policy for thebarnaz.com, a nonprofit animal volunteer management system that connects volunteers with animal-assisted therapy organizations.',
},
]
}
diff --git a/app/routes/_marketing+/tos.tsx b/app/routes/_marketing+/tos.tsx
index 51dd935..ca0439b 100644
--- a/app/routes/_marketing+/tos.tsx
+++ b/app/routes/_marketing+/tos.tsx
@@ -3,16 +3,16 @@ import { type V2_MetaFunction } from '@remix-run/node'
export const meta: V2_MetaFunction = () => {
return [
{
- title: 'Terms of Service | TrotTrack.org',
+ title: 'Terms of Service | thebarnaz.com',
},
{
property: 'og:title',
- content: 'Terms of Service | TrotTrack.org',
+ content: 'Terms of Service | thebarnaz.com',
},
{
name: 'description',
content:
- 'Read or Terms of Service for TrotTrack.org, a nonprofit equestrian volunteer system that connects volunteers with equestrian organizations.',
+ 'Read our Terms of Service for thebarnaz.com, a nonprofit animal volunteer management system that connects volunteers with animal-assisted therapy organizations.',
},
]
}
@@ -28,7 +28,7 @@ export default function TermsOfServiceRoute() {
1. Acceptance of Terms
- These terms of service govern your use of TrotTrack.org. By accessing
+ These terms of service govern your use of thebarnaz.com. By accessing
or using our website, you acknowledge that you have read, understood,
and agree to be bound by these terms.
@@ -36,8 +36,8 @@ export default function TermsOfServiceRoute() {
2. Description of Services
- TrotTrack.org is a nonprofit equestrian volunteer system that connects
- volunteers with equestrian organizations. Our services include
+ thebarnaz.com is a nonprofit animal volunteer management system that connects
+ volunteers with animal-assisted therapy organizations. Our services include
providing a platform for volunteers to find and sign up for volunteer
opportunities, and for organizations to manage their volunteer
programs.
@@ -45,7 +45,7 @@ export default function TermsOfServiceRoute() {
3. User Responsibilities
-
As a user of TrotTrack.org, you agree to:
+
As a user of thebarnaz.com, you agree to:
Provide accurate and complete information when creating an account
@@ -57,25 +57,25 @@ export default function TermsOfServiceRoute() {
Respect the privacy and rights of other users
Not engage in any activity that may disrupt or interfere with the
- proper functioning of TrotTrack.org
+ proper functioning of thebarnaz.com
4. Intellectual Property
- All content and materials on TrotTrack.org, including but not limited
+ All content and materials on thebarnaz.com, including but not limited
to text, graphics, logos, images, and software, are the property of
- TrotTrack.org or its licensors and are protected by intellectual
+ thebarnaz.com or its licensors and are protected by intellectual
property laws. You may not reproduce, distribute, modify, or create
derivative works of any content without prior written consent from
- TrotTrack.org.
+ thebarnaz.com.
5. Limitation of Liability
- TrotTrack.org and its affiliates shall not be liable for any direct,
+ thebarnaz.com and its affiliates shall not be liable for any direct,
indirect, incidental, special, or consequential damages arising out of
or in connection with your use of the website or services.
@@ -84,11 +84,11 @@ export default function TermsOfServiceRoute() {
6. Governing Law
These terms of service shall be governed by and construed in
- accordance with the laws of the jurisdiction in which TrotTrack.org
+ accordance with the laws of the jurisdiction in which thebarnaz.com
operates.
- By using TrotTrack.org, you agree to these terms of service. If you do
+ By using thebarnaz.com, you agree to these terms of service. If you do
not agree with any part of these terms, please do not use our website
or services.
diff --git a/app/routes/admin+/_horses+/horses.delete.$horseId.tsx b/app/routes/admin+/_animals+/animals.delete.$animalId.tsx
similarity index 74%
rename from app/routes/admin+/_horses+/horses.delete.$horseId.tsx
rename to app/routes/admin+/_animals+/animals.delete.$animalId.tsx
index a3e9828..f01187b 100644
--- a/app/routes/admin+/_horses+/horses.delete.$horseId.tsx
+++ b/app/routes/admin+/_animals+/animals.delete.$animalId.tsx
@@ -20,6 +20,7 @@ import {
} from '@remix-run/react'
import { json, type DataFunctionArgs } from '@remix-run/node'
import { requireAdmin } from '~/utils/permissions.server.ts'
+import { requireOrgMember } from '~/utils/auth.server.ts'
import { prisma } from '~/utils/db.server.ts'
import invariant from 'tiny-invariant'
import { conform, useForm } from '@conform-to/react'
@@ -31,35 +32,37 @@ import { z } from 'zod'
export const loader = async ({ request, params }: DataFunctionArgs) => {
await requireAdmin(request)
- invariant(params.horseId, 'Missing horse id')
- const horse = await prisma.horse.findUnique({ where: { id: params.horseId } })
- if (!horse) {
+ const { orgId } = await requireOrgMember(request)
+ invariant(params.animalId, 'Missing animal id')
+ const animal = await prisma.animal.findFirst({ where: { id: params.animalId, orgId } })
+ if (!animal) {
throw new Response('not found', { status: 404 })
}
- return json({ horse })
+ return json({ animal })
}
-export const deleteHorseFormSchema = z.object({
+export const deleteAnimalFormSchema = z.object({
name: z
.string()
.min(1, {
message:
- 'You must enter the name of this horse to delete it from the database.',
+ 'You must enter the name of this animal to delete it from the database.',
}),
})
export async function action({ request, params }: DataFunctionArgs) {
await requireAdmin(request)
- invariant(params.horseId, 'Missing horse id')
+ const { orgId } = await requireOrgMember(request)
+ invariant(params.animalId, 'Missing animal id')
const formData = await request.formData()
- const horse = await prisma.horse.findUnique({ where: { id: params.horseId } })
- if (!horse) {
+ const animal = await prisma.animal.findFirst({ where: { id: params.animalId, orgId } })
+ if (!animal) {
throw new Response('not found', { status: 404 })
}
const submission = await parse(formData, {
async: true,
- schema: deleteHorseFormSchema.superRefine(async ({ name }, ctx) => {
- if (horse.name != name) {
+ schema: deleteAnimalFormSchema.superRefine(async ({ name }, ctx) => {
+ if (animal.name != name) {
ctx.addIssue({
path: ['name'],
code: 'custom',
@@ -82,26 +85,26 @@ export async function action({ request, params }: DataFunctionArgs) {
)
}
- let deletedHorse
+ let deletedAnimal
try {
- deletedHorse = await prisma.horse.delete({
- where: { id: params.horseId },
+ deletedAnimal = await prisma.animal.delete({
+ where: { id: params.animalId },
})
} catch {
- return redirectWithToast('/admin/horses', {
+ return redirectWithToast('/admin/animals', {
title: 'Error',
variant: 'destructive',
- description: 'Failed to delete horse',
+ description: 'Failed to delete animal',
})
}
- return redirectWithToast('/admin/horses', {
+ return redirectWithToast('/admin/animals', {
title: 'Success',
- description: `Deleted horse ${deletedHorse.name}`,
+ description: `Deleted animal ${deletedAnimal.name}`,
})
}
-export default function DeleteHorse() {
+export default function DeleteAnimal() {
const data = useLoaderData() || {}
const actionData = useActionData()
const [open, setOpen] = useState(true)
@@ -120,7 +123,7 @@ export default function DeleteHorse() {
navigate('..', { preventScrollReset: true })
}
const [form, fields] = useForm({
- id: 'edit-horse',
+ id: 'delete-animal',
lastSubmission: actionData?.submission,
shouldRevalidate: 'onSubmit',
})
@@ -132,9 +135,9 @@ export default function DeleteHorse() {
onPointerDownOutside={dismissModal}
>
- Delete Horse
+ Delete Animal
- Are you sure you want to remove {data.horse?.name} from the
+ Are you sure you want to remove {data.animal?.name} from the
database? This will affect all associated events and assignments.
@@ -142,7 +145,7 @@ export default function DeleteHorse() {
{
await requireAdmin(request)
- invariant(params.horseId, 'Missing horse id')
- const horse = await prisma.horse.findUnique({ where: { id: params.horseId } })
- if (!horse) {
+ const { orgId } = await requireOrgMember(request)
+ invariant(params.animalId, 'Missing animal id')
+ const animal = await prisma.animal.findFirst({ where: { id: params.animalId, orgId } })
+ if (!animal) {
throw new Response('not found', { status: 404 })
}
- return json({ horse })
+ return json({ animal })
}
export async function action({ request, params }: DataFunctionArgs) {
await requireAdmin(request)
- invariant(params.horseId, 'Missing horse id')
+ const { orgId } = await requireOrgMember(request)
+ invariant(params.animalId, 'Missing animal id')
const formData = await request.formData()
const submission = await parse(formData, {
async: true,
- schema: horseFormSchema,
+ schema: animalFormSchema,
})
if (submission.intent !== 'submit') {
@@ -79,8 +82,12 @@ export async function action({ request, params }: DataFunctionArgs) {
cooldownEndDate,
} = submission.value
- const updatedHorse = await prisma.horse.update({
- where: { id: params.horseId },
+ const existingAnimal = await prisma.animal.findFirst({ where: { id: params.animalId, orgId } })
+ if (!existingAnimal) {
+ throw new Response('not found', { status: 404 })
+ }
+ const updatedAnimal = await prisma.animal.update({
+ where: { id: params.animalId },
data: {
name,
status,
@@ -91,47 +98,44 @@ export async function action({ request, params }: DataFunctionArgs) {
},
})
- if (!updatedHorse) {
- return redirectWithToast(`/admin/horses`, {
+ if (!updatedAnimal) {
+ return redirectWithToast(`/admin/animals`, {
title: `Error`,
variant: 'destructive',
- description: `Failed to update horse`,
+ description: `Failed to update animal`,
})
}
if (cooldown && cooldownStartDate && cooldownEndDate) {
- // Get events horseID is registered for
- const horseEvents = await prisma.event.findMany({
+ const animalEvents = await prisma.event.findMany({
where: {
- horses: {
+ animals: {
some: {
- id: updatedHorse.id,
+ id: updatedAnimal.id,
},
},
},
})
- // Compare event dates to cooldown dates and gather events with conflicts
const conflictEvents = []
- if (horseEvents) {
- for (const e of horseEvents) {
+ if (animalEvents) {
+ for (const e of animalEvents) {
if (
cooldownStartDate <= e.start &&
- e.start < add(cooldownEndDate, { days: 1 }) // checks that event is before midnight of cooldownEndDate
+ e.start < add(cooldownEndDate, { days: 1 })
) {
conflictEvents.push(e)
}
}
}
- // Remove horse from events with conflicts
if (conflictEvents.length > 0) {
for (const e of conflictEvents) {
await prisma.event.update({
where: { id: e.id },
data: {
- horses: {
- disconnect: { id: updatedHorse.id },
+ animals: {
+ disconnect: { id: updatedAnimal.id },
},
},
})
@@ -144,13 +148,13 @@ export async function action({ request, params }: DataFunctionArgs) {
}
}
- return redirectWithToast(`/admin/horses`, {
+ return redirectWithToast(`/admin/animals`, {
title: `Success`,
- description: `Updated ${updatedHorse.name}`,
+ description: `Updated ${updatedAnimal.name}`,
})
}
-export default function EditHorse() {
+export default function EditAnimal() {
const data = useLoaderData() || {}
const actionData = useActionData()
const [open, setOpen] = useState(true)
@@ -169,31 +173,27 @@ export default function EditHorse() {
navigate('..', { preventScrollReset: true })
}
const [form, fields] = useForm({
- id: 'edit-horse',
+ id: 'edit-animal',
lastSubmission: actionData?.submission,
defaultValue: {
- name: data.horse?.name,
- status: data.horse?.status,
- notes: data.horse?.notes,
- cooldownStartDate: data.horse?.cooldownStartDate
- ? format(new Date(data.horse.cooldownStartDate), 'yyyy-MM-dd')
+ name: data.animal?.name,
+ status: data.animal?.status,
+ notes: data.animal?.notes,
+ cooldownStartDate: data.animal?.cooldownStartDate
+ ? format(new Date(data.animal.cooldownStartDate), 'yyyy-MM-dd')
: null,
- cooldownEndDate: data.horse?.cooldownEndDate
- ? format(new Date(data.horse.cooldownEndDate), 'yyyy-MM-dd')
+ cooldownEndDate: data.animal?.cooldownEndDate
+ ? format(new Date(data.animal.cooldownEndDate), 'yyyy-MM-dd')
: null,
},
shouldRevalidate: 'onSubmit',
onSubmit: dismissModal,
})
- /**
- * If there is returned actionData (form validation errors),
- * use that checked state, otherwise use the boolean from the DB
- */
const cooldown = actionData
? actionData.submission.payload?.cooldown === 'on'
? true
: false
- : data.horse?.cooldown
+ : data.animal?.cooldown
const [cooldownChecked, setCooldownChecked] = useState(cooldown)
const conflictEvents = actionData?.conflictEvents ?? null
@@ -204,9 +204,9 @@ export default function EditHorse() {
onPointerDownOutside={dismissModal}
>
- Edit Horse: {data.horse?.name}
+ Edit Animal: {data.animal?.name}
- Edit this horse using this form. Click save to save your changes.
+ Edit this animal using this form. Click save to save your changes.