Start making front end web pages to test every single API.
This commit is contained in:
parent
d7d3c63d7f
commit
a2bb8023c9
@ -16,7 +16,11 @@ export const GET = async (request: NextRequest) => {
|
|||||||
const messages = await fetchMessages(parseInt(userId), parseInt(partnerId));
|
const messages = await fetchMessages(parseInt(userId), parseInt(partnerId));
|
||||||
return NextResponse.json(messages);
|
return NextResponse.json(messages);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error('Detailed error:', error);
|
||||||
return NextResponse.json({ message: "Error" }, { status: 500 });
|
if (error instanceof Error) {
|
||||||
|
return NextResponse.json({ message: `Error: ${error.message}` }, { status: 500 });
|
||||||
|
} else {
|
||||||
|
return NextResponse.json({ message: "Unknown error occurred" }, { status: 500 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
87
src/app/countdown/createOrUpdateCountdown/page.tsx
Normal file
87
src/app/countdown/createOrUpdateCountdown/page.tsx
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
export default function TestCreateOrUpdateCountdown() {
|
||||||
|
const [relationshipId, setRelationshipId] = useState('');
|
||||||
|
const [title, setTitle] = useState('');
|
||||||
|
const [date, setDate] = useState('');
|
||||||
|
const [result, setResult] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setResult(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/countdown/createOrUpdateCountdown', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': process.env.NEXT_PUBLIC_API_KEY ?? '',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
relationshipId,
|
||||||
|
title,
|
||||||
|
date,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const data = await response.json() as { message: string };
|
||||||
|
setResult(data.message);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error);
|
||||||
|
setResult('An error occurred');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex min-h-screen flex-col items-center justify-center
|
||||||
|
bg-gradient-to-b from-pink-500 to-orange-400 text-white cursor-pointer">
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl mb-4">Test Create or Update Countdown</h1>
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="relationshipId" className="block">Relationship ID:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="relationshipId"
|
||||||
|
value={relationshipId}
|
||||||
|
onChange={(e) => setRelationshipId(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="title" className="block">Title:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="title"
|
||||||
|
value={title}
|
||||||
|
onChange={(e) => setTitle(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="date" className="block">Date:</label>
|
||||||
|
<input
|
||||||
|
type="datetime-local"
|
||||||
|
id="date"
|
||||||
|
value={date}
|
||||||
|
onChange={(e) => setDate(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="bg-blue-500 text-white p-2 rounded">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{result && (
|
||||||
|
<div className="mt-4 p-2 rounded bg-black">
|
||||||
|
Result: {result}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
57
src/app/countdown/getCountdownByRelationship/page.tsx
Normal file
57
src/app/countdown/getCountdownByRelationship/page.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
export default function TestGetCountdownByRelationship() {
|
||||||
|
const [relationshipId, setRelationshipId] = useState('');
|
||||||
|
const [result, setResult] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setResult(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/countdown/getCountdownByRelationship?relationshipId=${relationshipId}`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'x-api-key': process.env.NEXT_PUBLIC_API_KEY ?? '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const data = await response.json() as { countdown: string };
|
||||||
|
setResult(JSON.stringify(data, null, 2));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error);
|
||||||
|
setResult('An error occurred');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex min-h-screen flex-col items-center justify-center
|
||||||
|
bg-gradient-to-b from-pink-500 to-orange-400 text-white cursor-pointer">
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl mb-4">Test Get Countdown By Relationship</h1>
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="relationshipId" className="block">Relationship ID:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="relationshipId"
|
||||||
|
value={relationshipId}
|
||||||
|
onChange={(e) => setRelationshipId(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="bg-blue-500 text-white p-2 rounded">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{result && (
|
||||||
|
<div className="mt-4 p-2 rounded bg-black">
|
||||||
|
<pre>{result}</pre>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
};
|
69
src/app/messages/fetchMessages/page.tsx
Normal file
69
src/app/messages/fetchMessages/page.tsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
"use client";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
export default function TestFetchMessages() {
|
||||||
|
const [userId, setUserId] = useState("");
|
||||||
|
const [partnerId, setPartnerId] = useState("");
|
||||||
|
const [result, setResult] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setResult(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/api/messages/fetchMessages?userId=${userId}&partnerId=${partnerId}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"x-api-key": process.env.NEXT_PUBLIC_API_KEY ?? "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json() as { message: string };
|
||||||
|
setResult(JSON.stringify(data, null, 2));
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error:", error);
|
||||||
|
setResult("An error occurred");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex min-h-screen flex-col items-center justify-center
|
||||||
|
bg-gradient-to-b from-pink-500 to-orange-400 text-white cursor-pointer">
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl mb-4">Test Fetch Messages</h1>
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="userId" className="block">User ID:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="userId"
|
||||||
|
value={userId}
|
||||||
|
onChange={(e) => setUserId(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="partnerId" className="block">Partner ID:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="partnerId"
|
||||||
|
value={partnerId}
|
||||||
|
onChange={(e) => setPartnerId(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="bg-blue-500 text-white p-2 rounded">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{result && (
|
||||||
|
<div className="mt-4 p-2 rounded bg-black">
|
||||||
|
<pre>{result}</pre>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
};
|
121
src/app/messages/sendMessage/page.tsx
Normal file
121
src/app/messages/sendMessage/page.tsx
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
|
type MediaType = 'text' | 'image' | 'video' | 'audio' | 'file' | 'link';
|
||||||
|
|
||||||
|
export default function TestSendMessage() {
|
||||||
|
const [senderId, setSenderId] = useState('');
|
||||||
|
const [receiverId, setReceiverId] = useState('');
|
||||||
|
const [content, setContent] = useState('');
|
||||||
|
const [mediaType, setMediaType] = useState<MediaType | ''>('');
|
||||||
|
const [mediaUrl, setMediaUrl] = useState('');
|
||||||
|
const [result, setResult] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setResult(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/messages/sendMessage', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': process.env.NEXT_PUBLIC_API_KEY ?? '',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
senderId,
|
||||||
|
receiverId,
|
||||||
|
content,
|
||||||
|
...(mediaType && mediaUrl && { mediaType, mediaUrl }),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json() as {message: string}
|
||||||
|
setResult(JSON.stringify(data, null, 2));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error);
|
||||||
|
setResult('An error occurred');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex min-h-screen flex-col items-center justify-center
|
||||||
|
bg-gradient-to-b from-pink-500 to-orange-400 text-white cursor-pointer">
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl mb-4">Test Send Message</h1>
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="senderId" className="block">Sender ID:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="senderId"
|
||||||
|
value={senderId}
|
||||||
|
onChange={(e) => setSenderId(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="receiverId" className="block">Receiver ID:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="receiverId"
|
||||||
|
value={receiverId}
|
||||||
|
onChange={(e) => setReceiverId(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="content" className="block">Content:</label>
|
||||||
|
<textarea
|
||||||
|
id="content"
|
||||||
|
value={content}
|
||||||
|
onChange={(e) => setContent(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="mediaType" className="block">Media Type:</label>
|
||||||
|
<select
|
||||||
|
id="mediaType"
|
||||||
|
value={mediaType}
|
||||||
|
onChange={(e) => setMediaType(e.target.value as MediaType)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
>
|
||||||
|
<option value="">None</option>
|
||||||
|
<option value="image">Image</option>
|
||||||
|
<option value="video">Video</option>
|
||||||
|
<option value="audio">Audio</option>
|
||||||
|
<option value="file">File</option>
|
||||||
|
<option value="link">Link</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{mediaType && (
|
||||||
|
<div>
|
||||||
|
<label htmlFor="mediaUrl" className="block">Media URL:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="mediaUrl"
|
||||||
|
value={mediaUrl}
|
||||||
|
onChange={(e) => setMediaUrl(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<button type="submit" className="bg-blue-500 text-white p-2 rounded">
|
||||||
|
Send Message
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{result && (
|
||||||
|
<div className="mt-4 p-2 rounded bg-black">
|
||||||
|
<pre>{result}</pre>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
75
src/app/relationships/createRequest/page.tsx
Normal file
75
src/app/relationships/createRequest/page.tsx
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React, {useState} from "react";
|
||||||
|
|
||||||
|
export default function TestCreateRequestPage() {
|
||||||
|
const [userId, setUserId] = useState('');
|
||||||
|
const [targetUserId, setTargetUserId] = useState('');
|
||||||
|
const [result, setResult] = useState<string | null>(null)
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setResult(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/relationships/createRequest', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'x-api-key': process.env.NEXT_PUBLIC_API_KEY ?? '',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
userId,
|
||||||
|
targetUserId,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const data = await response.json() as {message: string};
|
||||||
|
setResult(JSON.stringify(data));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error:', error);
|
||||||
|
setResult('An error occurred');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="flex min-h-screen flex-col items-center justify-center
|
||||||
|
bg-gradient-to-b from-pink-500 to-orange-400 text-white cursor-pointer">
|
||||||
|
<div className="p-4">
|
||||||
|
<h1 className="text-2xl mb-4">Create Relationship Request</h1>
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="userId" className="block">User ID:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="userId"
|
||||||
|
value={userId}
|
||||||
|
onChange={(e) => setUserId(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="targetUserId" className="block">Target User ID:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="targetUserId"
|
||||||
|
value={targetUserId}
|
||||||
|
onChange={(e) => setTargetUserId(e.target.value)}
|
||||||
|
className="border p-2 w-full bg-black"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="bg-blue-500 p-2 rounded">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{result && (
|
||||||
|
<div className="mt-4 p-2 rounded bg-black">
|
||||||
|
Result: {result}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,9 +1,10 @@
|
|||||||
import 'server-only';
|
import 'server-only';
|
||||||
import { db } from '~/server/db';
|
import { db } from '~/server/db';
|
||||||
import * as schema from '~/server/db/schema';
|
import * as schema from '~/server/db/schema';
|
||||||
import { eq, and, or } from 'drizzle-orm';
|
import { eq, and, or, sql } from 'drizzle-orm';
|
||||||
import { pgEnum } from 'drizzle-orm/pg-core';
|
import { pgEnum } from 'drizzle-orm/pg-core';
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
|
import { inArray } from 'drizzle-orm/sql';
|
||||||
|
|
||||||
// --- Helper Functions --- //
|
// --- Helper Functions --- //
|
||||||
|
|
||||||
@ -30,12 +31,39 @@ export const ensureUserExists = async (userId: number) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ensureRelationshipExistsByRelationshipId = async (relationshipId: number) => {
|
||||||
|
try {
|
||||||
|
const relationship = await db.select({
|
||||||
|
relationshipId: schema.userRelationships.relationshipId,
|
||||||
|
status: schema.relationships.status,
|
||||||
|
}).from(schema.userRelationships)
|
||||||
|
.leftJoin(schema.relationships,
|
||||||
|
eq(schema.userRelationships.relationshipId, schema.relationships.id))
|
||||||
|
.where(eq(schema.userRelationships.relationshipId, relationshipId));
|
||||||
|
|
||||||
|
if (relationship.length === 0) {
|
||||||
|
throw new Error("Relationship not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relationship[0]?.status !== 'accepted') {
|
||||||
|
throw new Error("Relationship not accepted");
|
||||||
|
}
|
||||||
|
return relationship[0];
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
throw new Error(`Error checking relationship: ${error.message}`);
|
||||||
|
} else {
|
||||||
|
throw new Error("Unknown error occurred while checking relationship");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure relationship exists between a user and a partner.
|
* Ensure relationship exists between a user and a partner.
|
||||||
* Handles both directions of a relationship (userId => partnerId or partnerId => userId).
|
* Handles both directions of a relationship (userId => partnerId or partnerId => userId).
|
||||||
* Optionally checks relationship status.
|
* Optionally checks relationship status.
|
||||||
*/
|
*/
|
||||||
export const ensureRelationshipExists = async (userId: number, partnerId: number, status?: 'pending' | 'accepted') => {
|
export const ensureRelationshipExistsOld = async (userId: number, partnerId: number, status?: 'pending' | 'accepted') => {
|
||||||
try {
|
try {
|
||||||
// Ensure bidirectional relationship (user1 <-> user2 or user2 <-> user1)
|
// Ensure bidirectional relationship (user1 <-> user2 or user2 <-> user1)
|
||||||
const relationship = await db.select({
|
const relationship = await db.select({
|
||||||
@ -76,6 +104,48 @@ export const ensureRelationshipExists = async (userId: number, partnerId: number
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const ensureRelationshipExists = async (userId: number, partnerId: number) => {
|
||||||
|
try {
|
||||||
|
// Ensure bidirectional relationship (user1 <-> user2 or user2 <-> user1)
|
||||||
|
const relationship = await db.select({
|
||||||
|
relationshipId: schema.userRelationships.relationshipId,
|
||||||
|
status: schema.relationships.status,
|
||||||
|
})
|
||||||
|
.from(schema.userRelationships)
|
||||||
|
.leftJoin(
|
||||||
|
schema.relationships,
|
||||||
|
eq(schema.userRelationships.relationshipId, schema.relationships.id)
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(schema.userRelationships.relationshipId,
|
||||||
|
db.select({ relationshipId: schema.userRelationships.relationshipId })
|
||||||
|
.from(schema.userRelationships)
|
||||||
|
.where(eq(schema.userRelationships.userId, partnerId))
|
||||||
|
.limit(1)
|
||||||
|
),
|
||||||
|
eq(schema.userRelationships.userId, userId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!relationship.length) {
|
||||||
|
throw new Error('Relationship does not exist');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relationship[0]?.status !== "accepted") {
|
||||||
|
throw new Error(`Relationship is not accepted`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return relationship[0];
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
throw new Error(`Error checking relationship: ${error.message}`);
|
||||||
|
} else {
|
||||||
|
throw new Error("Unknown error occurred while checking relationship");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// --- User Management Functions --- //
|
// --- User Management Functions --- //
|
||||||
|
|
||||||
export const getUserById = async (userId: number) => {
|
export const getUserById = async (userId: number) => {
|
||||||
@ -275,15 +345,24 @@ export const createRelationshipRequest = async (requestorId: number, requestedId
|
|||||||
await ensureUserExists(requestedId);
|
await ensureUserExists(requestedId);
|
||||||
|
|
||||||
// Check if a relationship exists in either direction
|
// Check if a relationship exists in either direction
|
||||||
const existingRelationship = await db.select()
|
const existingRelationship = await db
|
||||||
|
.select({
|
||||||
|
relationshipId: schema.userRelationships.relationshipId,
|
||||||
|
status: schema.relationships.status,
|
||||||
|
})
|
||||||
.from(schema.userRelationships)
|
.from(schema.userRelationships)
|
||||||
.leftJoin(schema.relationships, eq(schema.userRelationships.relationshipId, schema.relationships.id))
|
.innerJoin(
|
||||||
.where(or(
|
schema.relationships,
|
||||||
and(eq(schema.userRelationships.userId, requestorId), eq(schema.userRelationships.userId, requestedId)), // userId -> requestedId
|
eq(schema.userRelationships.relationshipId, schema.relationships.id)
|
||||||
and(eq(schema.userRelationships.userId, requestedId), eq(schema.userRelationships.userId, requestorId)) // requestedId -> userId
|
)
|
||||||
));
|
.where(
|
||||||
|
or(
|
||||||
|
eq(schema.userRelationships.userId, requestorId),
|
||||||
|
eq(schema.userRelationships.userId, requestedId)
|
||||||
|
)
|
||||||
|
).limit(1);
|
||||||
|
|
||||||
if (existingRelationship.length && existingRelationship[0]?.relationship?.status !== 'rejected') {
|
if (existingRelationship.length > 0) {
|
||||||
throw new Error('A relationship already exists or is pending between these users');
|
throw new Error('A relationship already exists or is pending between these users');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +391,6 @@ export const createRelationshipRequest = async (requestorId: number, requestedId
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const updateRelationshipRequest = async (relationshipId: number, status: 'accepted' | 'rejected') => {
|
export const updateRelationshipRequest = async (relationshipId: number, status: 'accepted' | 'rejected') => {
|
||||||
try {
|
try {
|
||||||
const relationship = await db.select().from(schema.relationships)
|
const relationship = await db.select().from(schema.relationships)
|
||||||
@ -366,8 +444,7 @@ export const sendMessage = async (
|
|||||||
await ensureUserExists(senderId);
|
await ensureUserExists(senderId);
|
||||||
await ensureUserExists(receiverId);
|
await ensureUserExists(receiverId);
|
||||||
|
|
||||||
// Ensure the relationship exists (no need to use returned 'relationshipId' for now)
|
await ensureRelationshipExists(senderId, receiverId);
|
||||||
await ensureRelationshipExists(senderId, receiverId, "accepted");
|
|
||||||
|
|
||||||
// Insert the new message
|
// Insert the new message
|
||||||
const message = await db.insert(schema.messages).values({
|
const message = await db.insert(schema.messages).values({
|
||||||
@ -378,7 +455,7 @@ export const sendMessage = async (
|
|||||||
if (!message.length || !message[0]?.id)
|
if (!message.length || !message[0]?.id)
|
||||||
throw new Error("Failed to send message");
|
throw new Error("Failed to send message");
|
||||||
|
|
||||||
if (mediaUrl && mediaType) {
|
if (mediaUrl && mediaType && mediaUrl.length > 0 && mediaType !== "text") {
|
||||||
await db.insert(schema.messageMedia).values({
|
await db.insert(schema.messageMedia).values({
|
||||||
messageId: message[0].id,
|
messageId: message[0].id,
|
||||||
mediaUrl,
|
mediaUrl,
|
||||||
@ -399,7 +476,7 @@ export const sendMessage = async (
|
|||||||
export const fetchMessages = async (userId: number, partnerId: number) => {
|
export const fetchMessages = async (userId: number, partnerId: number) => {
|
||||||
try {
|
try {
|
||||||
await ensureUserExists(userId);
|
await ensureUserExists(userId);
|
||||||
await ensureRelationshipExists(userId, partnerId, "accepted");
|
await ensureRelationshipExists(userId, partnerId);
|
||||||
|
|
||||||
const messages = await db.select().from(schema.messages)
|
const messages = await db.select().from(schema.messages)
|
||||||
.where(or(
|
.where(or(
|
||||||
|
Loading…
Reference in New Issue
Block a user