Skip to content
Snippets Groups Projects
Commit c6578434 authored by nar20's avatar nar20
Browse files

issue #7: ADD user-stats into system

parent daf16d8f
Branches
No related tags found
1 merge request!5issue #7: ADD user-stats into system
import { eq } from "drizzle-orm";
import { Service } from "typedi";
import db from "..";
import userStatsTable, {
userStatsSchemas,
type UserStatsInput,
type UserStatsModel,
type UserStatsUpdate
} from "../schema/user-stats.model";
@Service()
export class UserStatsRepo {
async findById(
id: UserStatsModel['id']
): Promise<UserStatsModel | null> {
const userStats = await db.query.userStatsTable.findFirst({
where: eq(userStatsTable.id, id)
})
if(!userStats) return null
return userStatsSchemas.userStatsModelSchema.parse(userStats)
}
async findByUserId(
user_id: UserStatsModel['user_id']
): Promise<UserStatsModel | null> {
const userStats = await db.query.userStatsTable.findFirst({
where: eq(userStatsTable.user_id, user_id)
})
if(!userStats) return null
return userStatsSchemas.userStatsModelSchema.parse(userStats)
}
async create(userStats: UserStatsInput, tx?: db): Promise<UserStatsModel> {
const repo = tx ?? db
const [ret] = await repo
.insert(userStatsTable)
.values(userStats)
.returning()
return userStatsSchemas.userStatsModelSchema.parse(ret)
}
async update(userStats: UserStatsUpdate): Promise<UserStatsModel>{
const [ret] = await db
.update(userStatsTable)
.set(userStats)
.where(eq(userStatsTable.id, userStats.id))
.returning()
return userStatsSchemas.userStatsModelSchema.parse(ret)
}
async delete(id: UserStatsModel['id']): Promise<UserStatsModel>{
const [ret] = await db
.delete(userStatsTable)
.where(eq(userStatsTable.id, id))
.returning()
return userStatsSchemas.userStatsModelSchema.parse(ret)
}
}
\ No newline at end of file
import userStatsTable from './user-stats.model'
import userTable from './user.model'
export {
userTable
userTable,
userStatsTable
}
export const tables = [userTable]
export const tables = [
userTable,
userStatsTable
]
import { relations } from "drizzle-orm";
import { integer, pgTable, serial } from "drizzle-orm/pg-core";
import userTable from "./user.model";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import type { z } from "zod";
const userStatsTable = pgTable('user_stats', {
id: serial('id').primaryKey()
.unique()
.notNull(),
user_id: integer('user_id')
.references(() => userTable.id, {onDelete: 'cascade'})
.notNull(),
score: integer('score')
.notNull()
.default(0),
likes: integer('likes')
.default(0),
likes_received: integer('likes_received')
.default(0),
follows: integer('follows')
.default(0),
followers: integer('followers')
.default(0),
collections: integer('collections')
.default(0),
submitted_resources: integer('submitted_resources')
.default(0),
approved_resources: integer('approved_resources')
.default(0),
reviewed_resources: integer('reviewed_resources')
.default(0),
comments: integer('comments')
.default(0),
})
export const userStatsTableRelations = relations(
userStatsTable,
({ one }) => ({
user: one(userTable, {
fields: [userStatsTable.user_id],
references: [userTable.id]
}),
})
)
const userStatsModelSchema = createSelectSchema(userStatsTable)
const userStatsDtoSchema = userStatsModelSchema
const userStatsInputSchema = createInsertSchema(userStatsTable)
const userStatsUpdateSchema = userStatsInputSchema
.partial()
.required({ id: true})
export type UserStatsModel = z.infer<typeof userStatsModelSchema>
export type UserStatsDto = z.infer<typeof userStatsDtoSchema>
export type UserStatsInput = z.infer<typeof userStatsInputSchema>
export type UserStatsUpdate = z.infer<typeof userStatsUpdateSchema>
export const userStatsSchemas = {
userStatsModelSchema,
userStatsDtoSchema,
userStatsInputSchema,
userStatsUpdateSchema
}
export default userStatsTable
\ No newline at end of file
import { sql } from 'drizzle-orm'
import { relations, sql } from 'drizzle-orm'
import { boolean, pgTable, serial, text, timestamp, varchar } from 'drizzle-orm/pg-core'
import { createInsertSchema, createSelectSchema } from 'drizzle-zod'
import { z } from 'zod'
import userStatsTable from './user-stats.model'
const userTable = pgTable('user', {
id: serial('id').primaryKey()
......@@ -17,8 +18,10 @@ const userTable = pgTable('user', {
email: varchar('email', { length: 255 })
.unique()
.notNull(),
description: text('description'),
institution: text('institution'),
description: text('description')
.default("sem descrição"),
institution: text('institution')
.default("sem instituição"),
birthday: timestamp('birthday', { mode: 'string' })
.notNull(),
cpf: varchar('cpf', { length: 255 })
......@@ -35,8 +38,16 @@ const userTable = pgTable('user', {
deleted_at: timestamp('deleted_at', { mode: 'string' }),
reactivated_at: timestamp('reactivated_at', { mode: 'string' }),
active: boolean('active')
.default(true)
})
export const userTableRelation = relations(
userTable,
({ one }) => ({
userStats: one(userStatsTable)
})
)
const userInputSchema = createInsertSchema(userTable)
const userModelSchema = createSelectSchema(userTable)
const userDtoSchema = createSelectSchema(userTable).omit({
......
......@@ -21,5 +21,6 @@ for (const table of schema.tables) {
}
await seeds.userSeed(db)
await seeds.userStatsSeed(db)
await connection.end()
export { default as userSeed } from './user.seed'
export { default as clientSeed } from './client.seed'
export { default as creditCardSeed } from './credit-card.seed'
export { default as userStatsSeed } from './user-stats.seed'
\ No newline at end of file
import type db from '@/db'
import { userStatsTable } from '../schema'
import type { UserStatsInput } from '../schema/user-stats.model'
export default async function seed(db: db) {
await db.insert(userStatsTable).values(usersStatsData)
}
const usersStatsData: UserStatsInput[] = [
{
user_id: 1
},
{
user_id: 2
}
]
......@@ -11,6 +11,7 @@ import { prettyJSON } from 'hono/pretty-json'
import { cors } from 'hono/cors'
import { bodyLimit } from 'hono/body-limit'
import { HttpStatus, createApexError } from './services/error.service'
import { userStatsRouter } from './routes/user-stats.route'
const app = new Hono()
......@@ -51,6 +52,7 @@ app
.basePath('/api')
.route('/user', userRouter)
.route('/upload', uploaderRouter)
.route('/user-stats', userStatsRouter)
export default app
export type AppType = typeof app
......
import { UserStatsService } from "@/services/user-stats.service";
import { honoWithJwt } from "..";
import Container from "typedi";
import { zValidator } from "@hono/zod-validator";
import { userStatsSchemas } from "@/db/schema/user-stats.model";
import { createApexError, HttpStatus } from "@/services/error.service";
const service = Container.get(UserStatsService)
export const userStatsRouter = honoWithJwt()
/* Nao deveria ter como criar um user stats sem user */
.post('/', zValidator('json', userStatsSchemas.userStatsInputSchema),
async (c) => {
try{
const input = await c.req.valid('json')
const user_stats = userStatsSchemas.userStatsDtoSchema.parse(
await service.create(input)
)
return c.json({ user_stats})
} catch (e) {
return c.json(
createApexError({
status: 'error',
message: 'could not create user stats',
code: HttpStatus.BAD_REQUEST,
path: c.req.routePath,
suggestion: 'check the input and try again',
}),
HttpStatus.BAD_REQUEST
)
}
})
/* Tem alguma utilidade sozinha? */
.get('/:user_id', async (c) =>{
try{
const user_id = +c.req.param('user_id')
const user_stats = await service.findByUserId(user_id)
const ret = userStatsSchemas.userStatsDtoSchema.parse(user_stats)
return c.json({ user_stats: ret})
} catch(e){
return c.notFound()
}
})
/* Update é uma rota própria ou vai estar embutida nas rotas das devidas estatisticas */
.post('/update',
zValidator('json', userStatsSchemas.userStatsUpdateSchema),
async (c) => {
try{
const input = await c.req.valid('json')
const user_stats = userStatsSchemas.userStatsDtoSchema.parse(
await service.update(input)
)
return c.json({user_stats})
} catch (e) {
return c.json(
createApexError({
status: 'error',
message: 'could not update user stats',
code: HttpStatus.BAD_REQUEST,
path: c.req.routePath,
suggestion: 'check the input and try again',
}),
HttpStatus.BAD_REQUEST
)
}
})
/* Nao deveria ter como deletar um user stats sozinho */
.post('/delete/:id',
zValidator('json', userStatsSchemas.userStatsUpdateSchema),
async (c) =>{
try{
const id: number = +c.req.param('id')
const user_stats = userStatsSchemas.userStatsDtoSchema.parse(
await service.delete(id)
)
return c.json(user_stats)
} catch (e){
return c.json(
createApexError({
status: 'error',
message: 'could delete user stats',
code: HttpStatus.BAD_REQUEST,
path: c.req.routePath,
suggestion: 'check the input and try again',
}),
HttpStatus.BAD_REQUEST
)
}
})
\ No newline at end of file
......@@ -6,8 +6,11 @@ import { zValidator } from '@hono/zod-validator'
import { honoWithJwt } from '..'
import { Hono } from 'hono'
import { createApexError, HttpStatus } from '@/services/error.service'
import { userStatsSchemas } from '@/db/schema/user-stats.model'
import { UserStatsService } from '@/services/user-stats.service'
const service = Container.get(UserService)
const userStatsService = Container.get(UserStatsService)
export const signUpRouter = new Hono()
.post('/',
......@@ -15,12 +18,18 @@ export const signUpRouter = new Hono()
async (c) => {
try {
const input = await c.req.valid('json')
const user = userSchemas.userDtoSchema.parse(
await service.create(input)
)
return c.json({ user })
const user_stats_schema = {
user_id: user.id
}
const user_stats = userStatsSchemas.userStatsDtoSchema.parse(
await userStatsService.create(user_stats_schema)
)
return c.json({ user, user_stats })
} catch (e) {
return c.text('could not create')
}
......
import type db from "@/db";
import { UserStatsRepo } from "@/db/repo/user-stats.repo";
import type { UserStatsInput, UserStatsModel, UserStatsUpdate } from "@/db/schema/user-stats.model";
import { Inject, Service } from "typedi";
@Service()
export class UserStatsService{
@Inject()
private readonly repo: UserStatsRepo
async findById(
userStats_id: UserStatsModel['id']
): Promise<UserStatsModel | null>{
return await this.repo.findById(userStats_id)
}
async findByUserId(
userStats_user_id: UserStatsModel['user_id']
): Promise<UserStatsModel | null>{
return await this.repo.findByUserId(userStats_user_id)
}
async create(
userStats: UserStatsInput, tx?: db
): Promise<UserStatsModel>{
return this.repo.create(userStats, tx)
}
async update(
userStats: UserStatsUpdate
): Promise<UserStatsModel>{
return this.repo.update(userStats)
}
async delete(
userStats: UserStatsModel['id']
): Promise<UserStatsModel>{
return this.repo.delete(userStats)
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment