mirror of
https://github.com/soconnor0919/hristudio.git
synced 2025-12-11 22:54:45 -05:00
chore(deps): Update dependencies and refactor API routes for improved error handling
- Updated various dependencies in package.json and pnpm-lock.yaml, including '@clerk/nextjs' to version 6.7.1 and several others for better performance and security. - Refactored API routes to use Promise.resolve for context parameters, enhancing reliability in asynchronous contexts. - Improved error handling in the dashboard and studies components, ensuring better user experience during data fetching. - Removed unused favicon.ico file to clean up the project structure. - Enhanced the dashboard components to utilize a new utility function for API URL fetching, promoting code reusability.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card";
|
||||
import { Button } from "~/components/ui/button";
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { useToast } from "~/hooks/use-toast";
|
||||
import Link from "next/link";
|
||||
import { getApiUrl } from "~/lib/fetch-utils";
|
||||
|
||||
interface StudyStats {
|
||||
participantCount: number;
|
||||
@@ -31,13 +32,9 @@ export default function StudyDashboard() {
|
||||
const { id } = useParams();
|
||||
const { toast } = useToast();
|
||||
|
||||
useEffect(() => {
|
||||
fetchStudyStats();
|
||||
}, [id]);
|
||||
|
||||
const fetchStudyStats = async () => {
|
||||
const fetchStudyStats = useCallback(async () => {
|
||||
try {
|
||||
const response = await fetch(`/api/studies/${id}/stats`);
|
||||
const response = await fetch(getApiUrl(`/api/studies/${id}/stats`));
|
||||
if (!response.ok) throw new Error("Failed to fetch study statistics");
|
||||
const data = await response.json();
|
||||
setStats(data.data);
|
||||
@@ -51,7 +48,11 @@ export default function StudyDashboard() {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
}, [toast, id]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchStudyStats();
|
||||
}, [fetchStudyStats]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
|
||||
@@ -12,6 +12,7 @@ import Link from "next/link";
|
||||
import { useActiveStudy } from "~/context/active-study";
|
||||
import { hasPermission } from "~/lib/permissions-client";
|
||||
import { PERMISSIONS } from "~/lib/permissions";
|
||||
import { getApiUrl } from "~/lib/fetch-utils";
|
||||
|
||||
export default function NewParticipant() {
|
||||
const [name, setName] = useState("");
|
||||
@@ -36,7 +37,7 @@ export default function NewParticipant() {
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/studies/${id}/participants`, {
|
||||
const response = await fetch(getApiUrl(`/api/studies/${id}/participants`), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card";
|
||||
import { Button } from "~/components/ui/button";
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "~/components/ui/table";
|
||||
|
||||
import { getApiUrl } from "~/lib/fetch-utils";
|
||||
interface Participant {
|
||||
id: number;
|
||||
name: string;
|
||||
@@ -48,13 +48,9 @@ export default function ParticipantsList() {
|
||||
const canDeleteParticipant = activeStudy && hasPermission(activeStudy.permissions, PERMISSIONS.DELETE_PARTICIPANT);
|
||||
const canViewNames = activeStudy && hasPermission(activeStudy.permissions, PERMISSIONS.VIEW_PARTICIPANT_NAMES);
|
||||
|
||||
useEffect(() => {
|
||||
fetchParticipants();
|
||||
}, [id]);
|
||||
|
||||
const fetchParticipants = async () => {
|
||||
const fetchParticipants = useCallback(async () => {
|
||||
try {
|
||||
const response = await fetch(`/api/studies/${id}/participants`, {
|
||||
const response = await fetch(getApiUrl(`/api/studies/${id}/participants`), {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -74,11 +70,15 @@ export default function ParticipantsList() {
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
}, [toast, id]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchParticipants();
|
||||
}, [fetchParticipants]);
|
||||
|
||||
const handleDelete = async (participantId: number) => {
|
||||
try {
|
||||
const response = await fetch(`/api/studies/${id}/participants`, {
|
||||
const response = await fetch(getApiUrl(`/api/studies/${id}/participants`), {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
@@ -10,6 +10,7 @@ import { PERMISSIONS } from "~/lib/permissions-client";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import { Settings2Icon, UsersIcon, UserIcon } from "lucide-react";
|
||||
import { cn } from "~/lib/utils";
|
||||
import { getApiUrl } from "~/lib/fetch-utils";
|
||||
|
||||
interface Study {
|
||||
id: number;
|
||||
@@ -29,7 +30,7 @@ export default function StudySettings() {
|
||||
useEffect(() => {
|
||||
const fetchStudy = async () => {
|
||||
try {
|
||||
const response = await fetch(`/api/studies/${id}`);
|
||||
const response = await fetch(getApiUrl(`/api/studies/${id}`));
|
||||
if (!response.ok) {
|
||||
if (response.status === 403) {
|
||||
router.push('/dashboard/studies');
|
||||
|
||||
@@ -13,7 +13,7 @@ import Link from "next/link";
|
||||
import { useActiveStudy } from "~/context/active-study";
|
||||
import { hasPermission } from "~/lib/permissions-client";
|
||||
import { PERMISSIONS } from "~/lib/permissions";
|
||||
|
||||
import { getApiUrl } from "~/lib/fetch-utils";
|
||||
export default function NewStudy() {
|
||||
const [title, setTitle] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
@@ -27,7 +27,7 @@ export default function NewStudy() {
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/studies', {
|
||||
const response = await fetch(getApiUrl('/api/studies'), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
AlertDialogFooter
|
||||
} from "~/components/ui/alert-dialog";
|
||||
import { ROLES } from "~/lib/roles";
|
||||
import { getApiUrl } from "~/lib/fetch-utils";
|
||||
|
||||
interface Study {
|
||||
id: number;
|
||||
@@ -50,7 +51,7 @@ export default function Studies() {
|
||||
|
||||
const fetchStudies = async () => {
|
||||
try {
|
||||
const response = await fetch("/api/studies");
|
||||
const response = await fetch(getApiUrl("/api/studies"));
|
||||
if (!response.ok) throw new Error("Failed to fetch studies");
|
||||
const data = await response.json();
|
||||
setStudies(data.data || []);
|
||||
@@ -67,7 +68,7 @@ export default function Studies() {
|
||||
const createStudy = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
const response = await fetch("/api/studies", {
|
||||
const response = await fetch(getApiUrl("/api/studies"), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -99,7 +100,7 @@ export default function Studies() {
|
||||
|
||||
const deleteStudy = async (id: number) => {
|
||||
try {
|
||||
const response = await fetch(`/api/studies/${id}`, {
|
||||
const response = await fetch(getApiUrl(`/api/studies/${id}`), {
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user