added mappers, updated models
This commit is contained in:
parent
6ada519e06
commit
a8375b99c2
11 changed files with 306 additions and 120 deletions
|
|
@ -1,46 +0,0 @@
|
|||
import { Box, Button, Stack, Text } from '@chakra-ui/react'
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
import { gql, useQuery } from '@apollo/client'
|
||||
|
||||
import { BooksManyQuery } from '@generated/types'
|
||||
|
||||
export const Route = createFileRoute('/example')({
|
||||
component: Dashboard,
|
||||
})
|
||||
|
||||
function Dashboard() {
|
||||
const { data, refetch } = useQuery<BooksManyQuery>(getBooksQuery)
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Text>Hello world!</Text>
|
||||
<Text>This is my template!</Text>
|
||||
<Stack>
|
||||
{data && (
|
||||
<>
|
||||
{data.booksMany.map((book: any) => (
|
||||
<Stack key={book.id}>
|
||||
<Text>{book.title}</Text>
|
||||
<Text>{book.author}</Text>
|
||||
</Stack>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
<Box>
|
||||
<Button onClick={async () => refetch()}>Refetch</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
const getBooksQuery = gql`
|
||||
query BooksMany {
|
||||
booksMany {
|
||||
id
|
||||
author
|
||||
title
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
@ -32,16 +32,16 @@ function RouteComponent() {
|
|||
return (
|
||||
<Stack justifyContent="center" alignItems="center">
|
||||
<Stack width="90%">
|
||||
<WorkingListSearch
|
||||
value={workingSearchValue}
|
||||
onSubmit={value => {
|
||||
alert(value);
|
||||
}}
|
||||
onChange={value => setWorkingSearchValue(value)}
|
||||
/>
|
||||
|
||||
{data != null ? (
|
||||
<>
|
||||
<WorkingListSearch
|
||||
value={workingSearchValue}
|
||||
onSubmit={value => {
|
||||
alert(value);
|
||||
}}
|
||||
onChange={value => setWorkingSearchValue(value)}
|
||||
/>
|
||||
|
||||
<WorkingList
|
||||
workingsList={data.workingMany.items.map(item => ({
|
||||
...item,
|
||||
|
|
@ -58,7 +58,15 @@ function RouteComponent() {
|
|||
/>
|
||||
</>
|
||||
) : (
|
||||
<Skeleton />
|
||||
<>
|
||||
<Stack direction="row" justifyContent="center" alignItems="center" gap={2}>
|
||||
<Skeleton height={10} width="80%" />
|
||||
<Skeleton height={10} width="calc(20% - 6px)" />
|
||||
</Stack>
|
||||
<Skeleton height={20} />
|
||||
<Skeleton height={20} />
|
||||
<Skeleton height={20} />
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
@ -70,21 +78,21 @@ const query = gql`
|
|||
workingMany(input: $input) {
|
||||
items {
|
||||
id
|
||||
type
|
||||
title
|
||||
description
|
||||
author {
|
||||
id
|
||||
username
|
||||
}
|
||||
progressStatus
|
||||
updatedAt
|
||||
chapters {
|
||||
total
|
||||
}
|
||||
wordsTotal
|
||||
progressStatus
|
||||
ratingTotal
|
||||
reviews {
|
||||
total
|
||||
reviewsTotal
|
||||
book {
|
||||
id
|
||||
chaptersTotal
|
||||
wordsTotal
|
||||
}
|
||||
}
|
||||
total
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ export const Query: QueryResolvers = {
|
|||
bookOne: BookOneResolver,
|
||||
identity: IdentityResolver,
|
||||
userOne: UserOneResolver
|
||||
// workingMany:
|
||||
};
|
||||
|
||||
export const Mutation: MutationResolvers = {
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
import { IdentityContext } from '@app/server/identity';
|
||||
import { Book, QueryBookOneArgs } from '@generated/types';
|
||||
import { books } from './booksManyResolver';
|
||||
|
||||
export async function BookOneResolver(
|
||||
_: any,
|
||||
{ id }: QueryBookOneArgs,
|
||||
{ identity }: IdentityContext
|
||||
): Promise<Book> {
|
||||
const book = books.filter(item => item.id === id)[0];
|
||||
|
||||
return book;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import { IdentityContext } from '@app/server/identity';
|
||||
import { Book } from '@generated/types';
|
||||
|
||||
export const books = [
|
||||
{
|
||||
id: '1',
|
||||
title: 'some-title-1',
|
||||
author: 'someone'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: 'some-title-1',
|
||||
author: 'someone'
|
||||
}
|
||||
];
|
||||
|
||||
export async function BooksManyResolver(
|
||||
_: any,
|
||||
__: any,
|
||||
{ req, res, identity }: IdentityContext
|
||||
): Promise<Book[]> {
|
||||
if (identity == null) throw new Error('Unauthorized');
|
||||
|
||||
return books;
|
||||
}
|
||||
23
app/server/graphql/resolvers/mappers/bookChapterMapper.ts
Normal file
23
app/server/graphql/resolvers/mappers/bookChapterMapper.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { call } from '@app/common';
|
||||
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> {
|
||||
return {
|
||||
id: model.id,
|
||||
title: model.title,
|
||||
createdAt: model.createdAt.toISOString(),
|
||||
updatedAt: model.createdAt.toISOString(),
|
||||
foreword: model.foreword,
|
||||
footnote: model.footnote,
|
||||
reviewsTotal: await call(async () => {
|
||||
const reviewsCount = await prisma.review.count({
|
||||
where: {
|
||||
bookChapterId: model.id
|
||||
}
|
||||
});
|
||||
return reviewsCount;
|
||||
})
|
||||
};
|
||||
}
|
||||
22
app/server/graphql/resolvers/mappers/bookMapper.ts
Normal file
22
app/server/graphql/resolvers/mappers/bookMapper.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { call } from '@app/common';
|
||||
import { prisma } from '@app/server/prisma/client';
|
||||
import { Book as BookSchema } from '@generated/types';
|
||||
import { Book } from '@prisma/client';
|
||||
|
||||
export async function toBookSchema(model: Book): Promise<BookSchema> {
|
||||
return {
|
||||
id: model.id,
|
||||
workingId: model.workingId,
|
||||
createdAt: model.createdAt.toISOString(),
|
||||
updatedAt: model.updatedAt.toISOString(),
|
||||
wordsTotal: model.wordsTotal,
|
||||
chaptersTotal: await call(async () => {
|
||||
const chaptersCount = await prisma.bookChapter.count({
|
||||
where: {
|
||||
bookId: model.id
|
||||
}
|
||||
});
|
||||
return chaptersCount;
|
||||
})
|
||||
};
|
||||
}
|
||||
24
app/server/graphql/resolvers/mappers/reviewMapper.ts
Normal file
24
app/server/graphql/resolvers/mappers/reviewMapper.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import { Review } from '@prisma/client';
|
||||
import { Review as ReviewSchema } from '@generated/types';
|
||||
import { toUserSchema } from './userMapper';
|
||||
import { call } from '@app/common';
|
||||
import { prisma } from '@app/server/prisma/client';
|
||||
|
||||
export async function toReviewSchema(model: Review): Promise<ReviewSchema> {
|
||||
return {
|
||||
id: model.id,
|
||||
author: await call(async () => {
|
||||
const userModel = await prisma.user.findUniqueOrThrow({
|
||||
where: {
|
||||
id: model.userId
|
||||
}
|
||||
});
|
||||
return toUserSchema(userModel);
|
||||
}),
|
||||
text: model.text,
|
||||
//todo: ratings implementation
|
||||
ratingTotal: await call(async () => {
|
||||
return 0;
|
||||
})
|
||||
};
|
||||
}
|
||||
65
app/server/graphql/resolvers/mappers/workingMapper.ts
Normal file
65
app/server/graphql/resolvers/mappers/workingMapper.ts
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
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);
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
scalar Void
|
||||
|
||||
type Query {
|
||||
booksMany: [Book!]!
|
||||
bookOne(id: ID!): Book!
|
||||
identity: Identity!
|
||||
userOne(id: ID!): User!
|
||||
workingMany(input: WorkingManyInput!): WorkingManyOutput!
|
||||
|
|
@ -44,14 +42,6 @@ type User {
|
|||
updatedAt: String!
|
||||
}
|
||||
|
||||
type Book {
|
||||
id: ID!
|
||||
title: String!
|
||||
author: String!
|
||||
}
|
||||
|
||||
input Working
|
||||
|
||||
input PaginationFilterInput {
|
||||
terms: String
|
||||
offset: Int
|
||||
|
|
@ -60,12 +50,18 @@ input PaginationFilterInput {
|
|||
|
||||
input WorkingManyInput {
|
||||
filter: PaginationFilterInput!
|
||||
type: WorkingType!
|
||||
}
|
||||
|
||||
enum WorkingType {
|
||||
book
|
||||
notepad
|
||||
}
|
||||
|
||||
enum WorkingProgressStatus {
|
||||
inProgress
|
||||
frozen
|
||||
finished
|
||||
complete
|
||||
}
|
||||
|
||||
type WorkingManyOutput {
|
||||
|
|
@ -80,35 +76,58 @@ type Working {
|
|||
author: User!
|
||||
createdAt: String!
|
||||
updatedAt: String!
|
||||
type: WorkingType!
|
||||
book: Book
|
||||
notepad: Notepad
|
||||
progressStatus: WorkingProgressStatus!
|
||||
wordsTotal: Int!
|
||||
ratingTotal: Int!
|
||||
chapters: ChapterManyOutput!
|
||||
reviews: ReviewManyOutput!
|
||||
reviewsTotal: Int!
|
||||
}
|
||||
|
||||
type ChapterManyOutput {
|
||||
items: [Chapter!]!
|
||||
total: Int!
|
||||
type Book {
|
||||
id: ID!
|
||||
workingId: ID!
|
||||
createdAt: String!
|
||||
updatedAt: String!
|
||||
wordsTotal: Int!
|
||||
chaptersTotal: Int!
|
||||
}
|
||||
|
||||
type Chapter {
|
||||
type BookChapter {
|
||||
id: ID!
|
||||
title: String!
|
||||
createdAt: String!
|
||||
updatedAt: String!
|
||||
foreword: String!
|
||||
footnote: String!
|
||||
reviewsTotal: Int!
|
||||
}
|
||||
|
||||
type ReviewManyOutput {
|
||||
items: [Review!]!
|
||||
input BookChapterManyInput {
|
||||
filter: PaginationFilterInput!
|
||||
}
|
||||
|
||||
type BookChapterManyOutput {
|
||||
items: [BookChapter!]!
|
||||
total: Int!
|
||||
}
|
||||
|
||||
type Notepad {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type Review {
|
||||
id: ID!
|
||||
author: User!
|
||||
text: String!
|
||||
ratingTotal: Int!
|
||||
}
|
||||
|
||||
input ReviewManyInput {
|
||||
filter: PaginationFilterInput!
|
||||
}
|
||||
|
||||
type ReviewManyOutput {
|
||||
items: [Review!]!
|
||||
total: Int!
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,4 +20,112 @@ model User {
|
|||
refreshToken String? @unique @db.VarChar(255)
|
||||
|
||||
isDarkMode Boolean @default(true)
|
||||
|
||||
workings Working[]
|
||||
reviews Review[]
|
||||
ratings Rating[]
|
||||
}
|
||||
|
||||
model Working {
|
||||
id String @id
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
title String @db.VarChar(255)
|
||||
description String @db.MediumText
|
||||
progressStatus WorkingProgressStatus @default(inProgress)
|
||||
|
||||
type WorkingType
|
||||
|
||||
author User @relation(fields: [authorId], references: [id])
|
||||
authorId String
|
||||
|
||||
book Book?
|
||||
|
||||
reviews Review[]
|
||||
ratings Rating[]
|
||||
}
|
||||
|
||||
enum WorkingType {
|
||||
book
|
||||
notepad
|
||||
}
|
||||
|
||||
enum WorkingProgressStatus {
|
||||
inProgress
|
||||
frozen
|
||||
complete
|
||||
}
|
||||
|
||||
model Book {
|
||||
id String @id
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
wordsTotal Int @default(0)
|
||||
|
||||
working Working @relation(fields: [workingId], references: [id])
|
||||
workingId String @unique @db.VarChar(255)
|
||||
|
||||
chapters BookChapter[]
|
||||
}
|
||||
|
||||
model BookChapter {
|
||||
id String @id
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
title String @db.VarChar(255)
|
||||
foreword String @db.MediumText
|
||||
footnote String @db.MediumText
|
||||
|
||||
book Book @relation(fields: [bookId], references: [id])
|
||||
bookId String @db.VarChar(255)
|
||||
|
||||
reviews Review[]
|
||||
ratings Rating[]
|
||||
}
|
||||
|
||||
model Review {
|
||||
id String @id
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
text String @db.MediumText
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String @db.VarChar(255)
|
||||
|
||||
working Working? @relation(fields: [workingId], references: [id])
|
||||
workingId String? @db.VarChar(255)
|
||||
|
||||
bookChapter BookChapter? @relation(fields: [bookChapterId], references: [id])
|
||||
bookChapterId String? @db.VarChar(255)
|
||||
}
|
||||
|
||||
enum RatingType {
|
||||
up
|
||||
down
|
||||
}
|
||||
|
||||
model Rating {
|
||||
id String @id
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
type RatingType
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String @db.VarChar(255)
|
||||
|
||||
working Working? @relation(fields: [workingId], references: [id])
|
||||
workingId String? @db.VarChar(255)
|
||||
|
||||
bookChapter BookChapter? @relation(fields: [bookChapterId], references: [id])
|
||||
bookChapterId String? @db.VarChar(255)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue