New: Hero Page und Navigation
This commit is contained in:
@ -0,0 +1,7 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "Nachhilfeangebot" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"subject" TEXT NOT NULL,
|
||||
"currentClass" TEXT NOT NULL,
|
||||
"cost" DECIMAL NOT NULL
|
||||
);
|
22
api/db/migrations/20241004122139_created_at/migration.sql
Normal file
22
api/db/migrations/20241004122139_created_at/migration.sql
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- Added the required column `userId` to the `Nachhilfeangebot` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- RedefineTables
|
||||
PRAGMA defer_foreign_keys=ON;
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_Nachhilfeangebot" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"subject" TEXT NOT NULL,
|
||||
"currentClass" TEXT NOT NULL,
|
||||
"cost" DECIMAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
CONSTRAINT "Nachhilfeangebot_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
INSERT INTO "new_Nachhilfeangebot" ("cost", "currentClass", "id", "subject") SELECT "cost", "currentClass", "id", "subject" FROM "Nachhilfeangebot";
|
||||
DROP TABLE "Nachhilfeangebot";
|
||||
ALTER TABLE "new_Nachhilfeangebot" RENAME TO "Nachhilfeangebot";
|
||||
PRAGMA foreign_keys=ON;
|
||||
PRAGMA defer_foreign_keys=OFF;
|
@ -24,18 +24,19 @@ model UserExample {
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
email String @unique
|
||||
id Int @id @default(autoincrement())
|
||||
email String @unique
|
||||
firstName String?
|
||||
lastName String?
|
||||
hashedPassword String?
|
||||
salt String?
|
||||
identites Identity[]
|
||||
resetToken String?
|
||||
resetTokenExpiresAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
roles String @default("user")
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
roles String @default("user")
|
||||
identites Identity[]
|
||||
Nachhilfeangebot Nachhilfeangebot[]
|
||||
}
|
||||
|
||||
model Identity {
|
||||
@ -61,3 +62,12 @@ model Post {
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Nachhilfeangebot {
|
||||
id Int @id @default(autoincrement())
|
||||
subject String
|
||||
currentClass String
|
||||
cost Decimal
|
||||
userId Int
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ export const handler = async (
|
||||
context: Context
|
||||
) => {
|
||||
const forgotPasswordOptions: DbAuthHandlerOptions['forgotPassword'] = {
|
||||
enabled: false,
|
||||
// handler() is invoked after verifying that a user was found with the given
|
||||
// username. This is where you can send the user an email with a link to
|
||||
// reset their password. With the default dbAuth routes and field names, the
|
||||
@ -75,6 +76,7 @@ export const handler = async (
|
||||
// didn't validate their email yet), throw an error and it will be returned
|
||||
// by the `logIn()` function from `useAuth()` in the form of:
|
||||
// `{ message: 'Error message' }`
|
||||
enabled: false,
|
||||
handler: (user) => {
|
||||
return user
|
||||
},
|
||||
@ -100,6 +102,7 @@ export const handler = async (
|
||||
handler: (_user) => {
|
||||
return true
|
||||
},
|
||||
enabled: false,
|
||||
|
||||
// If `false` then the new password MUST be different from the current one
|
||||
allowReusedPassword: true,
|
||||
@ -139,6 +142,7 @@ export const handler = async (
|
||||
//
|
||||
// If this returns anything else, it will be returned by the
|
||||
// `signUp()` function in the form of: `{ message: 'String here' }`.
|
||||
enabled: false,
|
||||
handler: ({
|
||||
username,
|
||||
hashedPassword,
|
||||
|
36
api/src/graphql/identities.sdl.ts
Normal file
36
api/src/graphql/identities.sdl.ts
Normal file
@ -0,0 +1,36 @@
|
||||
export const schema = gql`
|
||||
type Identity {
|
||||
id: Int!
|
||||
provider: String!
|
||||
# uid: String!
|
||||
userId: Int!
|
||||
user: User!
|
||||
# accessToken: String
|
||||
# scope: String
|
||||
lastLoginAt: DateTime!
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
type Query {
|
||||
identities: [Identity!]! @requireAuth
|
||||
}
|
||||
|
||||
input CreateIdentityInput {
|
||||
provider: String!
|
||||
uid: String!
|
||||
userId: Int!
|
||||
accessToken: String
|
||||
scope: String
|
||||
lastLoginAt: DateTime!
|
||||
}
|
||||
|
||||
input UpdateIdentityInput {
|
||||
provider: String
|
||||
uid: String
|
||||
userId: Int
|
||||
accessToken: String
|
||||
scope: String
|
||||
lastLoginAt: DateTime
|
||||
}
|
||||
`
|
37
api/src/graphql/nachhilfeangebots.sdl.ts
Normal file
37
api/src/graphql/nachhilfeangebots.sdl.ts
Normal file
@ -0,0 +1,37 @@
|
||||
export const schema = gql`
|
||||
type Nachhilfeangebot {
|
||||
id: Int!
|
||||
subject: String!
|
||||
currentClass: String!
|
||||
cost: Float!
|
||||
user: User!
|
||||
}
|
||||
|
||||
type Query {
|
||||
nachhilfeangebots: [Nachhilfeangebot!]! @requireAuth
|
||||
nachhilfeangebot(id: Int!): Nachhilfeangebot @requireAuth
|
||||
}
|
||||
|
||||
input CreateNachhilfeangebotInput {
|
||||
subject: String!
|
||||
currentClass: String!
|
||||
cost: Float!
|
||||
}
|
||||
|
||||
input UpdateNachhilfeangebotInput {
|
||||
subject: String
|
||||
currentClass: String
|
||||
cost: Float
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createNachhilfeangebot(
|
||||
input: CreateNachhilfeangebotInput!
|
||||
): Nachhilfeangebot! @requireAuth
|
||||
updateNachhilfeangebot(
|
||||
id: Int!
|
||||
input: UpdateNachhilfeangebotInput!
|
||||
): Nachhilfeangebot! @requireAuth
|
||||
deleteNachhilfeangebot(id: Int!): Nachhilfeangebot! @requireAuth
|
||||
}
|
||||
`
|
43
api/src/graphql/users.sdl.ts
Normal file
43
api/src/graphql/users.sdl.ts
Normal file
@ -0,0 +1,43 @@
|
||||
export const schema = gql`
|
||||
type User {
|
||||
id: Int!
|
||||
email: String!
|
||||
firstName: String
|
||||
lastName: String
|
||||
# hashedPassword: String
|
||||
# salt: String
|
||||
# resetToken: String
|
||||
# resetTokenExpiresAt: DateTime
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
roles: String!
|
||||
identites: [Identity]!
|
||||
Nachhilfeangebot: [Nachhilfeangebot]!
|
||||
}
|
||||
|
||||
type Query {
|
||||
users: [User!]! @requireAuth
|
||||
}
|
||||
|
||||
input CreateUserInput {
|
||||
email: String!
|
||||
firstName: String
|
||||
lastName: String
|
||||
hashedPassword: String
|
||||
salt: String
|
||||
resetToken: String
|
||||
resetTokenExpiresAt: DateTime
|
||||
roles: String!
|
||||
}
|
||||
|
||||
input UpdateUserInput {
|
||||
email: String
|
||||
firstName: String
|
||||
lastName: String
|
||||
hashedPassword: String
|
||||
salt: String
|
||||
resetToken: String
|
||||
resetTokenExpiresAt: DateTime
|
||||
roles: String
|
||||
}
|
||||
`
|
@ -36,7 +36,13 @@ export const getCurrentUser = async (session: Decoded) => {
|
||||
|
||||
return await db.user.findUnique({
|
||||
where: { id: session.id },
|
||||
select: { id: true, email: true, roles: true },
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
roles: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
35
api/src/services/identities/identities.scenarios.ts
Normal file
35
api/src/services/identities/identities.scenarios.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import type { Prisma, Identity } from '@prisma/client'
|
||||
import type { ScenarioData } from '@redwoodjs/testing/api'
|
||||
|
||||
export const standard = defineScenario<Prisma.IdentityCreateArgs>({
|
||||
identity: {
|
||||
one: {
|
||||
data: {
|
||||
provider: 'String',
|
||||
uid: 'String',
|
||||
updatedAt: '2024-10-04T12:47:55.457Z',
|
||||
user: {
|
||||
create: {
|
||||
email: 'String3211260',
|
||||
updatedAt: '2024-10-04T12:47:55.457Z',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
two: {
|
||||
data: {
|
||||
provider: 'String',
|
||||
uid: 'String',
|
||||
updatedAt: '2024-10-04T12:47:55.457Z',
|
||||
user: {
|
||||
create: {
|
||||
email: 'String2559297',
|
||||
updatedAt: '2024-10-04T12:47:55.457Z',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export type StandardScenario = ScenarioData<Identity, 'identity'>
|
18
api/src/services/identities/identities.test.ts
Normal file
18
api/src/services/identities/identities.test.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import type { Identity } from '@prisma/client'
|
||||
|
||||
import { identities } from './identities'
|
||||
import type { StandardScenario } from './identities.scenarios'
|
||||
|
||||
// Generated boilerplate tests do not account for all circumstances
|
||||
// and can fail without adjustments, e.g. Float.
|
||||
// Please refer to the RedwoodJS Testing Docs:
|
||||
// https://redwoodjs.com/docs/testing#testing-services
|
||||
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations
|
||||
|
||||
describe('identities', () => {
|
||||
scenario('returns all identities', async (scenario: StandardScenario) => {
|
||||
const result = await identities()
|
||||
|
||||
expect(result.length).toEqual(Object.keys(scenario.identity).length)
|
||||
})
|
||||
})
|
19
api/src/services/identities/identities.ts
Normal file
19
api/src/services/identities/identities.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import type { QueryResolvers, IdentityRelationResolvers } from 'types/graphql'
|
||||
|
||||
import { db } from 'src/lib/db'
|
||||
|
||||
export const identities: QueryResolvers['identities'] = () => {
|
||||
return db.identity.findMany()
|
||||
}
|
||||
|
||||
export const identity: QueryResolvers['identity'] = ({ id }) => {
|
||||
return db.identity.findUnique({
|
||||
where: { id },
|
||||
})
|
||||
}
|
||||
|
||||
export const Identity: IdentityRelationResolvers = {
|
||||
user: (_obj, { root }) => {
|
||||
return db.identity.findUnique({ where: { id: root?.id } }).user()
|
||||
},
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import type { Prisma, Nachhilfeangebot } from '@prisma/client'
|
||||
import type { ScenarioData } from '@redwoodjs/testing/api'
|
||||
|
||||
export const standard = defineScenario<Prisma.NachhilfeangebotCreateArgs>({
|
||||
nachhilfeangebot: {
|
||||
one: {
|
||||
data: {
|
||||
subject: 'String',
|
||||
currentClass: 'String',
|
||||
cost: 9626711.68060984,
|
||||
},
|
||||
},
|
||||
two: {
|
||||
data: {
|
||||
subject: 'String',
|
||||
currentClass: 'String',
|
||||
cost: 3400746.9395209556,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export type StandardScenario = ScenarioData<
|
||||
Nachhilfeangebot,
|
||||
'nachhilfeangebot'
|
||||
>
|
75
api/src/services/nachhilfeangebots/nachhilfeangebots.test.ts
Normal file
75
api/src/services/nachhilfeangebots/nachhilfeangebots.test.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { Prisma, Nachhilfeangebot } from '@prisma/client'
|
||||
|
||||
import {
|
||||
nachhilfeangebots,
|
||||
nachhilfeangebot,
|
||||
createNachhilfeangebot,
|
||||
updateNachhilfeangebot,
|
||||
deleteNachhilfeangebot,
|
||||
} from './nachhilfeangebots'
|
||||
import type { StandardScenario } from './nachhilfeangebots.scenarios'
|
||||
|
||||
// Generated boilerplate tests do not account for all circumstances
|
||||
// and can fail without adjustments, e.g. Float.
|
||||
// Please refer to the RedwoodJS Testing Docs:
|
||||
// https://redwoodjs.com/docs/testing#testing-services
|
||||
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations
|
||||
|
||||
describe('nachhilfeangebots', () => {
|
||||
scenario(
|
||||
'returns all nachhilfeangebots',
|
||||
async (scenario: StandardScenario) => {
|
||||
const result = await nachhilfeangebots()
|
||||
|
||||
expect(result.length).toEqual(
|
||||
Object.keys(scenario.nachhilfeangebot).length
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
scenario(
|
||||
'returns a single nachhilfeangebot',
|
||||
async (scenario: StandardScenario) => {
|
||||
const result = await nachhilfeangebot({
|
||||
id: scenario.nachhilfeangebot.one.id,
|
||||
})
|
||||
|
||||
expect(result).toEqual(scenario.nachhilfeangebot.one)
|
||||
}
|
||||
)
|
||||
|
||||
scenario('creates a nachhilfeangebot', async () => {
|
||||
const result = await createNachhilfeangebot({
|
||||
input: {
|
||||
subject: 'String',
|
||||
currentClass: 'String',
|
||||
cost: 3443924.824820386,
|
||||
},
|
||||
})
|
||||
|
||||
expect(result.subject).toEqual('String')
|
||||
expect(result.currentClass).toEqual('String')
|
||||
expect(result.cost).toEqual(new Prisma.Decimal(3443924.824820386))
|
||||
})
|
||||
|
||||
scenario('updates a nachhilfeangebot', async (scenario: StandardScenario) => {
|
||||
const original = (await nachhilfeangebot({
|
||||
id: scenario.nachhilfeangebot.one.id,
|
||||
})) as Nachhilfeangebot
|
||||
const result = await updateNachhilfeangebot({
|
||||
id: original.id,
|
||||
input: { subject: 'String2' },
|
||||
})
|
||||
|
||||
expect(result.subject).toEqual('String2')
|
||||
})
|
||||
|
||||
scenario('deletes a nachhilfeangebot', async (scenario: StandardScenario) => {
|
||||
const original = (await deleteNachhilfeangebot({
|
||||
id: scenario.nachhilfeangebot.one.id,
|
||||
})) as Nachhilfeangebot
|
||||
const result = await nachhilfeangebot({ id: original.id })
|
||||
|
||||
expect(result).toEqual(null)
|
||||
})
|
||||
})
|
43
api/src/services/nachhilfeangebots/nachhilfeangebots.ts
Normal file
43
api/src/services/nachhilfeangebots/nachhilfeangebots.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import type { QueryResolvers, MutationResolvers } from 'types/graphql'
|
||||
|
||||
import { db } from 'src/lib/db'
|
||||
|
||||
export const nachhilfeangebots: QueryResolvers['nachhilfeangebots'] = () => {
|
||||
return db.nachhilfeangebot.findMany()
|
||||
}
|
||||
|
||||
export const nachhilfeangebot: QueryResolvers['nachhilfeangebot'] = ({
|
||||
id,
|
||||
}) => {
|
||||
return {
|
||||
...db.nachhilfeangebot.findUnique({
|
||||
where: { id },
|
||||
}),
|
||||
user: db.nachhilfeangebot.findUnique({ where: { id } }).user(),
|
||||
}
|
||||
}
|
||||
|
||||
export const createNachhilfeangebot: MutationResolvers['createNachhilfeangebot'] =
|
||||
({ input }) => {
|
||||
return db.nachhilfeangebot.create({
|
||||
data: {
|
||||
...input,
|
||||
userId: context.currentUser.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const updateNachhilfeangebot: MutationResolvers['updateNachhilfeangebot'] =
|
||||
({ id, input }) => {
|
||||
return db.nachhilfeangebot.update({
|
||||
data: input,
|
||||
where: { id },
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteNachhilfeangebot: MutationResolvers['deleteNachhilfeangebot'] =
|
||||
({ id }) => {
|
||||
return db.nachhilfeangebot.delete({
|
||||
where: { id },
|
||||
})
|
||||
}
|
15
api/src/services/users/users.scenarios.ts
Normal file
15
api/src/services/users/users.scenarios.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import type { Prisma, User } from '@prisma/client'
|
||||
import type { ScenarioData } from '@redwoodjs/testing/api'
|
||||
|
||||
export const standard = defineScenario<Prisma.UserCreateArgs>({
|
||||
user: {
|
||||
one: {
|
||||
data: { email: 'String5874784', updatedAt: '2024-10-04T12:47:22.490Z' },
|
||||
},
|
||||
two: {
|
||||
data: { email: 'String7499025', updatedAt: '2024-10-04T12:47:22.490Z' },
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export type StandardScenario = ScenarioData<User, 'user'>
|
18
api/src/services/users/users.test.ts
Normal file
18
api/src/services/users/users.test.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import type { User } from '@prisma/client'
|
||||
|
||||
import { users } from './users'
|
||||
import type { StandardScenario } from './users.scenarios'
|
||||
|
||||
// Generated boilerplate tests do not account for all circumstances
|
||||
// and can fail without adjustments, e.g. Float.
|
||||
// Please refer to the RedwoodJS Testing Docs:
|
||||
// https://redwoodjs.com/docs/testing#testing-services
|
||||
// https://redwoodjs.com/docs/testing#jest-expect-type-considerations
|
||||
|
||||
describe('users', () => {
|
||||
scenario('returns all users', async (scenario: StandardScenario) => {
|
||||
const result = await users()
|
||||
|
||||
expect(result.length).toEqual(Object.keys(scenario.user).length)
|
||||
})
|
||||
})
|
22
api/src/services/users/users.ts
Normal file
22
api/src/services/users/users.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import type { QueryResolvers, UserRelationResolvers } from 'types/graphql'
|
||||
|
||||
import { db } from 'src/lib/db'
|
||||
|
||||
export const users: QueryResolvers['users'] = () => {
|
||||
return db.user.findMany()
|
||||
}
|
||||
|
||||
export const user: QueryResolvers['user'] = ({ id }) => {
|
||||
return db.user.findUnique({
|
||||
where: { id },
|
||||
})
|
||||
}
|
||||
|
||||
export const User: UserRelationResolvers = {
|
||||
identites: (_obj, { root }) => {
|
||||
return db.user.findUnique({ where: { id: root?.id } }).identites()
|
||||
},
|
||||
Nachhilfeangebot: (_obj, { root }) => {
|
||||
return db.user.findUnique({ where: { id: root?.id } }).Nachhilfeangebot()
|
||||
},
|
||||
}
|
Reference in New Issue
Block a user