added resolvers, updated model, updated navbar

This commit is contained in:
lnn0q 2025-05-17 21:41:07 +03:00
parent a8375b99c2
commit 1d40d7e15f
23 changed files with 439 additions and 301 deletions

View file

@ -2,10 +2,12 @@
import { MutationResolvers, QueryResolvers } from '@generated/types';
/* Query */
import { BookOneResolver } from './resolvers/bookOneResolver';
import { BooksManyResolver } from './resolvers/booksManyResolver';
import { IdentityResolver } from './resolvers/identityResolver';
import { UserOneResolver } from './resolvers/userOneResolver';
import { BookChapterManyResolver } from './resolvers/bookChapterMany';
import { BookChapterOneResolver } from './resolvers/bookChapterOne';
import { BookManyResolver } from './resolvers/bookManyResolver';
import { BookOneResolver } from './resolvers/bookOneResolver';
/* Mutation */
import { LoginResolver } from './resolvers/auth/login';
@ -13,11 +15,12 @@ import { LogoutResolver } from './resolvers/auth/logout';
import { SignUpResolver } from './resolvers/auth/signUp';
export const Query: QueryResolvers = {
booksMany: BooksManyResolver,
bookOne: BookOneResolver,
bookMany: BookManyResolver,
bookChapterOne: BookChapterOneResolver,
bookChapterMany: BookChapterManyResolver,
identity: IdentityResolver,
userOne: UserOneResolver
// workingMany:
};
export const Mutation: MutationResolvers = {

View file

@ -0,0 +1,25 @@
import { IdentityContext } from '@app/server/identity';
import { prisma } from '@app/server/prisma/client';
import { BookChapterManyOutput, QueryBookChapterManyArgs } from '@generated/types';
import { toBookChapterSchema } from './mappers/bookChapterMapper';
export async function BookChapterManyResolver(
_: any,
{ input }: QueryBookChapterManyArgs,
{ identity }: IdentityContext
): Promise<BookChapterManyOutput> {
const { bookId, filter } = input;
const items = await prisma.bookChapter.findMany({
where: {
bookId
},
skip: filter.offset ?? 0,
take: filter.size ?? 10
});
return {
items: await Promise.all(items.map(value => toBookChapterSchema(value))),
total: items.length
};
}

View file

@ -0,0 +1,17 @@
import { IdentityContext } from '@app/server/identity';
import { prisma } from '@app/server/prisma/client';
import { BookChapter, QueryBookChapterOneArgs } from '@generated/types';
import { toBookChapterSchema } from './mappers/bookChapterMapper';
export async function BookChapterOneResolver(
_: any,
{ id }: QueryBookChapterOneArgs,
{ identity }: IdentityContext
): Promise<BookChapter> {
const model = await prisma.bookChapter.findUniqueOrThrow({
where: {
id
}
});
return toBookChapterSchema(model);
}

View file

@ -0,0 +1,29 @@
import { IdentityContext } from '@app/server/identity';
import { prisma } from '@app/server/prisma/client';
import { BookManyOutput, QueryBookManyArgs } from '@generated/types';
import { toBookSchema } from './mappers/bookMapper';
export async function BookManyResolver(
_: any,
{ input }: QueryBookManyArgs,
{ identity }: IdentityContext
): Promise<BookManyOutput> {
const { filter } = input;
const terms = filter.terms?.toLowerCase();
const items = await prisma.book.findMany({
where: {
OR:
terms != null
? [{ title: { contains: terms } }, { author: { username: terms } }]
: undefined
},
skip: filter.offset ?? 0,
take: filter.size ?? 10
});
return {
items: await Promise.all(items.map(value => toBookSchema(value))),
total: items.length
};
}

View file

@ -0,0 +1,17 @@
import { IdentityContext } from '@app/server/identity';
import { prisma } from '@app/server/prisma/client';
import { Book, QueryBookOneArgs } from '@generated/types';
import { toBookSchema } from './mappers/bookMapper';
export async function BookOneResolver(
_: any,
{ id }: QueryBookOneArgs,
{ identity }: IdentityContext
): Promise<Book> {
const model = await prisma.book.findUniqueOrThrow({
where: {
id
}
});
return toBookSchema(model);
}

View file

@ -3,7 +3,7 @@ import { prisma } from '@app/server/prisma/client';
import { BookChapter as BookChapterSchema } from '@generated/types';
import { BookChapter } from '@prisma/client';
export async function toBookChapterMapping(model: BookChapter): Promise<BookChapterSchema> {
export async function toBookChapterSchema(model: BookChapter): Promise<BookChapterSchema> {
return {
id: model.id,
title: model.title,

View file

@ -1,14 +1,28 @@
import { assertUnreachable } from '@app/client/helpers';
import { call } from '@app/common';
import { prisma } from '@app/server/prisma/client';
import { Book as BookSchema } from '@generated/types';
import { Book } from '@prisma/client';
import {
Book as BookSchema,
WorkingProgressStatus as WorkingProgressStatusSchema
} from '@generated/types';
import { Book, WorkingProgressStatus } from '@prisma/client';
import { toUserSchema } from './userMapper';
export async function toBookSchema(model: Book): Promise<BookSchema> {
return {
id: model.id,
workingId: model.workingId,
title: model.title,
description: model.description,
author: await call(async () => {
const userModel = await prisma.user.findUniqueOrThrow({ where: { id: model.authorId } });
return toUserSchema(userModel);
}),
createdAt: model.createdAt.toISOString(),
updatedAt: model.updatedAt.toISOString(),
progressStatus: call(() => {
ensureWorkingProgressStatus(model.progressStatus);
return model.progressStatus;
}),
wordsTotal: model.wordsTotal,
chaptersTotal: await call(async () => {
const chaptersCount = await prisma.bookChapter.count({
@ -17,6 +31,32 @@ export async function toBookSchema(model: Book): Promise<BookSchema> {
}
});
return chaptersCount;
}),
// todo: ratings implementation
ratingTotal: await call(async () => {
const ratingsCount = await prisma.rating.count({
where: {
bookId: model.id
}
});
return ratingsCount;
}),
reviewsTotal: await call(async () => {
const reviewsCount = await prisma.review.count({
where: {
bookId: model.id
}
});
return reviewsCount;
})
};
}
function ensureWorkingProgressStatus(
value: WorkingProgressStatus
): asserts value is WorkingProgressStatusSchema {
if (value === WorkingProgressStatus.inProgress) return;
if (value === WorkingProgressStatus.frozen) return;
if (value === WorkingProgressStatus.complete) return;
assertUnreachable(value);
}

View file

@ -16,7 +16,7 @@ export async function toReviewSchema(model: Review): Promise<ReviewSchema> {
return toUserSchema(userModel);
}),
text: model.text,
//todo: ratings implementation
// todo: ratings implementation
ratingTotal: await call(async () => {
return 0;
})

View file

@ -1,65 +0,0 @@
import { assertUnreachable } from '@app/client/helpers';
import { call } from '@app/common';
import { prisma } from '@app/server/prisma/client';
import {
WorkingProgressStatus as WorkingProgressStatusSchema,
Working as WorkingSchema,
WorkingType as WorkingTypeSchema
} from '@generated/types';
import { Working, WorkingProgressStatus, WorkingType } from '@prisma/client';
import { toUserSchema } from './userMapper';
export async function toWorkingSchema(model: Working): Promise<WorkingSchema> {
return {
id: model.id,
title: model.title,
description: model.description,
author: await call(async () => {
const userModel = await prisma.user.findUniqueOrThrow({ where: { id: model.authorId } });
return toUserSchema(userModel);
}),
createdAt: model.createdAt.toISOString(),
updatedAt: model.updatedAt.toISOString(),
type: call(() => {
ensureWorkingType(model.type);
return model.type;
}),
progressStatus: call(() => {
ensureWorkingProgressStatus(model.progressStatus);
return model.progressStatus;
}),
//todo: ratings implementation
//todo: book/notes implementation
ratingTotal: await call(async () => {
const ratingsCount = await prisma.rating.count({
where: {
workingId: model.id
}
});
return ratingsCount;
}),
reviewsTotal: await call(async () => {
const reviewsCount = await prisma.review.count({
where: {
workingId: model.id
}
});
return reviewsCount;
})
};
}
function ensureWorkingType(value: WorkingType): asserts value is WorkingTypeSchema {
if (value == WorkingType.book) return;
if (value == WorkingType.notepad) return;
assertUnreachable(value);
}
function ensureWorkingProgressStatus(
value: WorkingProgressStatus
): asserts value is WorkingProgressStatusSchema {
if (value == WorkingProgressStatus.inProgress) return;
if (value == WorkingProgressStatus.frozen) return;
if (value == WorkingProgressStatus.complete) return;
assertUnreachable(value);
}

View file

@ -3,7 +3,11 @@ scalar Void
type Query {
identity: Identity!
userOne(id: ID!): User!
workingMany(input: WorkingManyInput!): WorkingManyOutput!
bookOne(id: ID!): Book!
bookMany(input: BookManyInput!): BookManyOutput!
bookChapterOne(id: ID!): BookChapter!
bookChapterMany(input: BookChapterManyInput!): BookChapterManyOutput!
reviewMany(input: ReviewManyInput!): ReviewManyOutput!
}
type Mutation {
@ -48,14 +52,8 @@ input PaginationFilterInput {
size: Int
}
input WorkingManyInput {
input BookManyInput {
filter: PaginationFilterInput!
type: WorkingType!
}
enum WorkingType {
book
notepad
}
enum WorkingProgressStatus {
@ -64,33 +62,23 @@ enum WorkingProgressStatus {
complete
}
type WorkingManyOutput {
items: [Working!]!
type BookManyOutput {
items: [Book!]!
total: Int!
}
type Working {
type Book {
id: ID!
title: String!
description: String!
author: User!
createdAt: String!
updatedAt: String!
type: WorkingType!
book: Book
notepad: Notepad
progressStatus: WorkingProgressStatus!
ratingTotal: Int!
reviewsTotal: Int!
}
type Book {
id: ID!
workingId: ID!
createdAt: String!
updatedAt: String!
wordsTotal: Int!
chaptersTotal: Int!
ratingTotal: Int!
reviewsTotal: Int!
}
type BookChapter {
@ -104,6 +92,7 @@ type BookChapter {
}
input BookChapterManyInput {
bookId: String!
filter: PaginationFilterInput!
}
@ -112,10 +101,6 @@ type BookChapterManyOutput {
total: Int!
}
type Notepad {
id: ID!
}
type Review {
id: ID!
author: User!
@ -124,6 +109,8 @@ type Review {
}
input ReviewManyInput {
bookId: String
bookChapterId: String
filter: PaginationFilterInput!
}