@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict/>
|
<dict>
|
||||||
|
<key>UIAppFonts</key>
|
||||||
|
<array>
|
||||||
|
<string>samurai.ttf</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "doushouqi-cat.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "doushouqi-dog.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 5.7 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "doushouqi-elephant.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 5.8 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "doushouqi-leopard.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "doushouqi-lion.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 8.7 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "doushouqi-rat.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 8.2 KiB |
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "doushouqi-wolf.svg",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 6.8 KiB |
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// SystemIcons.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by Rémi REGNAULT on 28/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct SystemIcons {
|
||||||
|
static let DarkTheme = "moon"
|
||||||
|
static let LightTheme = "sun.max"
|
||||||
|
static let SoundOn = "speaker.2"
|
||||||
|
static let SoundOff = "speaker.slash"
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// Fonts.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by Rémi REGNAULT on 27/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public struct Fonts {
|
||||||
|
static let title = "samurai"
|
||||||
|
}
|
@ -0,0 +1,150 @@
|
|||||||
|
//
|
||||||
|
// AddPlayerView.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by étudiant on 28/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
struct AddPlayerView: View {
|
||||||
|
@Binding var isPresented: Bool
|
||||||
|
@Binding var players: [Player]
|
||||||
|
@State private var playerName: String = ""
|
||||||
|
@State private var showAlert = false
|
||||||
|
@State private var showImagePicker = false
|
||||||
|
@State private var profileImage: UIImage? = nil
|
||||||
|
@State private var profileImagePath: String = ""
|
||||||
|
@State private var imagePickerSourceType: UIImagePickerController.SourceType = .photoLibrary
|
||||||
|
@State private var showActionSheet = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 20) {
|
||||||
|
Text("Add New Player")
|
||||||
|
.font(.headline)
|
||||||
|
|
||||||
|
TextField("Player Name", text: $playerName)
|
||||||
|
.padding()
|
||||||
|
.background(Color(.systemGray6))
|
||||||
|
.cornerRadius(10)
|
||||||
|
|
||||||
|
if let profileImage = profileImage {
|
||||||
|
Image(uiImage: profileImage)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else {
|
||||||
|
Button(action: {
|
||||||
|
showActionSheet = true
|
||||||
|
}) {
|
||||||
|
Text("Select Profile Photo")
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding()
|
||||||
|
.background(Color.blue)
|
||||||
|
.cornerRadius(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Button(action: {
|
||||||
|
if players.contains(where: { $0.name.lowercased() == playerName.lowercased() }) {
|
||||||
|
showAlert = true
|
||||||
|
} else {
|
||||||
|
if let image = profileImage, let imageData = image.jpegData(compressionQuality: 0.8) {
|
||||||
|
let filename = UUID().uuidString + ".jpg"
|
||||||
|
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
|
||||||
|
let documentsDirectory = paths[0]
|
||||||
|
let fileURL = documentsDirectory.appendingPathComponent(filename)
|
||||||
|
try? imageData.write(to: fileURL)
|
||||||
|
profileImagePath = fileURL.path
|
||||||
|
}
|
||||||
|
let newPlayer = Player(name: playerName, wins: 0, losses: 0, photo: profileImagePath)
|
||||||
|
players.append(newPlayer)
|
||||||
|
isPresented = false
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Text("Add")
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding()
|
||||||
|
.background(Color.blue)
|
||||||
|
.cornerRadius(10)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
isPresented = false
|
||||||
|
}) {
|
||||||
|
Text("Cancel")
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding()
|
||||||
|
.background(Color.red)
|
||||||
|
.cornerRadius(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.frame(maxWidth: 300)
|
||||||
|
.background(Color.white)
|
||||||
|
.cornerRadius(20)
|
||||||
|
.shadow(radius: 10)
|
||||||
|
.alert(isPresented: $showAlert) {
|
||||||
|
Alert(title: Text("Error"), message: Text("Player already exists."), dismissButton: .default(Text("OK")))
|
||||||
|
}
|
||||||
|
.actionSheet(isPresented: $showActionSheet) {
|
||||||
|
ActionSheet(title: Text("Select Photo"), message: Text("Choose a photo from the library or take a new one."), buttons: [
|
||||||
|
.default(Text("Photo Library")) {
|
||||||
|
imagePickerSourceType = .photoLibrary
|
||||||
|
showImagePicker = true
|
||||||
|
},
|
||||||
|
.default(Text("Camera")) {
|
||||||
|
imagePickerSourceType = .camera
|
||||||
|
showImagePicker = true
|
||||||
|
},
|
||||||
|
.cancel()
|
||||||
|
])
|
||||||
|
}
|
||||||
|
.sheet(isPresented: $showImagePicker) {
|
||||||
|
ImagePicker(image: $profileImage, sourceType: imagePickerSourceType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ImagePicker: UIViewControllerRepresentable {
|
||||||
|
@Binding var image: UIImage?
|
||||||
|
var sourceType: UIImagePickerController.SourceType
|
||||||
|
|
||||||
|
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
|
||||||
|
var parent: ImagePicker
|
||||||
|
|
||||||
|
init(parent: ImagePicker) {
|
||||||
|
self.parent = parent
|
||||||
|
}
|
||||||
|
|
||||||
|
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
|
||||||
|
if let uiImage = info[.originalImage] as? UIImage {
|
||||||
|
parent.image = uiImage
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.presentationMode.wrappedValue.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
||||||
|
parent.presentationMode.wrappedValue.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCoordinator() -> Coordinator {
|
||||||
|
Coordinator(parent: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Environment(\.presentationMode) var presentationMode
|
||||||
|
|
||||||
|
func makeUIViewController(context: Context) -> UIImagePickerController {
|
||||||
|
let picker = UIImagePickerController()
|
||||||
|
picker.delegate = context.coordinator
|
||||||
|
picker.sourceType = sourceType
|
||||||
|
return picker
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// PlayerRow.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by étudiant on 26/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct PlayerRow: View {
|
||||||
|
var player: Player
|
||||||
|
@Binding var players: [Player]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
if let image = UIImage(contentsOfFile: player.photo) {
|
||||||
|
Image(uiImage: image)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 50, height: 50)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else {
|
||||||
|
Image(systemName: "person.circle.fill")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 50, height: 50)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
}
|
||||||
|
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(player.name)
|
||||||
|
.font(.headline)
|
||||||
|
Text("Victoires : \(player.wins) Défaites : \(player.losses)")
|
||||||
|
.font(.subheadline)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
Button(action: {
|
||||||
|
// Action pour éditer le joueur
|
||||||
|
}) {
|
||||||
|
Image(systemName: "pencil")
|
||||||
|
.foregroundColor(.black)
|
||||||
|
}
|
||||||
|
Button(action: {
|
||||||
|
|
||||||
|
}) {
|
||||||
|
Image(systemName: "trash")
|
||||||
|
.foregroundColor(.red)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.background(Color.white)
|
||||||
|
.cornerRadius(10)
|
||||||
|
.shadow(radius: 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// CustomSwitchButton.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by etudiant on 27/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct CustomSwitchButton: View {
|
||||||
|
|
||||||
|
// Boolean
|
||||||
|
@Binding var IsOn: Bool
|
||||||
|
|
||||||
|
// Image when Off
|
||||||
|
var imgSystemNameIsOff: String
|
||||||
|
var imgIsOffWidth: CGFloat = 25
|
||||||
|
var imgIsOffHeight: CGFloat = 25
|
||||||
|
|
||||||
|
// Image when Off
|
||||||
|
var imgSystemNameIsOn: String
|
||||||
|
var imgIsOnWidth: CGFloat = 25
|
||||||
|
var imgIsOnHeight: CGFloat = 25
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
VStack {
|
||||||
|
if (!IsOn) {
|
||||||
|
Image(systemName: imgSystemNameIsOff)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: imgIsOffWidth, height: imgIsOffHeight)
|
||||||
|
}
|
||||||
|
}.frame(width: imgIsOffWidth, height: imgIsOffHeight)
|
||||||
|
|
||||||
|
Toggle("isOn", isOn: $IsOn)
|
||||||
|
.labelsHidden()
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
if (IsOn) {
|
||||||
|
Image(systemName: imgSystemNameIsOn)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: imgIsOnWidth, height: imgIsOnHeight)
|
||||||
|
}
|
||||||
|
}.frame(width: imgIsOffWidth, height: imgIsOffHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//struct CustomSwitchButton_Previews: PreviewProvider {
|
||||||
|
// static var previews: some View {
|
||||||
|
// @State var isOn: Bool = false
|
||||||
|
// CustomSwitchButton(IsOn: $isOn, imgNameIsOff: AppImages.TitleImage, imgNameIsOn: AppImages.TitleImage)
|
||||||
|
// }
|
||||||
|
//}
|
@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// TitlePageFrame.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by Rémi REGNAULT on 16/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct TitlePageFrame: View {
|
||||||
|
|
||||||
|
// Text Params
|
||||||
|
var Text: String
|
||||||
|
|
||||||
|
// Image Params
|
||||||
|
var ImageWidth: CGFloat = 200
|
||||||
|
var ImageHeight: CGFloat = 200
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
ZStack {
|
||||||
|
Image(AppImages.TitleImage)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: ImageWidth, height: ImageHeight)
|
||||||
|
|
||||||
|
SwiftUI.Text(self.Text)
|
||||||
|
.textStyle(CustomTextStyles.Title)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TitlePageFrame_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
TitlePageFrame(Text: "DouShouQi")
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +0,0 @@
|
|||||||
//
|
|
||||||
// MusicPlayer.swift
|
|
||||||
// DouShouQi_App
|
|
||||||
//
|
|
||||||
// Created by étudiant on 26/05/2024.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
@ -1,98 +0,0 @@
|
|||||||
//
|
|
||||||
// SwiftUIView.swift
|
|
||||||
// DouShouQi_App
|
|
||||||
//
|
|
||||||
// Created by étudiant on 22/05/2024.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct SwiftUIView: View {
|
|
||||||
var body: some View {
|
|
||||||
VStack {
|
|
||||||
TitlePageFrame(Text: "DOU SHOU QI", ImageWidth: 200, ImageHeight: 200)
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
VStack {
|
|
||||||
HStack{
|
|
||||||
VStack {
|
|
||||||
Button(action: {
|
|
||||||
// Action du bouton
|
|
||||||
}, label: {
|
|
||||||
Text("Play".uppercased())
|
|
||||||
.font(.headline)
|
|
||||||
.fontWeight(.semibold)
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: 50)
|
|
||||||
.background(
|
|
||||||
Color.red
|
|
||||||
)
|
|
||||||
.cornerRadius(0)
|
|
||||||
})
|
|
||||||
.frame(width: UIScreen.main.bounds.width / 1.7)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
// Action du bouton
|
|
||||||
}, label: {
|
|
||||||
Text("Historique".uppercased())
|
|
||||||
.font(.headline)
|
|
||||||
.fontWeight(.semibold)
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: 50)
|
|
||||||
.background(
|
|
||||||
Color.red
|
|
||||||
)
|
|
||||||
.cornerRadius(0)
|
|
||||||
})
|
|
||||||
.frame(width: UIScreen.main.bounds.width / 1.7)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
// Action du bouton
|
|
||||||
}, label: {
|
|
||||||
Text("Best scores".uppercased())
|
|
||||||
.font(.headline)
|
|
||||||
.fontWeight(.semibold)
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: 50)
|
|
||||||
.background(
|
|
||||||
Color.red
|
|
||||||
)
|
|
||||||
.cornerRadius(0)
|
|
||||||
})
|
|
||||||
.frame(width: UIScreen.main.bounds.width / 1.7)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
// Action du bouton
|
|
||||||
}, label: {
|
|
||||||
Text("Players".uppercased())
|
|
||||||
.font(.headline)
|
|
||||||
.fontWeight(.semibold)
|
|
||||||
.foregroundColor(.white)
|
|
||||||
.frame(maxWidth: .infinity, maxHeight: 50)
|
|
||||||
.background(
|
|
||||||
Color.red
|
|
||||||
)
|
|
||||||
.cornerRadius(0)
|
|
||||||
})
|
|
||||||
.frame(width: UIScreen.main.bounds.width / 1.7)
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.horizontal, 10)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct SwiftUIView_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
SwiftUIView()
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// MainMenuView.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by Rémi REGNAULT on 16/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct MainMenuView: View {
|
||||||
|
|
||||||
|
@State private var showSplash = true
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
VStack {
|
||||||
|
if showSplash {
|
||||||
|
SplashScreenView()
|
||||||
|
.transition(.opacity)
|
||||||
|
.animation(.easeOut(duration: 3), value: showSplash)
|
||||||
|
.onAppear {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 8) {
|
||||||
|
withAnimation {
|
||||||
|
showSplash = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TitlePageFrame(Text: "DOU SHOU QI", ImageWidth: 200, ImageHeight: 200)
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
VStack(spacing: 25) {
|
||||||
|
MainMenuButton(text: "Play", destination: ScoreBoardView(), sound: "TitleScreenButtonSound", topRightCorner: 10, bottomRightCorner: 10)
|
||||||
|
MainMenuButton(text: "Historique", destination: HistoricView(), sound: "TitleScreenButtonSound", topRightCorner: 10, bottomRightCorner: 10)
|
||||||
|
MainMenuButton(text: "Best Scores", destination: ScoreBoardView(), sound: "TitleScreenButtonSound", topRightCorner: 10, bottomRightCorner: 10)
|
||||||
|
MainMenuButton(text: "Players", destination: PlayersView(), sound: "TitleScreenButtonSound", topRightCorner: 10, bottomRightCorner: 10)
|
||||||
|
MainMenuButton(text: "Settings", destination: SettingsView(), sound: "TitleScreenButtonSound", topRightCorner: 10, bottomRightCorner: 10)
|
||||||
|
}
|
||||||
|
Image(AppImages.SemiLion)
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 200, height: 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
HStack {
|
||||||
|
Text("Copyright @")
|
||||||
|
.font(.headline)
|
||||||
|
.frame(alignment: .trailing)
|
||||||
|
|
||||||
|
Text("Dou Shou Qi Team")
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Text("2024")
|
||||||
|
.frame(alignment: .trailing)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.background(Color.white)
|
||||||
|
.overlay(
|
||||||
|
Rectangle()
|
||||||
|
.stroke(Color.black, lineWidth: 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
.onAppear {
|
||||||
|
MusicPlayer.shared.playBackgroundMusic(music: "TitleScreenMusic")
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
MusicPlayer.shared.stopBackgroundMusic()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MainMenuView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
MainMenuView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// SettingsView.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by etudiant on 27/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
extension String : Identifiable {
|
||||||
|
public var id: Self { return self }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SettingsView: View {
|
||||||
|
|
||||||
|
@State private var theme = false
|
||||||
|
@State private var choice = "English"
|
||||||
|
@State private var sound = true
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
TitlePageFrame(Text: "Settings")
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
Divider()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text("Theme")
|
||||||
|
.font(.headline)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
CustomSwitchButton(IsOn: $theme, imgSystemNameIsOff: SystemIcons.LightTheme, imgSystemNameIsOn: SystemIcons.DarkTheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text("Language")
|
||||||
|
.font(.headline)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Picker("Sort", selection: $choice) {
|
||||||
|
ForEach(["English", "Français", "Español"]) {
|
||||||
|
Text($0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pickerStyle(.menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text("Theme")
|
||||||
|
.font(.headline)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
CustomSwitchButton(IsOn: $sound, imgSystemNameIsOff: SystemIcons.SoundOff, imgSystemNameIsOn: SystemIcons.SoundOn)
|
||||||
|
}
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
}
|
||||||
|
.padding(20)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SettingsView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
SettingsView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// SplashScreenView.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by étudiant on 27/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct SplashScreenView: View {
|
||||||
|
var body: some View {
|
||||||
|
TitlePageFrame(Text: "DOU SHOU QI", ImageWidth: 200, ImageHeight: 200)
|
||||||
|
.onAppear {
|
||||||
|
playSound(named: "SplashScreenSound")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SplashScreenView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
SplashScreenView()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// PlayersView.swift
|
||||||
|
// DouShouQi_App
|
||||||
|
//
|
||||||
|
// Created by étudiant on 26/05/2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// Modèle de données pour un joueur
|
||||||
|
struct Player: Identifiable {
|
||||||
|
var id = UUID()
|
||||||
|
var name: String
|
||||||
|
var wins: Int
|
||||||
|
var losses: Int
|
||||||
|
var photo: String
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exemple de vue pour l'interface utilisateur des joueurs
|
||||||
|
struct PlayersView: View {
|
||||||
|
// Liste de joueurs pour l'exemple
|
||||||
|
@State private var players = [
|
||||||
|
Player(name: "Rayhan", wins: 7, losses: 6, photo: "shrek"),
|
||||||
|
Player(name: "Remi", wins: 7, losses: 2, photo: "shrek"),
|
||||||
|
Player(name: "Nathan", wins: 14, losses: 5, photo: "shrek")
|
||||||
|
]
|
||||||
|
|
||||||
|
@State private var searchText = ""
|
||||||
|
@State private var showingPopup = false
|
||||||
|
@State private var newPlayerName = ""
|
||||||
|
|
||||||
|
var filteredPlayers: [Player] {
|
||||||
|
if searchText.isEmpty {
|
||||||
|
return players
|
||||||
|
} else {
|
||||||
|
return players.filter { $0.name.lowercased().contains(searchText.lowercased()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
VStack {
|
||||||
|
|
||||||
|
TitlePageFrame(Text: "PLAYERS", ImageWidth: 200, ImageHeight: 200)
|
||||||
|
|
||||||
|
|
||||||
|
SearchBar(text: $searchText)
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
List {
|
||||||
|
ForEach(groupedPlayers.keys.sorted(), id: \.self) { key in
|
||||||
|
Section(header: Text(key)) {
|
||||||
|
ForEach(groupedPlayers[key]!) { player in
|
||||||
|
PlayerRow(player: player, players: $players)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
showingPopup = true
|
||||||
|
}) {
|
||||||
|
Text("Add a player")
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.padding()
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.background(Color.red)
|
||||||
|
.cornerRadius(10)
|
||||||
|
.padding(.horizontal)
|
||||||
|
}
|
||||||
|
.padding(.bottom)
|
||||||
|
.sheet(isPresented: $showingPopup) {
|
||||||
|
AddPlayerView(isPresented: $showingPopup, players: $players)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var groupedPlayers: [String: [Player]] {
|
||||||
|
Dictionary(grouping: filteredPlayers) { player in
|
||||||
|
String(player.name.prefix(1)).uppercased()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vue pour la barre de recherche
|
||||||
|
struct SearchBar: UIViewRepresentable {
|
||||||
|
@Binding var text: String
|
||||||
|
|
||||||
|
class Coordinator: NSObject, UISearchBarDelegate {
|
||||||
|
@Binding var text: String
|
||||||
|
|
||||||
|
init(text: Binding<String>) {
|
||||||
|
_text = text
|
||||||
|
}
|
||||||
|
|
||||||
|
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
|
||||||
|
text = searchText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeCoordinator() -> Coordinator {
|
||||||
|
return Coordinator(text: $text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeUIView(context: Context) -> UISearchBar {
|
||||||
|
let searchBar = UISearchBar(frame: .zero)
|
||||||
|
searchBar.delegate = context.coordinator
|
||||||
|
return searchBar
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIView(_ uiView: UISearchBar, context: Context) {
|
||||||
|
uiView.text = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct PlayersPageView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
PlayersView()
|
||||||
|
}
|
||||||
|
}
|